Add a basic regression test for DHCP parsing.

This commit is contained in:
David Anderson 2016-02-27 22:34:18 -08:00
parent 178a83f3e0
commit fa657ad649
4 changed files with 176 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net"
"sort"
)
var magic = []byte{99, 130, 83, 99}
@ -68,6 +69,40 @@ type Packet struct {
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.
func (p *Packet) Marshal() ([]byte, error) {
if len(p.TransactionID) != 4 {

73
dhcp/dhcp_test.go Normal file
View 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
View 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

Binary file not shown.