Mikio Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 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 | "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 | |
| 19 | var 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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 37 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 49 | }, |
| 50 | }, |
| 51 | }, |
| 52 | { |
| 53 | Type: ipv4.ICMPTypeTimeExceeded, Code: 1, |
| 54 | Body: &icmp.TimeExceeded{ |
| 55 | Data: []byte("ERROR-INVOKING-PACKET"), |
| 56 | Extensions: []icmp.Extension{ |
Mikio Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 57 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 69 | &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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 102 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 126 | }, |
| 127 | }, |
| 128 | }, |
| 129 | } |
| 130 | |
| 131 | func 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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 151 | t.Error(dumpExtensions(i, got.Extensions, want.Extensions)) |
Mikio Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 152 | } |
| 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 | |
| 176 | var 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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 194 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 207 | }, |
| 208 | }, |
| 209 | }, |
| 210 | { |
| 211 | Type: ipv6.ICMPTypeTimeExceeded, Code: 1, |
| 212 | Body: &icmp.TimeExceeded{ |
| 213 | Data: []byte("ERROR-INVOKING-PACKET"), |
| 214 | Extensions: []icmp.Extension{ |
Mikio Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 215 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 228 | &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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 240 | &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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 253 | }, |
| 254 | }, |
| 255 | }, |
| 256 | } |
| 257 | |
| 258 | func 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 | |
| 298 | func 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 Hara | c84eff7 | 2015-01-21 20:17:41 +0900 | [diff] [blame] | 307 | 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 Hara | 71586c3 | 2015-01-15 01:00:16 +0900 | [diff] [blame] | 312 | } |
| 313 | } |
| 314 | return s[:len(s)-1] |
| 315 | } |
Mikio Hara | 62ac18b | 2015-11-04 16:49:45 +0900 | [diff] [blame] | 316 | |
| 317 | var 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 | |
| 436 | func 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 | } |