mirror of
https://github.com/danderson/netboot.git
synced 2025-08-21 14:41:20 +02:00
Add a basic regression test for DHCP parsing.
This commit is contained in:
parent
178a83f3e0
commit
fa657ad649
35
dhcp/dhcp.go
35
dhcp/dhcp.go
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
var magic = []byte{99, 130, 83, 99}
|
var magic = []byte{99, 130, 83, 99}
|
||||||
@ -68,6 +69,40 @@ type Packet struct {
|
|||||||
Options Options
|
Options Options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Packet) testString() string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
bcast := "Unicast"
|
||||||
|
if p.Broadcast {
|
||||||
|
bcast = "Broadcast"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&b, `=====
|
||||||
|
%s
|
||||||
|
%#v
|
||||||
|
%s
|
||||||
|
MAC: %s
|
||||||
|
ClientIP: %s
|
||||||
|
YourIP: %s
|
||||||
|
RelayIP: %s
|
||||||
|
|
||||||
|
BootServerIP: %s
|
||||||
|
BootServerName: %s
|
||||||
|
BootFilename: %s
|
||||||
|
|
||||||
|
Options:
|
||||||
|
`, p.Type, p.TransactionID, bcast, p.HardwareAddr, p.ClientAddr, p.YourAddr, p.RelayAddr, p.BootServerAddr, p.BootServerName, p.BootFilename)
|
||||||
|
|
||||||
|
var opts []int
|
||||||
|
for n := range p.Options {
|
||||||
|
opts = append(opts, n)
|
||||||
|
}
|
||||||
|
sort.Ints(opts)
|
||||||
|
for _, n := range opts {
|
||||||
|
fmt.Fprintf(&b, " %d: %#v\n", n, p.Options[n])
|
||||||
|
}
|
||||||
|
b.WriteString("=====\n")
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
// Marshal returns the wire encoding of p.
|
// Marshal returns the wire encoding of p.
|
||||||
func (p *Packet) Marshal() ([]byte, error) {
|
func (p *Packet) Marshal() ([]byte, error) {
|
||||||
if len(p.TransactionID) != 4 {
|
if len(p.TransactionID) != 4 {
|
||||||
|
73
dhcp/dhcp_test.go
Normal file
73
dhcp/dhcp_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package dhcp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.universe.tf/netboot/pcap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func udpFromPcap(fname string) ([][]byte, error) {
|
||||||
|
f, err := os.Open(fname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r, err := pcap.NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.LinkType != pcap.LinkEthernet {
|
||||||
|
return nil, errors.New("Pcap packets are not ethernet")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := [][]byte{}
|
||||||
|
for r.Next() {
|
||||||
|
// Assume here that the packets are UDPv4, and just chop off
|
||||||
|
// the headers in front of the UDP payload
|
||||||
|
pkt := r.Packet()
|
||||||
|
hdrLen := 14 // Ethernet header
|
||||||
|
hdrLen += int(pkt.Bytes[hdrLen]&0xF) * 4 // IP header
|
||||||
|
hdrLen += 8 // UDP header
|
||||||
|
ret = append(ret, pkt.Bytes[hdrLen:])
|
||||||
|
}
|
||||||
|
if r.Err() != nil {
|
||||||
|
return nil, r.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
rawPkts, err := udpFromPcap("testdata/dhcp.pcap")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Getting test packets from pcap: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkts bytes.Buffer
|
||||||
|
for i, rawPkt := range rawPkts {
|
||||||
|
pkt, err := Unmarshal(rawPkt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parsing DHCP packet #%d: %s", i+1, err)
|
||||||
|
}
|
||||||
|
pkts.WriteString(pkt.testString())
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedFile := "testdata/dhcp.parsed"
|
||||||
|
expected, err := ioutil.ReadFile(expectedFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Reading expected file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkts.String() != string(expected) {
|
||||||
|
if os.Getenv("UPDATE_TESTDATA") != "" {
|
||||||
|
ioutil.WriteFile(expectedFile, pkts.Bytes(), 0644)
|
||||||
|
t.Errorf("dhcp.pcap didn't decode to dhcp.parsed (updated dhcp.parsed)")
|
||||||
|
} else {
|
||||||
|
t.Fatalf("dhcp.pcap didn't decode to dhcp.parsed (rerun with UPDATE_TESTDATA=1 to get diff)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
dhcp/testdata/dhcp.parsed
vendored
Normal file
68
dhcp/testdata/dhcp.parsed
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
=====
|
||||||
|
DHCPDISCOVER
|
||||||
|
"\x9bN\x05W"
|
||||||
|
Broadcast
|
||||||
|
MAC: d0:50:99:4e:05:57
|
||||||
|
ClientIP: 0.0.0.0
|
||||||
|
YourIP: 0.0.0.0
|
||||||
|
RelayIP: 0.0.0.0
|
||||||
|
|
||||||
|
BootServerIP: 0.0.0.0
|
||||||
|
BootServerName:
|
||||||
|
BootFilename:
|
||||||
|
|
||||||
|
Options:
|
||||||
|
53: []byte{0x1}
|
||||||
|
55: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0xb, 0xc, 0xd, 0xf, 0x10, 0x11, 0x12, 0x16, 0x17, 0x1c, 0x28, 0x29, 0x2a, 0x2b, 0x32, 0x33, 0x36, 0x3a, 0x3b, 0x3c, 0x42, 0x43, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87}
|
||||||
|
57: []byte{0x4, 0xec}
|
||||||
|
60: []byte{0x50, 0x58, 0x45, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x3a, 0x41, 0x72, 0x63, 0x68, 0x3a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3a, 0x55, 0x4e, 0x44, 0x49, 0x3a, 0x30, 0x30, 0x32, 0x30, 0x30, 0x31}
|
||||||
|
93: []byte{0x0, 0x0}
|
||||||
|
94: []byte{0x1, 0x2, 0x1}
|
||||||
|
97: []byte{0x0, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, 0x9}
|
||||||
|
=====
|
||||||
|
=====
|
||||||
|
DHCPOFFER
|
||||||
|
"\x9bN\x05W"
|
||||||
|
Broadcast
|
||||||
|
MAC: d0:50:99:4e:05:57
|
||||||
|
ClientIP: 0.0.0.0
|
||||||
|
YourIP: 0.0.0.0
|
||||||
|
RelayIP: 0.0.0.0
|
||||||
|
|
||||||
|
BootServerIP: 0.0.0.0
|
||||||
|
BootServerName:
|
||||||
|
BootFilename:
|
||||||
|
|
||||||
|
Options:
|
||||||
|
43: []byte{0x6, 0x1, 0x3, 0x8, 0x7, 0x80, 0x0, 0x1, 0xc0, 0xa8, 0x10, 0xa, 0x9, 0xc, 0x80, 0x0, 0x9, 0x50, 0x69, 0x78, 0x69, 0x65, 0x63, 0x6f, 0x72, 0x65, 0xa, 0xa, 0x0, 0x50, 0x69, 0x78, 0x69, 0x65, 0x63, 0x6f, 0x72, 0x65, 0xff}
|
||||||
|
53: []byte{0x2}
|
||||||
|
54: []byte{0xc0, 0xa8, 0x10, 0xa}
|
||||||
|
60: []byte{0x50, 0x58, 0x45, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74}
|
||||||
|
97: []byte{0x0, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, 0x9}
|
||||||
|
=====
|
||||||
|
=====
|
||||||
|
DHCPOFFER
|
||||||
|
"\x9bN\x05W"
|
||||||
|
Broadcast
|
||||||
|
MAC: d0:50:99:4e:05:57
|
||||||
|
ClientIP: 0.0.0.0
|
||||||
|
YourIP: 192.168.16.12
|
||||||
|
RelayIP: 0.0.0.0
|
||||||
|
|
||||||
|
BootServerIP: 192.168.16.1
|
||||||
|
BootServerName:
|
||||||
|
BootFilename:
|
||||||
|
|
||||||
|
Options:
|
||||||
|
1: []byte{0xff, 0xff, 0xff, 0x0}
|
||||||
|
3: []byte{0xc0, 0xa8, 0x10, 0x1}
|
||||||
|
6: []byte{0xc0, 0xa8, 0x10, 0x1}
|
||||||
|
12: []byte{0x63, 0x6f, 0x72, 0x65, 0x30, 0x31}
|
||||||
|
15: []byte{0x68, 0x6f, 0x6d, 0x65, 0x2e, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x65, 0x2e, 0x74, 0x66}
|
||||||
|
28: []byte{0xc0, 0xa8, 0x10, 0xff}
|
||||||
|
51: []byte{0x0, 0x0, 0xe, 0x10}
|
||||||
|
53: []byte{0x2}
|
||||||
|
54: []byte{0xc0, 0xa8, 0x10, 0x1}
|
||||||
|
58: []byte{0x0, 0x0, 0x7, 0x8}
|
||||||
|
59: []byte{0x0, 0x0, 0xc, 0x4e}
|
||||||
|
=====
|
BIN
dhcp/testdata/dhcp.pcap
vendored
Normal file
BIN
dhcp/testdata/dhcp.pcap
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user