1
2
3
4
5 package icmp
6
7 import (
8 "fmt"
9 "net"
10 "reflect"
11 "testing"
12
13 "golang.org/x/net/internal/iana"
14 "golang.org/x/net/ipv4"
15 "golang.org/x/net/ipv6"
16 )
17
18 func TestMarshalAndParseExtension(t *testing.T) {
19 fn := func(t *testing.T, proto int, typ Type, hdr, obj []byte, te Extension) error {
20 b, err := te.Marshal(proto)
21 if err != nil {
22 return err
23 }
24 if !reflect.DeepEqual(b, obj) {
25 return fmt.Errorf("got %#v; want %#v", b, obj)
26 }
27 switch typ {
28 case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
29 exts, l, err := parseExtensions(typ, append(hdr, obj...), 0)
30 if err != nil {
31 return err
32 }
33 if l != 0 {
34 return fmt.Errorf("got %d; want 0", l)
35 }
36 if !reflect.DeepEqual(exts, []Extension{te}) {
37 return fmt.Errorf("got %#v; want %#v", exts[0], te)
38 }
39 default:
40 for i, wire := range []struct {
41 data []byte
42 inlattr int
43 outlattr int
44 err error
45 }{
46 {nil, 0, -1, errNoExtension},
47 {make([]byte, 127), 128, -1, errNoExtension},
48
49 {make([]byte, 128), 127, -1, errNoExtension},
50 {make([]byte, 128), 128, -1, errNoExtension},
51 {make([]byte, 128), 129, -1, errNoExtension},
52
53 {append(make([]byte, 128), append(hdr, obj...)...), 127, 128, nil},
54 {append(make([]byte, 128), append(hdr, obj...)...), 128, 128, nil},
55 {append(make([]byte, 128), append(hdr, obj...)...), 129, 128, nil},
56
57 {append(make([]byte, 512), append(hdr, obj...)...), 511, -1, errNoExtension},
58 {append(make([]byte, 512), append(hdr, obj...)...), 512, 512, nil},
59 {append(make([]byte, 512), append(hdr, obj...)...), 513, -1, errNoExtension},
60 } {
61 exts, l, err := parseExtensions(typ, wire.data, wire.inlattr)
62 if err != wire.err {
63 return fmt.Errorf("#%d: got %v; want %v", i, err, wire.err)
64 }
65 if wire.err != nil {
66 continue
67 }
68 if l != wire.outlattr {
69 return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
70 }
71 if !reflect.DeepEqual(exts, []Extension{te}) {
72 return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], te)
73 }
74 }
75 }
76 return nil
77 }
78
79 t.Run("MPLSLabelStack", func(t *testing.T) {
80 for _, et := range []struct {
81 proto int
82 typ Type
83 hdr []byte
84 obj []byte
85 ext Extension
86 }{
87
88 {
89 proto: iana.ProtocolICMP,
90 typ: ipv4.ICMPTypeDestinationUnreachable,
91 hdr: []byte{
92 0x20, 0x00, 0x00, 0x00,
93 },
94 obj: []byte{
95 0x00, 0x04, 0x01, 0x01,
96 },
97 ext: &MPLSLabelStack{
98 Class: classMPLSLabelStack,
99 Type: typeIncomingMPLSLabelStack,
100 },
101 },
102
103 {
104 proto: iana.ProtocolIPv6ICMP,
105 typ: ipv6.ICMPTypeDestinationUnreachable,
106 hdr: []byte{
107 0x20, 0x00, 0x00, 0x00,
108 },
109 obj: []byte{
110 0x00, 0x08, 0x01, 0x01,
111 0x03, 0xe8, 0xe9, 0xff,
112 },
113 ext: &MPLSLabelStack{
114 Class: classMPLSLabelStack,
115 Type: typeIncomingMPLSLabelStack,
116 Labels: []MPLSLabel{
117 {
118 Label: 16014,
119 TC: 0x4,
120 S: true,
121 TTL: 255,
122 },
123 },
124 },
125 },
126
127 {
128 proto: iana.ProtocolICMP,
129 typ: ipv4.ICMPTypeDestinationUnreachable,
130 hdr: []byte{
131 0x20, 0x00, 0x00, 0x00,
132 },
133 obj: []byte{
134 0x00, 0x0c, 0x01, 0x01,
135 0x03, 0xe8, 0xde, 0xfe,
136 0x03, 0xe8, 0xe1, 0xff,
137 },
138 ext: &MPLSLabelStack{
139 Class: classMPLSLabelStack,
140 Type: typeIncomingMPLSLabelStack,
141 Labels: []MPLSLabel{
142 {
143 Label: 16013,
144 TC: 0x7,
145 S: false,
146 TTL: 254,
147 },
148 {
149 Label: 16014,
150 TC: 0,
151 S: true,
152 TTL: 255,
153 },
154 },
155 },
156 },
157 } {
158 if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
159 t.Error(err)
160 }
161 }
162 })
163 t.Run("InterfaceInfo", func(t *testing.T) {
164 for _, et := range []struct {
165 proto int
166 typ Type
167 hdr []byte
168 obj []byte
169 ext Extension
170 }{
171
172 {
173 proto: iana.ProtocolICMP,
174 typ: ipv4.ICMPTypeDestinationUnreachable,
175 hdr: []byte{
176 0x20, 0x00, 0x00, 0x00,
177 },
178 obj: []byte{
179 0x00, 0x04, 0x02, 0x00,
180 },
181 ext: &InterfaceInfo{
182 Class: classInterfaceInfo,
183 },
184 },
185
186 {
187 proto: iana.ProtocolICMP,
188 typ: ipv4.ICMPTypeDestinationUnreachable,
189 hdr: []byte{
190 0x20, 0x00, 0x00, 0x00,
191 },
192 obj: []byte{
193 0x00, 0x10, 0x02, 0x0a,
194 0x00, 0x00, 0x00, 0x10,
195 0x08, byte('e'), byte('n'), byte('1'),
196 byte('0'), byte('1'), 0x00, 0x00,
197 },
198 ext: &InterfaceInfo{
199 Class: classInterfaceInfo,
200 Type: 0x0a,
201 Interface: &net.Interface{
202 Index: 16,
203 Name: "en101",
204 },
205 },
206 },
207
208 {
209 proto: iana.ProtocolIPv6ICMP,
210 typ: ipv6.ICMPTypeDestinationUnreachable,
211 hdr: []byte{
212 0x20, 0x00, 0x00, 0x00,
213 },
214 obj: []byte{
215 0x00, 0x28, 0x02, 0x0f,
216 0x00, 0x00, 0x00, 0x0f,
217 0x00, 0x02, 0x00, 0x00,
218 0xfe, 0x80, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x01,
222 0x08, byte('e'), byte('n'), byte('1'),
223 byte('0'), byte('1'), 0x00, 0x00,
224 0x00, 0x00, 0x20, 0x00,
225 },
226 ext: &InterfaceInfo{
227 Class: classInterfaceInfo,
228 Type: 0x0f,
229 Interface: &net.Interface{
230 Index: 15,
231 Name: "en101",
232 MTU: 8192,
233 },
234 Addr: &net.IPAddr{
235 IP: net.ParseIP("fe80::1"),
236 Zone: "en101",
237 },
238 },
239 },
240 } {
241 if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
242 t.Error(err)
243 }
244 }
245 })
246 t.Run("InterfaceIdent", func(t *testing.T) {
247 for _, et := range []struct {
248 proto int
249 typ Type
250 hdr []byte
251 obj []byte
252 ext Extension
253 }{
254
255 {
256 proto: iana.ProtocolICMP,
257 typ: ipv4.ICMPTypeExtendedEchoRequest,
258 hdr: []byte{
259 0x20, 0x00, 0x00, 0x00,
260 },
261 obj: []byte{
262 0x00, 0x0c, 0x03, 0x01,
263 byte('e'), byte('n'), byte('1'), byte('0'),
264 byte('1'), 0x00, 0x00, 0x00,
265 },
266 ext: &InterfaceIdent{
267 Class: classInterfaceIdent,
268 Type: typeInterfaceByName,
269 Name: "en101",
270 },
271 },
272
273 {
274 proto: iana.ProtocolIPv6ICMP,
275 typ: ipv6.ICMPTypeExtendedEchoRequest,
276 hdr: []byte{
277 0x20, 0x00, 0x00, 0x00,
278 },
279 obj: []byte{
280 0x00, 0x08, 0x03, 0x02,
281 0x00, 0x00, 0x03, 0x8f,
282 },
283 ext: &InterfaceIdent{
284 Class: classInterfaceIdent,
285 Type: typeInterfaceByIndex,
286 Index: 911,
287 },
288 },
289
290 {
291 proto: iana.ProtocolICMP,
292 typ: ipv4.ICMPTypeExtendedEchoRequest,
293 hdr: []byte{
294 0x20, 0x00, 0x00, 0x00,
295 },
296 obj: []byte{
297 0x00, 0x10, 0x03, 0x03,
298 byte(iana.AddrFamily48bitMAC >> 8), byte(iana.AddrFamily48bitMAC & 0x0f), 0x06, 0x00,
299 0x01, 0x23, 0x45, 0x67,
300 0x89, 0xab, 0x00, 0x00,
301 },
302 ext: &InterfaceIdent{
303 Class: classInterfaceIdent,
304 Type: typeInterfaceByAddress,
305 AFI: iana.AddrFamily48bitMAC,
306 Addr: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
307 },
308 },
309 } {
310 if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
311 t.Error(err)
312 }
313 }
314 })
315 }
316
317 func TestParseInterfaceName(t *testing.T) {
318 ifi := InterfaceInfo{Interface: &net.Interface{}}
319 for i, tt := range []struct {
320 b []byte
321 error
322 }{
323 {[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
324 {[]byte{4, 'e', 'n', '0'}, nil},
325 {[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
326 {[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
327 } {
328 if _, err := ifi.parseName(tt.b); err != tt.error {
329 t.Errorf("#%d: got %v; want %v", i, err, tt.error)
330 }
331 }
332 }
333
View as plain text