github.com/vpnishe/netstack@v1.10.6/tcpip/header/ndp_test.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package header 16 17 import ( 18 "bytes" 19 "testing" 20 "time" 21 22 "github.com/vpnishe/netstack/tcpip" 23 ) 24 25 // TestNDPNeighborSolicit tests the functions of NDPNeighborSolicit. 26 func TestNDPNeighborSolicit(t *testing.T) { 27 b := []byte{ 28 0, 0, 0, 0, 29 1, 2, 3, 4, 30 5, 6, 7, 8, 31 9, 10, 11, 12, 32 13, 14, 15, 16, 33 } 34 35 // Test getting the Target Address. 36 ns := NDPNeighborSolicit(b) 37 addr := tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10") 38 if got := ns.TargetAddress(); got != addr { 39 t.Errorf("got ns.TargetAddress = %s, want %s", got, addr) 40 } 41 42 // Test updating the Target Address. 43 addr2 := tcpip.Address("\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x11") 44 ns.SetTargetAddress(addr2) 45 if got := ns.TargetAddress(); got != addr2 { 46 t.Errorf("got ns.TargetAddress = %s, want %s", got, addr2) 47 } 48 // Make sure the address got updated in the backing buffer. 49 if got := tcpip.Address(b[ndpNSTargetAddessOffset:][:IPv6AddressSize]); got != addr2 { 50 t.Errorf("got targetaddress buffer = %s, want %s", got, addr2) 51 } 52 } 53 54 // TestNDPNeighborAdvert tests the functions of NDPNeighborAdvert. 55 func TestNDPNeighborAdvert(t *testing.T) { 56 b := []byte{ 57 160, 0, 0, 0, 58 1, 2, 3, 4, 59 5, 6, 7, 8, 60 9, 10, 11, 12, 61 13, 14, 15, 16, 62 } 63 64 // Test getting the Target Address. 65 na := NDPNeighborAdvert(b) 66 addr := tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10") 67 if got := na.TargetAddress(); got != addr { 68 t.Errorf("got TargetAddress = %s, want %s", got, addr) 69 } 70 71 // Test getting the Router Flag. 72 if got := na.RouterFlag(); !got { 73 t.Errorf("got RouterFlag = false, want = true") 74 } 75 76 // Test getting the Solicited Flag. 77 if got := na.SolicitedFlag(); got { 78 t.Errorf("got SolicitedFlag = true, want = false") 79 } 80 81 // Test getting the Override Flag. 82 if got := na.OverrideFlag(); !got { 83 t.Errorf("got OverrideFlag = false, want = true") 84 } 85 86 // Test updating the Target Address. 87 addr2 := tcpip.Address("\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x11") 88 na.SetTargetAddress(addr2) 89 if got := na.TargetAddress(); got != addr2 { 90 t.Errorf("got TargetAddress = %s, want %s", got, addr2) 91 } 92 // Make sure the address got updated in the backing buffer. 93 if got := tcpip.Address(b[ndpNATargetAddressOffset:][:IPv6AddressSize]); got != addr2 { 94 t.Errorf("got targetaddress buffer = %s, want %s", got, addr2) 95 } 96 97 // Test updating the Router Flag. 98 na.SetRouterFlag(false) 99 if got := na.RouterFlag(); got { 100 t.Errorf("got RouterFlag = true, want = false") 101 } 102 103 // Test updating the Solicited Flag. 104 na.SetSolicitedFlag(true) 105 if got := na.SolicitedFlag(); !got { 106 t.Errorf("got SolicitedFlag = false, want = true") 107 } 108 109 // Test updating the Override Flag. 110 na.SetOverrideFlag(false) 111 if got := na.OverrideFlag(); got { 112 t.Errorf("got OverrideFlag = true, want = false") 113 } 114 115 // Make sure flags got updated in the backing buffer. 116 if got := b[ndpNAFlagsOffset]; got != 64 { 117 t.Errorf("got flags byte = %d, want = 64") 118 } 119 } 120 121 func TestNDPRouterAdvert(t *testing.T) { 122 b := []byte{ 123 64, 128, 1, 2, 124 3, 4, 5, 6, 125 7, 8, 9, 10, 126 } 127 128 ra := NDPRouterAdvert(b) 129 130 if got := ra.CurrHopLimit(); got != 64 { 131 t.Errorf("got ra.CurrHopLimit = %d, want = 64", got) 132 } 133 134 if got := ra.ManagedAddrConfFlag(); !got { 135 t.Errorf("got ManagedAddrConfFlag = false, want = true") 136 } 137 138 if got := ra.OtherConfFlag(); got { 139 t.Errorf("got OtherConfFlag = true, want = false") 140 } 141 142 if got, want := ra.RouterLifetime(), time.Second*258; got != want { 143 t.Errorf("got ra.RouterLifetime = %d, want = %d", got, want) 144 } 145 146 if got, want := ra.ReachableTime(), time.Millisecond*50595078; got != want { 147 t.Errorf("got ra.ReachableTime = %d, want = %d", got, want) 148 } 149 150 if got, want := ra.RetransTimer(), time.Millisecond*117967114; got != want { 151 t.Errorf("got ra.RetransTimer = %d, want = %d", got, want) 152 } 153 } 154 155 // TestNDPTargetLinkLayerAddressOptionEthernetAddress tests getting the 156 // Ethernet address from an NDPTargetLinkLayerAddressOption. 157 func TestNDPTargetLinkLayerAddressOptionEthernetAddress(t *testing.T) { 158 tests := []struct { 159 name string 160 buf []byte 161 expected tcpip.LinkAddress 162 }{ 163 { 164 "ValidMAC", 165 []byte{1, 2, 3, 4, 5, 6}, 166 tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"), 167 }, 168 { 169 "TLLBodyTooShort", 170 []byte{1, 2, 3, 4, 5}, 171 tcpip.LinkAddress([]byte(nil)), 172 }, 173 { 174 "TLLBodyLargerThanNeeded", 175 []byte{1, 2, 3, 4, 5, 6, 7, 8}, 176 tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"), 177 }, 178 } 179 180 for _, test := range tests { 181 t.Run(test.name, func(t *testing.T) { 182 tll := NDPTargetLinkLayerAddressOption(test.buf) 183 if got := tll.EthernetAddress(); got != test.expected { 184 t.Errorf("got tll.EthernetAddress = %s, want = %s", got, test.expected) 185 } 186 }) 187 } 188 189 } 190 191 // TestNDPTargetLinkLayerAddressOptionSerialize tests serializing a 192 // NDPTargetLinkLayerAddressOption. 193 func TestNDPTargetLinkLayerAddressOptionSerialize(t *testing.T) { 194 tests := []struct { 195 name string 196 buf []byte 197 expectedBuf []byte 198 addr tcpip.LinkAddress 199 }{ 200 { 201 "Ethernet", 202 make([]byte, 8), 203 []byte{2, 1, 1, 2, 3, 4, 5, 6}, 204 "\x01\x02\x03\x04\x05\x06", 205 }, 206 { 207 "Padding", 208 []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 209 []byte{2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0}, 210 "\x01\x02\x03\x04\x05\x06\x07\x08", 211 }, 212 { 213 "Empty", 214 []byte{}, 215 []byte{}, 216 "", 217 }, 218 } 219 220 for _, test := range tests { 221 t.Run(test.name, func(t *testing.T) { 222 opts := NDPOptions(test.buf) 223 serializer := NDPOptionsSerializer{ 224 NDPTargetLinkLayerAddressOption(test.addr), 225 } 226 if got, want := int(serializer.Length()), len(test.expectedBuf); got != want { 227 t.Fatalf("got Length = %d, want = %d", got, want) 228 } 229 opts.Serialize(serializer) 230 if !bytes.Equal(test.buf, test.expectedBuf) { 231 t.Fatalf("got b = %d, want = %d", test.buf, test.expectedBuf) 232 } 233 234 it, err := opts.Iter(true) 235 if err != nil { 236 t.Fatalf("got Iter = (_, %s), want = (_, nil)", err) 237 } 238 239 if len(test.expectedBuf) > 0 { 240 next, done, err := it.Next() 241 if err != nil { 242 t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err) 243 } 244 if done { 245 t.Fatal("got Next = (_, true, _), want = (_, false, _)") 246 } 247 if got := next.Type(); got != NDPTargetLinkLayerAddressOptionType { 248 t.Fatalf("got Type %= %d, want = %d", got, NDPTargetLinkLayerAddressOptionType) 249 } 250 tll := next.(NDPTargetLinkLayerAddressOption) 251 if got, want := []byte(tll), test.expectedBuf[2:]; !bytes.Equal(got, want) { 252 t.Fatalf("got Next = (%x, _, _), want = (%x, _, _)", got, want) 253 } 254 255 if got, want := tll.EthernetAddress(), tcpip.LinkAddress(test.expectedBuf[2:][:EthernetAddressSize]); got != want { 256 t.Errorf("got tll.MACAddress = %s, want = %s", got, want) 257 } 258 } 259 260 // Iterator should not return anything else. 261 next, done, err := it.Next() 262 if err != nil { 263 t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err) 264 } 265 if !done { 266 t.Error("got Next = (_, false, _), want = (_, true, _)") 267 } 268 if next != nil { 269 t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next) 270 } 271 }) 272 } 273 } 274 275 // TestNDPPrefixInformationOption tests the field getters and serialization of a 276 // NDPPrefixInformation. 277 func TestNDPPrefixInformationOption(t *testing.T) { 278 b := []byte{ 279 43, 127, 280 1, 2, 3, 4, 281 5, 6, 7, 8, 282 5, 5, 5, 5, 283 9, 10, 11, 12, 284 13, 14, 15, 16, 285 17, 18, 19, 20, 286 21, 22, 23, 24, 287 } 288 289 targetBuf := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} 290 opts := NDPOptions(targetBuf) 291 serializer := NDPOptionsSerializer{ 292 NDPPrefixInformation(b), 293 } 294 opts.Serialize(serializer) 295 expectedBuf := []byte{ 296 3, 4, 43, 64, 297 1, 2, 3, 4, 298 5, 6, 7, 8, 299 0, 0, 0, 0, 300 9, 10, 11, 12, 301 13, 14, 15, 16, 302 17, 18, 19, 20, 303 21, 22, 23, 24, 304 } 305 if !bytes.Equal(targetBuf, expectedBuf) { 306 t.Fatalf("got targetBuf = %x, want = %x", targetBuf, expectedBuf) 307 } 308 309 it, err := opts.Iter(true) 310 if err != nil { 311 t.Fatalf("got Iter = (_, %s), want = (_, nil)", err) 312 } 313 314 next, done, err := it.Next() 315 if err != nil { 316 t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err) 317 } 318 if done { 319 t.Fatal("got Next = (_, true, _), want = (_, false, _)") 320 } 321 if got := next.Type(); got != NDPPrefixInformationType { 322 t.Errorf("got Type = %d, want = %d", got, NDPPrefixInformationType) 323 } 324 325 pi := next.(NDPPrefixInformation) 326 327 if got := pi.Type(); got != 3 { 328 t.Errorf("got Type = %d, want = 3", got) 329 } 330 331 if got := pi.Length(); got != 30 { 332 t.Errorf("got Length = %d, want = 30", got) 333 } 334 335 if got := pi.PrefixLength(); got != 43 { 336 t.Errorf("got PrefixLength = %d, want = 43", got) 337 } 338 339 if pi.OnLinkFlag() { 340 t.Error("got OnLinkFlag = true, want = false") 341 } 342 343 if !pi.AutonomousAddressConfigurationFlag() { 344 t.Error("got AutonomousAddressConfigurationFlag = false, want = true") 345 } 346 347 if got, want := pi.ValidLifetime(), 16909060*time.Second; got != want { 348 t.Errorf("got ValidLifetime = %d, want = %d", got, want) 349 } 350 351 if got, want := pi.PreferredLifetime(), 84281096*time.Second; got != want { 352 t.Errorf("got PreferredLifetime = %d, want = %d", got, want) 353 } 354 355 if got, want := pi.Prefix(), tcpip.Address("\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18"); got != want { 356 t.Errorf("got Prefix = %s, want = %s", got, want) 357 } 358 359 // Iterator should not return anything else. 360 next, done, err = it.Next() 361 if err != nil { 362 t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err) 363 } 364 if !done { 365 t.Error("got Next = (_, false, _), want = (_, true, _)") 366 } 367 if next != nil { 368 t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next) 369 } 370 } 371 372 // TestNDPOptionsIterCheck tests that Iter will return false if the NDPOptions 373 // the iterator was returned for is malformed. 374 func TestNDPOptionsIterCheck(t *testing.T) { 375 tests := []struct { 376 name string 377 buf []byte 378 expected error 379 }{ 380 { 381 "ZeroLengthField", 382 []byte{0, 0, 0, 0, 0, 0, 0, 0}, 383 ErrNDPOptZeroLength, 384 }, 385 { 386 "ValidTargetLinkLayerAddressOption", 387 []byte{2, 1, 1, 2, 3, 4, 5, 6}, 388 nil, 389 }, 390 { 391 "TooSmallTargetLinkLayerAddressOption", 392 []byte{2, 1, 1, 2, 3, 4, 5}, 393 ErrNDPOptBufExhausted, 394 }, 395 { 396 "ValidPrefixInformation", 397 []byte{ 398 3, 4, 43, 64, 399 1, 2, 3, 4, 400 5, 6, 7, 8, 401 0, 0, 0, 0, 402 9, 10, 11, 12, 403 13, 14, 15, 16, 404 17, 18, 19, 20, 405 21, 22, 23, 24, 406 }, 407 nil, 408 }, 409 { 410 "TooSmallPrefixInformation", 411 []byte{ 412 3, 4, 43, 64, 413 1, 2, 3, 4, 414 5, 6, 7, 8, 415 0, 0, 0, 0, 416 9, 10, 11, 12, 417 13, 14, 15, 16, 418 17, 18, 19, 20, 419 21, 22, 23, 420 }, 421 ErrNDPOptBufExhausted, 422 }, 423 { 424 "InvalidPrefixInformationLength", 425 []byte{ 426 3, 3, 43, 64, 427 1, 2, 3, 4, 428 5, 6, 7, 8, 429 0, 0, 0, 0, 430 9, 10, 11, 12, 431 13, 14, 15, 16, 432 }, 433 ErrNDPOptMalformedBody, 434 }, 435 { 436 "ValidTargetLinkLayerAddressWithPrefixInformation", 437 []byte{ 438 // Target Link-Layer Address. 439 2, 1, 1, 2, 3, 4, 5, 6, 440 441 // Prefix information. 442 3, 4, 43, 64, 443 1, 2, 3, 4, 444 5, 6, 7, 8, 445 0, 0, 0, 0, 446 9, 10, 11, 12, 447 13, 14, 15, 16, 448 17, 18, 19, 20, 449 21, 22, 23, 24, 450 }, 451 nil, 452 }, 453 { 454 "ValidTargetLinkLayerAddressWithPrefixInformationWithUnrecognized", 455 []byte{ 456 // Target Link-Layer Address. 457 2, 1, 1, 2, 3, 4, 5, 6, 458 459 // 255 is an unrecognized type. If 255 ends up 460 // being the type for some recognized type, 461 // update 255 to some other unrecognized value. 462 255, 2, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 463 464 // Prefix information. 465 3, 4, 43, 64, 466 1, 2, 3, 4, 467 5, 6, 7, 8, 468 0, 0, 0, 0, 469 9, 10, 11, 12, 470 13, 14, 15, 16, 471 17, 18, 19, 20, 472 21, 22, 23, 24, 473 }, 474 nil, 475 }, 476 } 477 478 for _, test := range tests { 479 t.Run(test.name, func(t *testing.T) { 480 opts := NDPOptions(test.buf) 481 482 if _, err := opts.Iter(true); err != test.expected { 483 t.Fatalf("got Iter(true) = (_, %v), want = (_, %v)", err, test.expected) 484 } 485 486 // test.buf may be malformed but we chose not to check 487 // the iterator so it must return true. 488 if _, err := opts.Iter(false); err != nil { 489 t.Fatalf("got Iter(false) = (_, %s), want = (_, nil)", err) 490 } 491 }) 492 } 493 } 494 495 // TestNDPOptionsIter tests that we can iterator over a valid NDPOptions. Note, 496 // this test does not actually check any of the option's getters, it simply 497 // checks the option Type and Body. We have other tests that tests the option 498 // field gettings given an option body and don't need to duplicate those tests 499 // here. 500 func TestNDPOptionsIter(t *testing.T) { 501 buf := []byte{ 502 // Target Link-Layer Address. 503 2, 1, 1, 2, 3, 4, 5, 6, 504 505 // 255 is an unrecognized type. If 255 ends up being the type 506 // for some recognized type, update 255 to some other 507 // unrecognized value. Note, this option should be skipped when 508 // iterating. 509 255, 2, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 510 511 // Prefix information. 512 3, 4, 43, 64, 513 1, 2, 3, 4, 514 5, 6, 7, 8, 515 0, 0, 0, 0, 516 9, 10, 11, 12, 517 13, 14, 15, 16, 518 17, 18, 19, 20, 519 21, 22, 23, 24, 520 } 521 522 opts := NDPOptions(buf) 523 it, err := opts.Iter(true) 524 if err != nil { 525 t.Fatalf("got Iter = (_, %s), want = (_, nil)", err) 526 } 527 528 // Test the first (Taret Link-Layer) option. 529 next, done, err := it.Next() 530 if err != nil { 531 t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err) 532 } 533 if done { 534 t.Fatal("got Next = (_, true, _), want = (_, false, _)") 535 } 536 if got, want := []byte(next.(NDPTargetLinkLayerAddressOption)), buf[2:][:6]; !bytes.Equal(got, want) { 537 t.Errorf("got Next = (%x, _, _), want = (%x, _, _)", got, want) 538 } 539 if got := next.Type(); got != NDPTargetLinkLayerAddressOptionType { 540 t.Errorf("got Type = %d, want = %d", got, NDPTargetLinkLayerAddressOptionType) 541 } 542 543 // Test the next (Prefix Information) option. 544 // Note, the unrecognized option should be skipped. 545 next, done, err = it.Next() 546 if err != nil { 547 t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err) 548 } 549 if done { 550 t.Fatal("got Next = (_, true, _), want = (_, false, _)") 551 } 552 if got, want := next.(NDPPrefixInformation), buf[26:][:30]; !bytes.Equal(got, want) { 553 t.Errorf("got Next = (%x, _, _), want = (%x, _, _)", got, want) 554 } 555 if got := next.Type(); got != NDPPrefixInformationType { 556 t.Errorf("got Type = %d, want = %d", got, NDPPrefixInformationType) 557 } 558 559 // Iterator should not return anything else. 560 next, done, err = it.Next() 561 if err != nil { 562 t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err) 563 } 564 if !done { 565 t.Error("got Next = (_, false, _), want = (_, true, _)") 566 } 567 if next != nil { 568 t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next) 569 } 570 }