1
2
3
4
5 package ipv4
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "net"
11 "reflect"
12 "runtime"
13 "strings"
14 "testing"
15
16 "golang.org/x/net/internal/socket"
17 )
18
19 type headerTest struct {
20 wireHeaderFromKernel []byte
21 wireHeaderToKernel []byte
22 wireHeaderFromTradBSDKernel []byte
23 wireHeaderToTradBSDKernel []byte
24 wireHeaderFromFreeBSD10Kernel []byte
25 wireHeaderToFreeBSD10Kernel []byte
26 *Header
27 }
28
29 var headerLittleEndianTests = []headerTest{
30
31
32 {
33 wireHeaderFromKernel: []byte{
34 0x45, 0x01, 0xbe, 0xef,
35 0xca, 0xfe, 0x45, 0xdc,
36 0xff, 0x01, 0xde, 0xad,
37 172, 16, 254, 254,
38 192, 168, 0, 1,
39 },
40 wireHeaderToKernel: []byte{
41 0x45, 0x01, 0xbe, 0xef,
42 0xca, 0xfe, 0x45, 0xdc,
43 0xff, 0x01, 0xde, 0xad,
44 172, 16, 254, 254,
45 192, 168, 0, 1,
46 },
47 wireHeaderFromTradBSDKernel: []byte{
48 0x45, 0x01, 0xdb, 0xbe,
49 0xca, 0xfe, 0xdc, 0x45,
50 0xff, 0x01, 0xde, 0xad,
51 172, 16, 254, 254,
52 192, 168, 0, 1,
53 },
54 wireHeaderToTradBSDKernel: []byte{
55 0x45, 0x01, 0xef, 0xbe,
56 0xca, 0xfe, 0xdc, 0x45,
57 0xff, 0x01, 0xde, 0xad,
58 172, 16, 254, 254,
59 192, 168, 0, 1,
60 },
61 wireHeaderFromFreeBSD10Kernel: []byte{
62 0x45, 0x01, 0xef, 0xbe,
63 0xca, 0xfe, 0xdc, 0x45,
64 0xff, 0x01, 0xde, 0xad,
65 172, 16, 254, 254,
66 192, 168, 0, 1,
67 },
68 wireHeaderToFreeBSD10Kernel: []byte{
69 0x45, 0x01, 0xef, 0xbe,
70 0xca, 0xfe, 0xdc, 0x45,
71 0xff, 0x01, 0xde, 0xad,
72 172, 16, 254, 254,
73 192, 168, 0, 1,
74 },
75 Header: &Header{
76 Version: Version,
77 Len: HeaderLen,
78 TOS: 1,
79 TotalLen: 0xbeef,
80 ID: 0xcafe,
81 Flags: DontFragment,
82 FragOff: 1500,
83 TTL: 255,
84 Protocol: 1,
85 Checksum: 0xdead,
86 Src: net.IPv4(172, 16, 254, 254),
87 Dst: net.IPv4(192, 168, 0, 1),
88 },
89 },
90
91
92 {
93 wireHeaderFromKernel: []byte{
94 0x46, 0x01, 0xbe, 0xf3,
95 0xca, 0xfe, 0x45, 0xdc,
96 0xff, 0x01, 0xde, 0xad,
97 172, 16, 254, 254,
98 192, 168, 0, 1,
99 0xff, 0xfe, 0xfe, 0xff,
100 },
101 wireHeaderToKernel: []byte{
102 0x46, 0x01, 0xbe, 0xf3,
103 0xca, 0xfe, 0x45, 0xdc,
104 0xff, 0x01, 0xde, 0xad,
105 172, 16, 254, 254,
106 192, 168, 0, 1,
107 0xff, 0xfe, 0xfe, 0xff,
108 },
109 wireHeaderFromTradBSDKernel: []byte{
110 0x46, 0x01, 0xdb, 0xbe,
111 0xca, 0xfe, 0xdc, 0x45,
112 0xff, 0x01, 0xde, 0xad,
113 172, 16, 254, 254,
114 192, 168, 0, 1,
115 0xff, 0xfe, 0xfe, 0xff,
116 },
117 wireHeaderToTradBSDKernel: []byte{
118 0x46, 0x01, 0xf3, 0xbe,
119 0xca, 0xfe, 0xdc, 0x45,
120 0xff, 0x01, 0xde, 0xad,
121 172, 16, 254, 254,
122 192, 168, 0, 1,
123 0xff, 0xfe, 0xfe, 0xff,
124 },
125 wireHeaderFromFreeBSD10Kernel: []byte{
126 0x46, 0x01, 0xf3, 0xbe,
127 0xca, 0xfe, 0xdc, 0x45,
128 0xff, 0x01, 0xde, 0xad,
129 172, 16, 254, 254,
130 192, 168, 0, 1,
131 0xff, 0xfe, 0xfe, 0xff,
132 },
133 wireHeaderToFreeBSD10Kernel: []byte{
134 0x46, 0x01, 0xf3, 0xbe,
135 0xca, 0xfe, 0xdc, 0x45,
136 0xff, 0x01, 0xde, 0xad,
137 172, 16, 254, 254,
138 192, 168, 0, 1,
139 0xff, 0xfe, 0xfe, 0xff,
140 },
141 Header: &Header{
142 Version: Version,
143 Len: HeaderLen + 4,
144 TOS: 1,
145 TotalLen: 0xbef3,
146 ID: 0xcafe,
147 Flags: DontFragment,
148 FragOff: 1500,
149 TTL: 255,
150 Protocol: 1,
151 Checksum: 0xdead,
152 Src: net.IPv4(172, 16, 254, 254),
153 Dst: net.IPv4(192, 168, 0, 1),
154 Options: []byte{0xff, 0xfe, 0xfe, 0xff},
155 },
156 },
157 }
158
159 func TestMarshalHeader(t *testing.T) {
160 for i, tt := range []struct {
161 h *Header
162 err error
163 }{
164 {nil, errNilHeader},
165 {&Header{Len: HeaderLen - 1}, errHeaderTooShort},
166 } {
167 if _, err := tt.h.Marshal(); err != tt.err {
168 t.Errorf("#%d: got %v; want %v", i, err, tt.err)
169 }
170 }
171
172 if socket.NativeEndian != binary.LittleEndian {
173 t.Skip("no test for non-little endian machine yet")
174 }
175 for _, tt := range headerLittleEndianTests {
176 b, err := tt.Header.Marshal()
177 if err != nil {
178 t.Fatal(err)
179 }
180 var wh []byte
181 switch runtime.GOOS {
182 case "darwin", "ios", "dragonfly", "netbsd":
183 wh = tt.wireHeaderToTradBSDKernel
184 case "freebsd":
185 switch {
186 case freebsdVersion < 1000000:
187 wh = tt.wireHeaderToTradBSDKernel
188 case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
189 wh = tt.wireHeaderToFreeBSD10Kernel
190 default:
191 wh = tt.wireHeaderToKernel
192 }
193 default:
194 wh = tt.wireHeaderToKernel
195 }
196 if !bytes.Equal(b, wh) {
197 t.Fatalf("got %#v; want %#v", b, wh)
198 }
199 }
200 }
201
202 func TestParseHeader(t *testing.T) {
203 for i, tt := range []struct {
204 h *Header
205 wh []byte
206 err error
207 }{
208 {nil, nil, errNilHeader},
209 {&Header{}, nil, errNilHeader},
210 {&Header{}, make([]byte, HeaderLen-1), errHeaderTooShort},
211 {&Header{}, []byte{
212 0x46, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00,
217 }, errExtHeaderTooShort},
218 } {
219 if err := tt.h.Parse(tt.wh); err != tt.err {
220 t.Fatalf("#%d: got %v; want %v", i, err, tt.err)
221 }
222 }
223
224 if socket.NativeEndian != binary.LittleEndian {
225 t.Skip("no test for big endian machine yet")
226 }
227 for _, tt := range headerLittleEndianTests {
228 var wh []byte
229 switch runtime.GOOS {
230 case "darwin", "ios", "dragonfly", "netbsd":
231 wh = tt.wireHeaderFromTradBSDKernel
232 case "freebsd":
233 switch {
234 case freebsdVersion < 1000000:
235 wh = tt.wireHeaderFromTradBSDKernel
236 case 1000000 <= freebsdVersion && freebsdVersion < 1100000:
237 wh = tt.wireHeaderFromFreeBSD10Kernel
238 default:
239 wh = tt.wireHeaderFromKernel
240 }
241 default:
242 wh = tt.wireHeaderFromKernel
243 }
244 h, err := ParseHeader(wh)
245 if err != nil {
246 t.Fatal(err)
247 }
248 if err := h.Parse(wh); err != nil {
249 t.Fatal(err)
250 }
251 if !reflect.DeepEqual(h, tt.Header) {
252 t.Fatalf("got %#v; want %#v", h, tt.Header)
253 }
254 s := h.String()
255 if strings.Contains(s, ",") {
256 t.Fatalf("should be space-separated values: %s", s)
257 }
258 }
259 }
260
View as plain text