blob: 966ccb8da1155bcfae83c1521c65ad66fdfe3a07 [file] [log] [blame]
Mikio Hara71586c32015-01-15 01:00:16 +09001// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package icmp_test
6
7import (
8 "fmt"
9 "net"
10 "reflect"
11 "testing"
12
13 "golang.org/x/net/icmp"
14 "golang.org/x/net/internal/iana"
15 "golang.org/x/net/ipv4"
16 "golang.org/x/net/ipv6"
17)
18
19var marshalAndParseMultipartMessageForIPv4Tests = []icmp.Message{
20 {
21 Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
22 Body: &icmp.DstUnreach{
23 Data: []byte("ERROR-INVOKING-PACKET"),
24 Extensions: []icmp.Extension{
25 &icmp.MPLSLabelStack{
26 Class: 1,
27 Type: 1,
28 Labels: []icmp.MPLSLabel{
29 {
30 Label: 16014,
31 TC: 0x4,
32 S: true,
33 TTL: 255,
34 },
35 },
36 },
Mikio Harac84eff72015-01-21 20:17:41 +090037 &icmp.InterfaceInfo{
38 Class: 2,
39 Type: 0x0f,
40 Interface: &net.Interface{
41 Index: 15,
42 Name: "en101",
43 MTU: 8192,
44 },
45 Addr: &net.IPAddr{
46 IP: net.IPv4(192, 168, 0, 1).To4(),
47 },
48 },
Mikio Hara71586c32015-01-15 01:00:16 +090049 },
50 },
51 },
52 {
53 Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
54 Body: &icmp.TimeExceeded{
55 Data: []byte("ERROR-INVOKING-PACKET"),
56 Extensions: []icmp.Extension{
Mikio Harac84eff72015-01-21 20:17:41 +090057 &icmp.InterfaceInfo{
58 Class: 2,
59 Type: 0x0f,
60 Interface: &net.Interface{
61 Index: 15,
62 Name: "en101",
63 MTU: 8192,
64 },
65 Addr: &net.IPAddr{
66 IP: net.IPv4(192, 168, 0, 1).To4(),
67 },
68 },
Mikio Hara71586c32015-01-15 01:00:16 +090069 &icmp.MPLSLabelStack{
70 Class: 1,
71 Type: 1,
72 Labels: []icmp.MPLSLabel{
73 {
74 Label: 16014,
75 TC: 0x4,
76 S: true,
77 TTL: 255,
78 },
79 },
80 },
81 },
82 },
83 },
84 {
85 Type: ipv4.ICMPTypeParameterProblem, Code: 2,
86 Body: &icmp.ParamProb{
87 Pointer: 8,
88 Data: []byte("ERROR-INVOKING-PACKET"),
89 Extensions: []icmp.Extension{
90 &icmp.MPLSLabelStack{
91 Class: 1,
92 Type: 1,
93 Labels: []icmp.MPLSLabel{
94 {
95 Label: 16014,
96 TC: 0x4,
97 S: true,
98 TTL: 255,
99 },
100 },
101 },
Mikio Harac84eff72015-01-21 20:17:41 +0900102 &icmp.InterfaceInfo{
103 Class: 2,
104 Type: 0x0f,
105 Interface: &net.Interface{
106 Index: 15,
107 Name: "en101",
108 MTU: 8192,
109 },
110 Addr: &net.IPAddr{
111 IP: net.IPv4(192, 168, 0, 1).To4(),
112 },
113 },
114 &icmp.InterfaceInfo{
115 Class: 2,
116 Type: 0x2f,
117 Interface: &net.Interface{
118 Index: 16,
119 Name: "en102",
120 MTU: 8192,
121 },
122 Addr: &net.IPAddr{
123 IP: net.IPv4(192, 168, 0, 2).To4(),
124 },
125 },
Mikio Hara71586c32015-01-15 01:00:16 +0900126 },
127 },
128 },
129}
130
131func TestMarshalAndParseMultipartMessageForIPv4(t *testing.T) {
132 for i, tt := range marshalAndParseMultipartMessageForIPv4Tests {
133 b, err := tt.Marshal(nil)
134 if err != nil {
135 t.Fatal(err)
136 }
137 if b[5] != 32 {
138 t.Errorf("#%v: got %v; want 32", i, b[5])
139 }
140 m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
141 if err != nil {
142 t.Fatal(err)
143 }
144 if m.Type != tt.Type || m.Code != tt.Code {
145 t.Errorf("#%v: got %v; want %v", i, m, &tt)
146 }
147 switch m.Type {
148 case ipv4.ICMPTypeDestinationUnreachable:
149 got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
150 if !reflect.DeepEqual(got.Extensions, want.Extensions) {
Mikio Harac84eff72015-01-21 20:17:41 +0900151 t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
Mikio Hara71586c32015-01-15 01:00:16 +0900152 }
153 if len(got.Data) != 128 {
154 t.Errorf("#%v: got %v; want 128", i, len(got.Data))
155 }
156 case ipv4.ICMPTypeTimeExceeded:
157 got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
158 if !reflect.DeepEqual(got.Extensions, want.Extensions) {
159 t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
160 }
161 if len(got.Data) != 128 {
162 t.Errorf("#%v: got %v; want 128", i, len(got.Data))
163 }
164 case ipv4.ICMPTypeParameterProblem:
165 got, want := m.Body.(*icmp.ParamProb), tt.Body.(*icmp.ParamProb)
166 if !reflect.DeepEqual(got.Extensions, want.Extensions) {
167 t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
168 }
169 if len(got.Data) != 128 {
170 t.Errorf("#%v: got %v; want 128", i, len(got.Data))
171 }
172 }
173 }
174}
175
176var marshalAndParseMultipartMessageForIPv6Tests = []icmp.Message{
177 {
178 Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
179 Body: &icmp.DstUnreach{
180 Data: []byte("ERROR-INVOKING-PACKET"),
181 Extensions: []icmp.Extension{
182 &icmp.MPLSLabelStack{
183 Class: 1,
184 Type: 1,
185 Labels: []icmp.MPLSLabel{
186 {
187 Label: 16014,
188 TC: 0x4,
189 S: true,
190 TTL: 255,
191 },
192 },
193 },
Mikio Harac84eff72015-01-21 20:17:41 +0900194 &icmp.InterfaceInfo{
195 Class: 2,
196 Type: 0x0f,
197 Interface: &net.Interface{
198 Index: 15,
199 Name: "en101",
200 MTU: 8192,
201 },
202 Addr: &net.IPAddr{
203 IP: net.ParseIP("fe80::1"),
204 Zone: "en101",
205 },
206 },
Mikio Hara71586c32015-01-15 01:00:16 +0900207 },
208 },
209 },
210 {
211 Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
212 Body: &icmp.TimeExceeded{
213 Data: []byte("ERROR-INVOKING-PACKET"),
214 Extensions: []icmp.Extension{
Mikio Harac84eff72015-01-21 20:17:41 +0900215 &icmp.InterfaceInfo{
216 Class: 2,
217 Type: 0x0f,
218 Interface: &net.Interface{
219 Index: 15,
220 Name: "en101",
221 MTU: 8192,
222 },
223 Addr: &net.IPAddr{
224 IP: net.ParseIP("fe80::1"),
225 Zone: "en101",
226 },
227 },
Mikio Hara71586c32015-01-15 01:00:16 +0900228 &icmp.MPLSLabelStack{
229 Class: 1,
230 Type: 1,
231 Labels: []icmp.MPLSLabel{
232 {
233 Label: 16014,
234 TC: 0x4,
235 S: true,
236 TTL: 255,
237 },
238 },
239 },
Mikio Harac84eff72015-01-21 20:17:41 +0900240 &icmp.InterfaceInfo{
241 Class: 2,
242 Type: 0x2f,
243 Interface: &net.Interface{
244 Index: 16,
245 Name: "en102",
246 MTU: 8192,
247 },
248 Addr: &net.IPAddr{
249 IP: net.ParseIP("fe80::1"),
250 Zone: "en102",
251 },
252 },
Mikio Hara71586c32015-01-15 01:00:16 +0900253 },
254 },
255 },
256}
257
258func TestMarshalAndParseMultipartMessageForIPv6(t *testing.T) {
259 pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
260 for i, tt := range marshalAndParseMultipartMessageForIPv6Tests {
261 for _, psh := range [][]byte{pshicmp, nil} {
262 b, err := tt.Marshal(psh)
263 if err != nil {
264 t.Fatal(err)
265 }
266 if b[4] != 16 {
267 t.Errorf("#%v: got %v; want 16", i, b[4])
268 }
269 m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
270 if err != nil {
271 t.Fatal(err)
272 }
273 if m.Type != tt.Type || m.Code != tt.Code {
274 t.Errorf("#%v: got %v; want %v", i, m, &tt)
275 }
276 switch m.Type {
277 case ipv6.ICMPTypeDestinationUnreachable:
278 got, want := m.Body.(*icmp.DstUnreach), tt.Body.(*icmp.DstUnreach)
279 if !reflect.DeepEqual(got.Extensions, want.Extensions) {
280 t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
281 }
282 if len(got.Data) != 128 {
283 t.Errorf("#%v: got %v; want 128", i, len(got.Data))
284 }
285 case ipv6.ICMPTypeTimeExceeded:
286 got, want := m.Body.(*icmp.TimeExceeded), tt.Body.(*icmp.TimeExceeded)
287 if !reflect.DeepEqual(got.Extensions, want.Extensions) {
288 t.Error(dumpExtensions(i, got.Extensions, want.Extensions))
289 }
290 if len(got.Data) != 128 {
291 t.Errorf("#%v: got %v; want 128", i, len(got.Data))
292 }
293 }
294 }
295 }
296}
297
298func dumpExtensions(i int, gotExts, wantExts []icmp.Extension) string {
299 var s string
300 for j, got := range gotExts {
301 switch got := got.(type) {
302 case *icmp.MPLSLabelStack:
303 want := wantExts[j].(*icmp.MPLSLabelStack)
304 if !reflect.DeepEqual(got, want) {
305 s += fmt.Sprintf("#%v/%v: got %#v; want %#v\n", i, j, got, want)
306 }
Mikio Harac84eff72015-01-21 20:17:41 +0900307 case *icmp.InterfaceInfo:
308 want := wantExts[j].(*icmp.InterfaceInfo)
309 if !reflect.DeepEqual(got, want) {
310 s += fmt.Sprintf("#%v/%v: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, j, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
311 }
Mikio Hara71586c32015-01-15 01:00:16 +0900312 }
313 }
314 return s[:len(s)-1]
315}
Mikio Hara62ac18b2015-11-04 16:49:45 +0900316
317var multipartMessageBodyLenTests = []struct {
318 proto int
319 in icmp.MessageBody
320 out int
321}{
322 {
323 iana.ProtocolICMP,
324 &icmp.DstUnreach{
325 Data: make([]byte, ipv4.HeaderLen),
326 },
327 4 + ipv4.HeaderLen, // unused and original datagram
328 },
329 {
330 iana.ProtocolICMP,
331 &icmp.TimeExceeded{
332 Data: make([]byte, ipv4.HeaderLen),
333 },
334 4 + ipv4.HeaderLen, // unused and original datagram
335 },
336 {
337 iana.ProtocolICMP,
338 &icmp.ParamProb{
339 Data: make([]byte, ipv4.HeaderLen),
340 },
341 4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
342 },
343
344 {
345 iana.ProtocolICMP,
346 &icmp.ParamProb{
347 Data: make([]byte, ipv4.HeaderLen),
348 Extensions: []icmp.Extension{
349 &icmp.MPLSLabelStack{},
350 },
351 },
352 4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
353 },
354 {
355 iana.ProtocolICMP,
356 &icmp.ParamProb{
357 Data: make([]byte, 128),
358 Extensions: []icmp.Extension{
359 &icmp.MPLSLabelStack{},
360 },
361 },
362 4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
363 },
364 {
365 iana.ProtocolICMP,
366 &icmp.ParamProb{
367 Data: make([]byte, 129),
368 Extensions: []icmp.Extension{
369 &icmp.MPLSLabelStack{},
370 },
371 },
372 4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
373 },
374
375 {
376 iana.ProtocolIPv6ICMP,
377 &icmp.DstUnreach{
378 Data: make([]byte, ipv6.HeaderLen),
379 },
380 4 + ipv6.HeaderLen, // unused and original datagram
381 },
382 {
383 iana.ProtocolIPv6ICMP,
384 &icmp.PacketTooBig{
385 Data: make([]byte, ipv6.HeaderLen),
386 },
387 4 + ipv6.HeaderLen, // mtu and original datagram
388 },
389 {
390 iana.ProtocolIPv6ICMP,
391 &icmp.TimeExceeded{
392 Data: make([]byte, ipv6.HeaderLen),
393 },
394 4 + ipv6.HeaderLen, // unused and original datagram
395 },
396 {
397 iana.ProtocolIPv6ICMP,
398 &icmp.ParamProb{
399 Data: make([]byte, ipv6.HeaderLen),
400 },
401 4 + ipv6.HeaderLen, // pointer and original datagram
402 },
403
404 {
405 iana.ProtocolIPv6ICMP,
406 &icmp.DstUnreach{
407 Data: make([]byte, 127),
408 Extensions: []icmp.Extension{
409 &icmp.MPLSLabelStack{},
410 },
411 },
412 4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
413 },
414 {
415 iana.ProtocolIPv6ICMP,
416 &icmp.DstUnreach{
417 Data: make([]byte, 128),
418 Extensions: []icmp.Extension{
419 &icmp.MPLSLabelStack{},
420 },
421 },
422 4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
423 },
424 {
425 iana.ProtocolIPv6ICMP,
426 &icmp.DstUnreach{
427 Data: make([]byte, 129),
428 Extensions: []icmp.Extension{
429 &icmp.MPLSLabelStack{},
430 },
431 },
432 4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
433 },
434}
435
436func TestMultipartMessageBodyLen(t *testing.T) {
437 for i, tt := range multipartMessageBodyLenTests {
438 if out := tt.in.Len(tt.proto); out != tt.out {
439 t.Errorf("#%d: got %d; want %d", i, out, tt.out)
440 }
441 }
442}