Skip to content

Commit 49ab074

Browse files
Reintroduce test for DHCPv4 packet marshalling and unmarshalling (#20)
* Reintroduce test for DHCPv4 packet marshalling and unmarshalling Necessary components from `netboot/pcap` have been merged into the test. * Fix linter rule violations --------- Co-authored-by: Stefan Majer <[email protected]>
1 parent 5ca1854 commit 49ab074

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

dhcp4/packet_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2016 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dhcp4
16+
17+
import (
18+
"bufio"
19+
"bytes"
20+
"encoding/binary"
21+
"errors"
22+
"fmt"
23+
"io"
24+
"os"
25+
"reflect"
26+
"testing"
27+
)
28+
29+
const (
30+
// See: https://wiki.wireshark.org/Development/LibpcapFileFormat#global-header
31+
pcapHdrLen = 24
32+
ethHdrLen = 14
33+
udpHdrLen = 8
34+
)
35+
36+
// See: https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
37+
type packetHdr struct {
38+
_ uint32
39+
_ uint32
40+
Len uint32
41+
_ uint32
42+
}
43+
44+
func udpFromPcap(fname string) ([][]byte, error) {
45+
f, err := os.Open(fname)
46+
if err != nil {
47+
return nil, err
48+
}
49+
r := bufio.NewReader(f)
50+
51+
_, err = r.Discard(pcapHdrLen)
52+
if err != nil {
53+
return nil, fmt.Errorf("failed to discard header: %w", err)
54+
}
55+
56+
var ret [][]byte
57+
for {
58+
var hdr packetHdr
59+
if err = binary.Read(r, binary.LittleEndian, &hdr); err != nil {
60+
break
61+
}
62+
bs := make([]byte, hdr.Len)
63+
if _, err = io.ReadFull(r, bs); err != nil {
64+
break
65+
}
66+
hdrLen := ethHdrLen
67+
hdrLen += int(bs[hdrLen]&0xF) * 4 // IP header
68+
hdrLen += udpHdrLen
69+
ret = append(ret, bs[hdrLen:])
70+
}
71+
if err != nil && !errors.Is(err, io.EOF) {
72+
return nil, err
73+
}
74+
75+
return ret, nil
76+
}
77+
78+
func TestParse(t *testing.T) {
79+
rawPkts, err := udpFromPcap("testdata/dhcp.pcap")
80+
if err != nil {
81+
t.Fatalf("Getting test packets from pcap: %s", err)
82+
}
83+
84+
var pkts bytes.Buffer
85+
for i, rawPkt := range rawPkts {
86+
pkt, err := Unmarshal(rawPkt)
87+
if err != nil {
88+
t.Fatalf("Parsing DHCP packet #%d: %s", i+1, err)
89+
}
90+
pkts.WriteString(pkt.DebugString())
91+
pkts.WriteString("======\n")
92+
}
93+
94+
expectedFile := "testdata/dhcp.parsed"
95+
expected, err := os.ReadFile(expectedFile)
96+
if err != nil {
97+
t.Fatalf("Reading expected file: %s", err)
98+
}
99+
100+
if pkts.String() != string(expected) {
101+
if os.Getenv("UPDATE_TESTDATA") != "" {
102+
_ = os.WriteFile(expectedFile, pkts.Bytes(), 0600)
103+
t.Errorf("dhcp.pcap didn't decode to dhcp.parsed (updated dhcp.parsed)")
104+
} else {
105+
t.Fatalf("dhcp.pcap didn't decode to dhcp.parsed (rerun with UPDATE_TESTDATA=1 to get diff)")
106+
}
107+
}
108+
}
109+
110+
func TestWriteRead(t *testing.T) {
111+
rawPkts, err := udpFromPcap("testdata/dhcp.pcap")
112+
if err != nil {
113+
t.Fatalf("Getting test packets from pcap: %s", err)
114+
}
115+
116+
var pkts []*Packet
117+
for i, rawPkt := range rawPkts {
118+
pkt, err := Unmarshal(rawPkt)
119+
if err != nil {
120+
t.Fatalf("Unmarshalling testdata packet #%d: %s", i+1, err)
121+
}
122+
pkts = append(pkts, pkt)
123+
}
124+
125+
for _, pkt := range pkts {
126+
raw, err := pkt.Marshal()
127+
if err != nil {
128+
t.Fatalf("Packet marshalling failed: %s\nPacket: %#v", err, pkt)
129+
}
130+
pkt2, err := Unmarshal(raw)
131+
if err != nil {
132+
t.Fatalf("Packet unmarshalling failed: %s\nPacket: %#v", err, pkt)
133+
}
134+
if !reflect.DeepEqual(pkt, pkt2) {
135+
t.Fatalf("Packet mutated by write-then-read: %#v", pkt)
136+
}
137+
}
138+
}

0 commit comments

Comments
 (0)