source sync 20190409
[platform/core/system/edge-orchestration.git] / vendor / golang.org / x / net / icmp / multipart_test.go
1 // 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
5 package icmp_test
6
7 import (
8         "errors"
9         "fmt"
10         "net"
11         "reflect"
12         "testing"
13
14         "golang.org/x/net/icmp"
15         "golang.org/x/net/internal/iana"
16         "golang.org/x/net/ipv4"
17         "golang.org/x/net/ipv6"
18 )
19
20 func TestMarshalAndParseMultipartMessage(t *testing.T) {
21         fn := func(t *testing.T, proto int, tm icmp.Message) error {
22                 b, err := tm.Marshal(nil)
23                 if err != nil {
24                         return err
25                 }
26                 switch tm.Type {
27                 case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
28                 default:
29                         switch proto {
30                         case iana.ProtocolICMP:
31                                 if b[5] != 32 {
32                                         return fmt.Errorf("got %d; want 32", b[5])
33                                 }
34                         case iana.ProtocolIPv6ICMP:
35                                 if b[4] != 16 {
36                                         return fmt.Errorf("got %d; want 16", b[4])
37                                 }
38                         default:
39                                 return fmt.Errorf("unknown protocol: %d", proto)
40                         }
41                 }
42                 m, err := icmp.ParseMessage(proto, b)
43                 if err != nil {
44                         return err
45                 }
46                 if m.Type != tm.Type || m.Code != tm.Code {
47                         return fmt.Errorf("got %v; want %v", m, &tm)
48                 }
49                 switch m.Type {
50                 case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
51                         got, want := m.Body.(*icmp.ExtendedEchoRequest), tm.Body.(*icmp.ExtendedEchoRequest)
52                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
53                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
54                         }
55                 case ipv4.ICMPTypeDestinationUnreachable:
56                         got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
57                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
58                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
59                         }
60                         if len(got.Data) != 128 {
61                                 return fmt.Errorf("got %d; want 128", len(got.Data))
62                         }
63                 case ipv4.ICMPTypeTimeExceeded:
64                         got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
65                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
66                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
67                         }
68                         if len(got.Data) != 128 {
69                                 return fmt.Errorf("got %d; want 128", len(got.Data))
70                         }
71                 case ipv4.ICMPTypeParameterProblem:
72                         got, want := m.Body.(*icmp.ParamProb), tm.Body.(*icmp.ParamProb)
73                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
74                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
75                         }
76                         if len(got.Data) != 128 {
77                                 return fmt.Errorf("got %d; want 128", len(got.Data))
78                         }
79                 case ipv6.ICMPTypeDestinationUnreachable:
80                         got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
81                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
82                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
83                         }
84                         if len(got.Data) != 128 {
85                                 return fmt.Errorf("got %d; want 128", len(got.Data))
86                         }
87                 case ipv6.ICMPTypeTimeExceeded:
88                         got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
89                         if !reflect.DeepEqual(got.Extensions, want.Extensions) {
90                                 return errors.New(dumpExtensions(got.Extensions, want.Extensions))
91                         }
92                         if len(got.Data) != 128 {
93                                 return fmt.Errorf("got %d; want 128", len(got.Data))
94                         }
95                 default:
96                         return fmt.Errorf("unknown message type: %v", m.Type)
97                 }
98                 return nil
99         }
100
101         t.Run("IPv4", func(t *testing.T) {
102                 for i, tm := range []icmp.Message{
103                         {
104                                 Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
105                                 Body: &icmp.DstUnreach{
106                                         Data: []byte("ERROR-INVOKING-PACKET"),
107                                         Extensions: []icmp.Extension{
108                                                 &icmp.MPLSLabelStack{
109                                                         Class: 1,
110                                                         Type:  1,
111                                                         Labels: []icmp.MPLSLabel{
112                                                                 {
113                                                                         Label: 16014,
114                                                                         TC:    0x4,
115                                                                         S:     true,
116                                                                         TTL:   255,
117                                                                 },
118                                                         },
119                                                 },
120                                                 &icmp.InterfaceInfo{
121                                                         Class: 2,
122                                                         Type:  0x0f,
123                                                         Interface: &net.Interface{
124                                                                 Index: 15,
125                                                                 Name:  "en101",
126                                                                 MTU:   8192,
127                                                         },
128                                                         Addr: &net.IPAddr{
129                                                                 IP: net.IPv4(192, 168, 0, 1).To4(),
130                                                         },
131                                                 },
132                                         },
133                                 },
134                         },
135                         {
136                                 Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
137                                 Body: &icmp.TimeExceeded{
138                                         Data: []byte("ERROR-INVOKING-PACKET"),
139                                         Extensions: []icmp.Extension{
140                                                 &icmp.InterfaceInfo{
141                                                         Class: 2,
142                                                         Type:  0x0f,
143                                                         Interface: &net.Interface{
144                                                                 Index: 15,
145                                                                 Name:  "en101",
146                                                                 MTU:   8192,
147                                                         },
148                                                         Addr: &net.IPAddr{
149                                                                 IP: net.IPv4(192, 168, 0, 1).To4(),
150                                                         },
151                                                 },
152                                                 &icmp.MPLSLabelStack{
153                                                         Class: 1,
154                                                         Type:  1,
155                                                         Labels: []icmp.MPLSLabel{
156                                                                 {
157                                                                         Label: 16014,
158                                                                         TC:    0x4,
159                                                                         S:     true,
160                                                                         TTL:   255,
161                                                                 },
162                                                         },
163                                                 },
164                                         },
165                                 },
166                         },
167                         {
168                                 Type: ipv4.ICMPTypeParameterProblem, Code: 2,
169                                 Body: &icmp.ParamProb{
170                                         Pointer: 8,
171                                         Data:    []byte("ERROR-INVOKING-PACKET"),
172                                         Extensions: []icmp.Extension{
173                                                 &icmp.MPLSLabelStack{
174                                                         Class: 1,
175                                                         Type:  1,
176                                                         Labels: []icmp.MPLSLabel{
177                                                                 {
178                                                                         Label: 16014,
179                                                                         TC:    0x4,
180                                                                         S:     true,
181                                                                         TTL:   255,
182                                                                 },
183                                                         },
184                                                 },
185                                                 &icmp.InterfaceInfo{
186                                                         Class: 2,
187                                                         Type:  0x0f,
188                                                         Interface: &net.Interface{
189                                                                 Index: 15,
190                                                                 Name:  "en101",
191                                                                 MTU:   8192,
192                                                         },
193                                                         Addr: &net.IPAddr{
194                                                                 IP: net.IPv4(192, 168, 0, 1).To4(),
195                                                         },
196                                                 },
197                                                 &icmp.InterfaceInfo{
198                                                         Class: 2,
199                                                         Type:  0x2f,
200                                                         Interface: &net.Interface{
201                                                                 Index: 16,
202                                                                 Name:  "en102",
203                                                                 MTU:   8192,
204                                                         },
205                                                         Addr: &net.IPAddr{
206                                                                 IP: net.IPv4(192, 168, 0, 2).To4(),
207                                                         },
208                                                 },
209                                         },
210                                 },
211                         },
212                         {
213                                 Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
214                                 Body: &icmp.ExtendedEchoRequest{
215                                         ID: 1, Seq: 2, Local: true,
216                                         Extensions: []icmp.Extension{
217                                                 &icmp.InterfaceIdent{
218                                                         Class: 3,
219                                                         Type:  1,
220                                                         Name:  "en101",
221                                                 },
222                                         },
223                                 },
224                         },
225                         {
226                                 Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
227                                 Body: &icmp.ExtendedEchoRequest{
228                                         ID: 1, Seq: 2, Local: true,
229                                         Extensions: []icmp.Extension{
230                                                 &icmp.InterfaceIdent{
231                                                         Class: 3,
232                                                         Type:  2,
233                                                         Index: 911,
234                                                 },
235                                         },
236                                 },
237                         },
238                         {
239                                 Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
240                                 Body: &icmp.ExtendedEchoRequest{
241                                         ID: 1, Seq: 2,
242                                         Extensions: []icmp.Extension{
243                                                 &icmp.InterfaceIdent{
244                                                         Class: 3,
245                                                         Type:  3,
246                                                         AFI:   iana.AddrFamily48bitMAC,
247                                                         Addr:  []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
248                                                 },
249                                         },
250                                 },
251                         },
252                 } {
253                         if err := fn(t, iana.ProtocolICMP, tm); err != nil {
254                                 t.Errorf("#%d: %v", i, err)
255                         }
256                 }
257         })
258         t.Run("IPv6", func(t *testing.T) {
259                 for i, tm := range []icmp.Message{
260                         {
261                                 Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
262                                 Body: &icmp.DstUnreach{
263                                         Data: []byte("ERROR-INVOKING-PACKET"),
264                                         Extensions: []icmp.Extension{
265                                                 &icmp.MPLSLabelStack{
266                                                         Class: 1,
267                                                         Type:  1,
268                                                         Labels: []icmp.MPLSLabel{
269                                                                 {
270                                                                         Label: 16014,
271                                                                         TC:    0x4,
272                                                                         S:     true,
273                                                                         TTL:   255,
274                                                                 },
275                                                         },
276                                                 },
277                                                 &icmp.InterfaceInfo{
278                                                         Class: 2,
279                                                         Type:  0x0f,
280                                                         Interface: &net.Interface{
281                                                                 Index: 15,
282                                                                 Name:  "en101",
283                                                                 MTU:   8192,
284                                                         },
285                                                         Addr: &net.IPAddr{
286                                                                 IP:   net.ParseIP("fe80::1"),
287                                                                 Zone: "en101",
288                                                         },
289                                                 },
290                                         },
291                                 },
292                         },
293                         {
294                                 Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
295                                 Body: &icmp.TimeExceeded{
296                                         Data: []byte("ERROR-INVOKING-PACKET"),
297                                         Extensions: []icmp.Extension{
298                                                 &icmp.InterfaceInfo{
299                                                         Class: 2,
300                                                         Type:  0x0f,
301                                                         Interface: &net.Interface{
302                                                                 Index: 15,
303                                                                 Name:  "en101",
304                                                                 MTU:   8192,
305                                                         },
306                                                         Addr: &net.IPAddr{
307                                                                 IP:   net.ParseIP("fe80::1"),
308                                                                 Zone: "en101",
309                                                         },
310                                                 },
311                                                 &icmp.MPLSLabelStack{
312                                                         Class: 1,
313                                                         Type:  1,
314                                                         Labels: []icmp.MPLSLabel{
315                                                                 {
316                                                                         Label: 16014,
317                                                                         TC:    0x4,
318                                                                         S:     true,
319                                                                         TTL:   255,
320                                                                 },
321                                                         },
322                                                 },
323                                                 &icmp.InterfaceInfo{
324                                                         Class: 2,
325                                                         Type:  0x2f,
326                                                         Interface: &net.Interface{
327                                                                 Index: 16,
328                                                                 Name:  "en102",
329                                                                 MTU:   8192,
330                                                         },
331                                                         Addr: &net.IPAddr{
332                                                                 IP:   net.ParseIP("fe80::1"),
333                                                                 Zone: "en102",
334                                                         },
335                                                 },
336                                         },
337                                 },
338                         },
339                         {
340                                 Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
341                                 Body: &icmp.ExtendedEchoRequest{
342                                         ID: 1, Seq: 2, Local: true,
343                                         Extensions: []icmp.Extension{
344                                                 &icmp.InterfaceIdent{
345                                                         Class: 3,
346                                                         Type:  1,
347                                                         Name:  "en101",
348                                                 },
349                                         },
350                                 },
351                         },
352                         {
353                                 Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
354                                 Body: &icmp.ExtendedEchoRequest{
355                                         ID: 1, Seq: 2, Local: true,
356                                         Extensions: []icmp.Extension{
357                                                 &icmp.InterfaceIdent{
358                                                         Class: 3,
359                                                         Type:  2,
360                                                         Index: 911,
361                                                 },
362                                         },
363                                 },
364                         },
365                         {
366                                 Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
367                                 Body: &icmp.ExtendedEchoRequest{
368                                         ID: 1, Seq: 2,
369                                         Extensions: []icmp.Extension{
370                                                 &icmp.InterfaceIdent{
371                                                         Class: 3,
372                                                         Type:  3,
373                                                         AFI:   iana.AddrFamilyIPv4,
374                                                         Addr:  []byte{192, 0, 2, 1},
375                                                 },
376                                         },
377                                 },
378                         },
379                 } {
380                         if err := fn(t, iana.ProtocolIPv6ICMP, tm); err != nil {
381                                 t.Errorf("#%d: %v", i, err)
382                         }
383                 }
384         })
385 }
386
387 func dumpExtensions(gotExts, wantExts []icmp.Extension) string {
388         var s string
389         for i, got := range gotExts {
390                 switch got := got.(type) {
391                 case *icmp.MPLSLabelStack:
392                         want := wantExts[i].(*icmp.MPLSLabelStack)
393                         if !reflect.DeepEqual(got, want) {
394                                 s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
395                         }
396                 case *icmp.InterfaceInfo:
397                         want := wantExts[i].(*icmp.InterfaceInfo)
398                         if !reflect.DeepEqual(got, want) {
399                                 s += fmt.Sprintf("#%d: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
400                         }
401                 case *icmp.InterfaceIdent:
402                         want := wantExts[i].(*icmp.InterfaceIdent)
403                         if !reflect.DeepEqual(got, want) {
404                                 s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
405                         }
406                 case *icmp.RawExtension:
407                         s += fmt.Sprintf("#%d: raw extension\n", i)
408                 }
409         }
410         if len(s) == 0 {
411                 s += "empty extension"
412         }
413         return s[:len(s)-1]
414 }
415
416 func TestMultipartMessageBodyLen(t *testing.T) {
417         for i, tt := range []struct {
418                 proto int
419                 in    icmp.MessageBody
420                 out   int
421         }{
422                 {
423                         iana.ProtocolICMP,
424                         &icmp.DstUnreach{
425                                 Data: make([]byte, ipv4.HeaderLen),
426                         },
427                         4 + ipv4.HeaderLen, // unused and original datagram
428                 },
429                 {
430                         iana.ProtocolICMP,
431                         &icmp.TimeExceeded{
432                                 Data: make([]byte, ipv4.HeaderLen),
433                         },
434                         4 + ipv4.HeaderLen, // unused and original datagram
435                 },
436                 {
437                         iana.ProtocolICMP,
438                         &icmp.ParamProb{
439                                 Data: make([]byte, ipv4.HeaderLen),
440                         },
441                         4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
442                 },
443
444                 {
445                         iana.ProtocolICMP,
446                         &icmp.ParamProb{
447                                 Data: make([]byte, ipv4.HeaderLen),
448                                 Extensions: []icmp.Extension{
449                                         &icmp.MPLSLabelStack{},
450                                 },
451                         },
452                         4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
453                 },
454                 {
455                         iana.ProtocolICMP,
456                         &icmp.ParamProb{
457                                 Data: make([]byte, 128),
458                                 Extensions: []icmp.Extension{
459                                         &icmp.MPLSLabelStack{},
460                                 },
461                         },
462                         4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
463                 },
464                 {
465                         iana.ProtocolICMP,
466                         &icmp.ParamProb{
467                                 Data: make([]byte, 129),
468                                 Extensions: []icmp.Extension{
469                                         &icmp.MPLSLabelStack{},
470                                 },
471                         },
472                         4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
473                 },
474
475                 {
476                         iana.ProtocolIPv6ICMP,
477                         &icmp.DstUnreach{
478                                 Data: make([]byte, ipv6.HeaderLen),
479                         },
480                         4 + ipv6.HeaderLen, // unused and original datagram
481                 },
482                 {
483                         iana.ProtocolIPv6ICMP,
484                         &icmp.PacketTooBig{
485                                 Data: make([]byte, ipv6.HeaderLen),
486                         },
487                         4 + ipv6.HeaderLen, // mtu and original datagram
488                 },
489                 {
490                         iana.ProtocolIPv6ICMP,
491                         &icmp.TimeExceeded{
492                                 Data: make([]byte, ipv6.HeaderLen),
493                         },
494                         4 + ipv6.HeaderLen, // unused and original datagram
495                 },
496                 {
497                         iana.ProtocolIPv6ICMP,
498                         &icmp.ParamProb{
499                                 Data: make([]byte, ipv6.HeaderLen),
500                         },
501                         4 + ipv6.HeaderLen, // pointer and original datagram
502                 },
503
504                 {
505                         iana.ProtocolIPv6ICMP,
506                         &icmp.DstUnreach{
507                                 Data: make([]byte, 127),
508                                 Extensions: []icmp.Extension{
509                                         &icmp.MPLSLabelStack{},
510                                 },
511                         },
512                         4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
513                 },
514                 {
515                         iana.ProtocolIPv6ICMP,
516                         &icmp.DstUnreach{
517                                 Data: make([]byte, 128),
518                                 Extensions: []icmp.Extension{
519                                         &icmp.MPLSLabelStack{},
520                                 },
521                         },
522                         4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
523                 },
524                 {
525                         iana.ProtocolIPv6ICMP,
526                         &icmp.DstUnreach{
527                                 Data: make([]byte, 129),
528                                 Extensions: []icmp.Extension{
529                                         &icmp.MPLSLabelStack{},
530                                 },
531                         },
532                         4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
533                 },
534
535                 {
536                         iana.ProtocolICMP,
537                         &icmp.ExtendedEchoRequest{},
538                         4, // [id, seq, l-bit]
539                 },
540                 {
541                         iana.ProtocolICMP,
542                         &icmp.ExtendedEchoRequest{
543                                 Extensions: []icmp.Extension{
544                                         &icmp.InterfaceIdent{},
545                                 },
546                         },
547                         4 + 4 + 4, // [id, seq, l-bit], extension header, object header
548                 },
549                 {
550                         iana.ProtocolIPv6ICMP,
551                         &icmp.ExtendedEchoRequest{
552                                 Extensions: []icmp.Extension{
553                                         &icmp.InterfaceIdent{
554                                                 Type: 3,
555                                                 AFI:  iana.AddrFamilyNSAP,
556                                                 Addr: []byte{0x49, 0x00, 0x01, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0x00},
557                                         },
558                                 },
559                         },
560                         4 + 4 + 4 + 16, // [id, seq, l-bit], extension header, object header, object payload
561                 },
562         } {
563                 if out := tt.in.Len(tt.proto); out != tt.out {
564                         t.Errorf("#%d: got %d; want %d", i, out, tt.out)
565                 }
566         }
567 }