gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/network/ipv6/ipv6_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 ipv6 16 17 import ( 18 "bytes" 19 "encoding/hex" 20 "fmt" 21 "io/ioutil" 22 "math" 23 "net" 24 "reflect" 25 "testing" 26 27 "github.com/google/go-cmp/cmp" 28 "gvisor.dev/gvisor/pkg/buffer" 29 "gvisor.dev/gvisor/pkg/sync" 30 "gvisor.dev/gvisor/pkg/tcpip" 31 "gvisor.dev/gvisor/pkg/tcpip/checker" 32 "gvisor.dev/gvisor/pkg/tcpip/checksum" 33 "gvisor.dev/gvisor/pkg/tcpip/header" 34 "gvisor.dev/gvisor/pkg/tcpip/link/channel" 35 iptestutil "gvisor.dev/gvisor/pkg/tcpip/network/internal/testutil" 36 "gvisor.dev/gvisor/pkg/tcpip/prependable" 37 "gvisor.dev/gvisor/pkg/tcpip/stack" 38 "gvisor.dev/gvisor/pkg/tcpip/testutil" 39 "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" 40 "gvisor.dev/gvisor/pkg/tcpip/transport/udp" 41 "gvisor.dev/gvisor/pkg/waiter" 42 ) 43 44 var ( 45 addr1 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) 46 addr2 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02")) 47 // The least significant 3 bytes are the same as addr2 so both addr2 and 48 // addr3 will have the same solicited-node address. 49 addr3 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x02")) 50 addr4 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x03")) 51 ) 52 53 const ( 54 // Tests use the extension header identifier values as uint8 instead of 55 // header.IPv6ExtensionHeaderIdentifier. 56 hopByHopExtHdrID = uint8(header.IPv6HopByHopOptionsExtHdrIdentifier) 57 routingExtHdrID = uint8(header.IPv6RoutingExtHdrIdentifier) 58 fragmentExtHdrID = uint8(header.IPv6FragmentExtHdrIdentifier) 59 destinationExtHdrID = uint8(header.IPv6DestinationOptionsExtHdrIdentifier) 60 noNextHdrID = uint8(header.IPv6NoNextHeaderIdentifier) 61 unknownHdrID = uint8(header.IPv6UnknownExtHdrIdentifier) 62 63 extraHeaderReserve = 50 64 ) 65 66 var _ stack.MulticastForwardingEventDispatcher = (*fakeMulticastEventDispatcher)(nil) 67 68 type fakeMulticastEventDispatcher struct{} 69 70 func (m *fakeMulticastEventDispatcher) OnMissingRoute(context stack.MulticastPacketContext) {} 71 72 func (m *fakeMulticastEventDispatcher) OnUnexpectedInputInterface(context stack.MulticastPacketContext, expectedInputInterface tcpip.NICID) { 73 } 74 75 // testReceiveICMP tests receiving an ICMP packet from src to dst. want is the 76 // expected Neighbor Advertisement received count after receiving the packet. 77 func testReceiveICMP(t *testing.T, s *stack.Stack, e *channel.Endpoint, src, dst tcpip.Address, want uint64) { 78 t.Helper() 79 80 // Receive ICMP packet. 81 hdr := prependable.New(header.IPv6MinimumSize + header.ICMPv6NeighborAdvertMinimumSize) 82 pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertMinimumSize)) 83 pkt.SetType(header.ICMPv6NeighborAdvert) 84 pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 85 Header: pkt, 86 Src: src, 87 Dst: dst, 88 })) 89 payloadLength := hdr.UsedLength() 90 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 91 ip.Encode(&header.IPv6Fields{ 92 PayloadLength: uint16(payloadLength), 93 TransportProtocol: header.ICMPv6ProtocolNumber, 94 HopLimit: 255, 95 SrcAddr: src, 96 DstAddr: dst, 97 }) 98 99 pktBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{ 100 Payload: buffer.MakeWithData(hdr.View()), 101 }) 102 e.InjectInbound(ProtocolNumber, pktBuf) 103 pktBuf.DecRef() 104 105 stats := s.Stats().ICMP.V6.PacketsReceived 106 107 if got := stats.NeighborAdvert.Value(); got != want { 108 t.Fatalf("got NeighborAdvert = %d, want = %d", got, want) 109 } 110 } 111 112 // testReceiveUDP tests receiving a UDP packet from src to dst. want is the 113 // expected UDP received count after receiving the packet. 114 func testReceiveUDP(t *testing.T, s *stack.Stack, e *channel.Endpoint, src, dst tcpip.Address, want uint64) { 115 t.Helper() 116 117 wq := waiter.Queue{} 118 we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) 119 wq.EventRegister(&we) 120 defer wq.EventUnregister(&we) 121 defer close(ch) 122 123 ep, err := s.NewEndpoint(udp.ProtocolNumber, ProtocolNumber, &wq) 124 if err != nil { 125 t.Fatalf("NewEndpoint failed: %v", err) 126 } 127 defer ep.Close() 128 129 if err := ep.Bind(tcpip.FullAddress{Addr: dst, Port: 80}); err != nil { 130 t.Fatalf("ep.Bind(...) failed: %v", err) 131 } 132 133 // Receive UDP Packet. 134 hdr := prependable.New(header.IPv6MinimumSize + header.UDPMinimumSize) 135 u := header.UDP(hdr.Prepend(header.UDPMinimumSize)) 136 u.Encode(&header.UDPFields{ 137 SrcPort: 5555, 138 DstPort: 80, 139 Length: header.UDPMinimumSize, 140 }) 141 142 // UDP pseudo-header checksum. 143 sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, src, dst, header.UDPMinimumSize) 144 145 // UDP checksum 146 sum = checksum.Checksum(nil, sum) 147 u.SetChecksum(^u.CalculateChecksum(sum)) 148 149 payloadLength := hdr.UsedLength() 150 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 151 ip.Encode(&header.IPv6Fields{ 152 PayloadLength: uint16(payloadLength), 153 TransportProtocol: udp.ProtocolNumber, 154 HopLimit: 255, 155 SrcAddr: src, 156 DstAddr: dst, 157 }) 158 159 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 160 Payload: buffer.MakeWithData(hdr.View()), 161 }) 162 e.InjectInbound(ProtocolNumber, pkt) 163 pkt.DecRef() 164 165 stat := s.Stats().UDP.PacketsReceived 166 167 if got := stat.Value(); got != want { 168 t.Fatalf("got UDPPacketsReceived = %d, want = %d", got, want) 169 } 170 } 171 172 func compareFragments(packets []*stack.PacketBuffer, sourcePacket *stack.PacketBuffer, mtu uint32, wantFragments []fragmentInfo, proto tcpip.TransportProtocolNumber) error { 173 // sourcePacket does not have its IP Header populated. Let's copy the one 174 // from the first fragment. 175 source := header.IPv6(packets[0].NetworkHeader().Slice()) 176 sourceIPHeadersLen := len(source) 177 view := sourcePacket.ToView() 178 defer view.Release() 179 source = append(source, view.AsSlice()...) 180 181 var reassembledPayload buffer.Buffer 182 defer reassembledPayload.Release() 183 for i, fragment := range packets { 184 // Confirm that the packet is valid. 185 allBytes := fragment.ToBuffer() 186 defer allBytes.Release() 187 fragmentIPHeaders := header.IPv6(allBytes.Flatten()) 188 if !fragmentIPHeaders.IsValid(len(fragmentIPHeaders)) { 189 return fmt.Errorf("fragment #%d: IP packet is invalid:\n%s", i, hex.Dump(fragmentIPHeaders)) 190 } 191 192 fragmentIPHeadersLength := len(fragment.NetworkHeader().Slice()) 193 if fragmentIPHeadersLength != sourceIPHeadersLen { 194 return fmt.Errorf("fragment #%d: got fragmentIPHeadersLength = %d, want = %d", i, fragmentIPHeadersLength, sourceIPHeadersLen) 195 } 196 197 if got := len(fragmentIPHeaders); got > int(mtu) { 198 return fmt.Errorf("fragment #%d: got len(fragmentIPHeaders) = %d, want <= %d", i, got, mtu) 199 } 200 201 sourceIPHeader := source[:header.IPv6MinimumSize] 202 fragmentIPHeader := fragmentIPHeaders[:header.IPv6MinimumSize] 203 204 if got := fragmentIPHeaders.PayloadLength(); got != wantFragments[i].payloadSize { 205 return fmt.Errorf("fragment #%d: got fragmentIPHeaders.PayloadLength() = %d, want = %d", i, got, wantFragments[i].payloadSize) 206 } 207 208 // We expect the IPv6 Header to be similar across each fragment, besides the 209 // payload length. 210 sourceIPHeader.SetPayloadLength(0) 211 fragmentIPHeader.SetPayloadLength(0) 212 if diff := cmp.Diff(fragmentIPHeader, sourceIPHeader); diff != "" { 213 return fmt.Errorf("fragment #%d: fragmentIPHeader mismatch (-want +got):\n%s", i, diff) 214 } 215 216 if got := fragment.AvailableHeaderBytes(); got != extraHeaderReserve { 217 return fmt.Errorf("fragment #%d: got packet.AvailableHeaderBytes() = %d, want = %d", i, got, extraHeaderReserve) 218 } 219 if fragment.NetworkProtocolNumber != sourcePacket.NetworkProtocolNumber { 220 return fmt.Errorf("fragment #%d: got fragment.NetworkProtocolNumber = %d, want = %d", i, fragment.NetworkProtocolNumber, sourcePacket.NetworkProtocolNumber) 221 } 222 223 if len(packets) > 1 { 224 // If the source packet was big enough that it needed fragmentation, let's 225 // inspect the fragment header. Because no other extension headers are 226 // supported, it will always be the last extension header. 227 fragmentHeader := header.IPv6Fragment(fragmentIPHeaders[fragmentIPHeadersLength-header.IPv6FragmentHeaderSize : fragmentIPHeadersLength]) 228 229 if got := fragmentHeader.More(); got != wantFragments[i].more { 230 return fmt.Errorf("fragment #%d: got fragmentHeader.More() = %t, want = %t", i, got, wantFragments[i].more) 231 } 232 if got := fragmentHeader.FragmentOffset(); got != wantFragments[i].offset { 233 return fmt.Errorf("fragment #%d: got fragmentHeader.FragmentOffset() = %d, want = %d", i, got, wantFragments[i].offset) 234 } 235 if got := fragmentHeader.NextHeader(); got != uint8(proto) { 236 return fmt.Errorf("fragment #%d: got fragmentHeader.NextHeader() = %d, want = %d", i, got, uint8(proto)) 237 } 238 } 239 240 // Store the reassembled payload as we parse each fragment. The payload 241 // includes the Transport header and everything after. 242 reassembledPayload.Append(fragment.TransportHeader().View()) 243 reassembledPayload.Append(fragment.Data().AsRange().ToView()) 244 } 245 246 if diff := cmp.Diff([]byte(source[sourceIPHeadersLen:]), reassembledPayload.Flatten()); diff != "" { 247 return fmt.Errorf("reassembledPayload mismatch (-want +got):\n%s", diff) 248 } 249 250 return nil 251 } 252 253 // TestReceiveOnAllNodesMulticastAddr tests that IPv6 endpoints receive ICMP and 254 // UDP packets destined to the IPv6 link-local all-nodes multicast address. 255 func TestReceiveOnAllNodesMulticastAddr(t *testing.T) { 256 tests := []struct { 257 name string 258 rxf func(t *testing.T, s *stack.Stack, e *channel.Endpoint, src, dst tcpip.Address, want uint64) 259 }{ 260 {"ICMP", testReceiveICMP}, 261 {"UDP", testReceiveUDP}, 262 } 263 264 for _, test := range tests { 265 t.Run(test.name, func(t *testing.T) { 266 c := newTestContext() 267 defer c.cleanup() 268 s := c.s 269 270 e := channel.New(10, header.IPv6MinimumMTU, linkAddr1) 271 defer e.Close() 272 if err := s.CreateNIC(1, e); err != nil { 273 t.Fatalf("CreateNIC(_) = %s", err) 274 } 275 276 // Should receive a packet destined to the all-nodes 277 // multicast address. 278 test.rxf(t, s, e, addr1, header.IPv6AllNodesMulticastAddress, 1) 279 }) 280 } 281 } 282 283 // TestReceiveOnSolicitedNodeAddr tests that IPv6 endpoints receive ICMP and UDP 284 // packets destined to the IPv6 solicited-node address of an assigned IPv6 285 // address. 286 func TestReceiveOnSolicitedNodeAddr(t *testing.T) { 287 tests := []struct { 288 name string 289 rxf func(t *testing.T, s *stack.Stack, e *channel.Endpoint, src, dst tcpip.Address, want uint64) 290 }{ 291 {"ICMP", testReceiveICMP}, 292 {"UDP", testReceiveUDP}, 293 } 294 295 snmc := header.SolicitedNodeAddr(addr2) 296 297 for _, test := range tests { 298 t.Run(test.name, func(t *testing.T) { 299 c := newTestContext() 300 defer c.cleanup() 301 s := c.s 302 303 e := channel.New(1, header.IPv6MinimumMTU, linkAddr1) 304 defer e.Close() 305 if err := s.CreateNIC(nicID, e); err != nil { 306 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 307 } 308 309 s.SetRouteTable([]tcpip.Route{ 310 { 311 Destination: header.IPv6EmptySubnet, 312 NIC: nicID, 313 }, 314 }) 315 316 // Should not receive a packet destined to the solicited node address of 317 // addr2/addr3 yet as we haven't added those addresses. 318 test.rxf(t, s, e, addr1, snmc, 0) 319 320 protocolAddr2 := tcpip.ProtocolAddress{ 321 Protocol: ProtocolNumber, 322 AddressWithPrefix: addr2.WithPrefix(), 323 } 324 if err := s.AddProtocolAddress(nicID, protocolAddr2, stack.AddressProperties{}); err != nil { 325 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr2, err) 326 } 327 328 // Should receive a packet destined to the solicited node address of 329 // addr2/addr3 now that we have added added addr2. 330 test.rxf(t, s, e, addr1, snmc, 1) 331 332 protocolAddr3 := tcpip.ProtocolAddress{ 333 Protocol: ProtocolNumber, 334 AddressWithPrefix: addr3.WithPrefix(), 335 } 336 if err := s.AddProtocolAddress(nicID, protocolAddr3, stack.AddressProperties{}); err != nil { 337 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr3, err) 338 } 339 340 // Should still receive a packet destined to the solicited node address of 341 // addr2/addr3 now that we have added addr3. 342 test.rxf(t, s, e, addr1, snmc, 2) 343 344 if err := s.RemoveAddress(nicID, addr2); err != nil { 345 t.Fatalf("RemoveAddress(%d, %s) = %s", nicID, addr2, err) 346 } 347 348 // Should still receive a packet destined to the solicited node address of 349 // addr2/addr3 now that we have removed addr2. 350 test.rxf(t, s, e, addr1, snmc, 3) 351 352 // Make sure addr3's endpoint does not get removed from the NIC by 353 // incrementing its reference count with a route. 354 r, err := s.FindRoute(nicID, addr3, addr4, ProtocolNumber, false) 355 if err != nil { 356 t.Fatalf("FindRoute(%d, %s, %s, %d, false): %s", nicID, addr3, addr4, ProtocolNumber, err) 357 } 358 defer r.Release() 359 360 if err := s.RemoveAddress(nicID, addr3); err != nil { 361 t.Fatalf("RemoveAddress(%d, %s) = %s", nicID, addr3, err) 362 } 363 364 // Should not receive a packet destined to the solicited node address of 365 // addr2/addr3 yet as both of them got removed, even though a route using 366 // addr3 exists. 367 test.rxf(t, s, e, addr1, snmc, 3) 368 }) 369 } 370 } 371 372 // TestAddIpv6Address tests adding IPv6 addresses. 373 func TestAddIpv6Address(t *testing.T) { 374 const nicID = 1 375 376 tests := []struct { 377 name string 378 addr tcpip.Address 379 }{ 380 // This test is in response to b/140943433. 381 { 382 "Nil", 383 tcpip.Address{}, 384 }, 385 { 386 "ValidUnicast", 387 addr1, 388 }, 389 { 390 "ValidLinkLocalUnicast", 391 lladdr0, 392 }, 393 } 394 395 for _, test := range tests { 396 t.Run(test.name, func(t *testing.T) { 397 c := newTestContext() 398 defer c.cleanup() 399 s := c.s 400 401 if err := s.CreateNIC(nicID, &stubLinkEndpoint{}); err != nil { 402 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 403 } 404 405 protocolAddr := tcpip.ProtocolAddress{ 406 Protocol: ProtocolNumber, 407 AddressWithPrefix: test.addr.WithPrefix(), 408 } 409 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 410 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 411 } 412 413 if addr, err := s.GetMainNICAddress(nicID, ProtocolNumber); err != nil { 414 t.Fatalf("stack.GetMainNICAddress(%d, %d): %s", nicID, ProtocolNumber, err) 415 } else if addr.Address != test.addr { 416 t.Fatalf("got stack.GetMainNICAddress(%d, %d) = %s, want = %s", nicID, ProtocolNumber, addr.Address, test.addr) 417 } 418 }) 419 } 420 } 421 422 func TestReceiveIPv6ExtHdrs(t *testing.T) { 423 tests := []struct { 424 name string 425 extHdr func(nextHdr uint8) ([]byte, uint8) 426 shouldAccept bool 427 countersToBeIncremented func(*tcpip.Stats) []*tcpip.StatCounter 428 // Should we expect an ICMP response and if so, with what contents? 429 expectICMP bool 430 ICMPType header.ICMPv6Type 431 ICMPCode header.ICMPv6Code 432 pointer uint32 433 multicast bool 434 }{ 435 { 436 name: "None", 437 extHdr: func(nextHdr uint8) ([]byte, uint8) { return nil, nextHdr }, 438 shouldAccept: true, 439 expectICMP: false, 440 }, 441 { 442 name: "hopbyhop with router alert option", 443 extHdr: func(nextHdr uint8) ([]byte, uint8) { 444 return []byte{ 445 nextHdr, 0, 446 447 // Router Alert option. 448 5, 2, 0, 0, 0, 0, 449 }, hopByHopExtHdrID 450 }, 451 shouldAccept: true, 452 countersToBeIncremented: func(stats *tcpip.Stats) []*tcpip.StatCounter { 453 return []*tcpip.StatCounter{stats.IP.OptionRouterAlertReceived} 454 }, 455 }, 456 { 457 name: "hopbyhop with two router alert options", 458 extHdr: func(nextHdr uint8) ([]byte, uint8) { 459 return []byte{ 460 nextHdr, 1, 461 462 // Router Alert option. 463 5, 2, 0, 0, 0, 0, 464 465 // Router Alert option. 466 5, 2, 0, 0, 0, 0, 0, 0, 467 }, hopByHopExtHdrID 468 }, 469 shouldAccept: false, 470 countersToBeIncremented: func(stats *tcpip.Stats) []*tcpip.StatCounter { 471 return []*tcpip.StatCounter{ 472 stats.IP.OptionRouterAlertReceived, 473 stats.IP.MalformedPacketsReceived, 474 } 475 }, 476 }, 477 { 478 name: "hopbyhop with unknown option skippable action", 479 extHdr: func(nextHdr uint8) ([]byte, uint8) { 480 return []byte{ 481 nextHdr, 1, 482 483 // Skippable unknown. 484 63, 4, 1, 2, 3, 4, 485 486 // Skippable unknown. 487 62, 6, 1, 2, 3, 4, 5, 6, 488 }, hopByHopExtHdrID 489 }, 490 shouldAccept: true, 491 }, 492 { 493 name: "hopbyhop with unknown option discard action", 494 extHdr: func(nextHdr uint8) ([]byte, uint8) { 495 return []byte{ 496 nextHdr, 1, 497 498 // Skippable unknown. 499 63, 4, 1, 2, 3, 4, 500 501 // Discard unknown. 502 127, 6, 1, 2, 3, 4, 5, 6, 503 }, hopByHopExtHdrID 504 }, 505 shouldAccept: false, 506 expectICMP: false, 507 }, 508 { 509 name: "hopbyhop with unknown option discard and send icmp action (unicast)", 510 extHdr: func(nextHdr uint8) ([]byte, uint8) { 511 return []byte{ 512 nextHdr, 1, 513 514 // Skippable unknown. 515 63, 4, 1, 2, 3, 4, 516 517 // Discard & send ICMP if option is unknown. 518 191, 6, 1, 2, 3, 4, 5, 6, 519 //^ Unknown option. 520 }, hopByHopExtHdrID 521 }, 522 shouldAccept: false, 523 expectICMP: true, 524 ICMPType: header.ICMPv6ParamProblem, 525 ICMPCode: header.ICMPv6UnknownOption, 526 pointer: header.IPv6FixedHeaderSize + 8, 527 }, 528 { 529 name: "hopbyhop with unknown option discard and send icmp action (multicast)", 530 extHdr: func(nextHdr uint8) ([]byte, uint8) { 531 return []byte{ 532 nextHdr, 1, 533 534 // Skippable unknown. 535 63, 4, 1, 2, 3, 4, 536 537 // Discard & send ICMP if option is unknown. 538 191, 6, 1, 2, 3, 4, 5, 6, 539 //^ Unknown option. 540 }, hopByHopExtHdrID 541 }, 542 multicast: true, 543 shouldAccept: false, 544 expectICMP: true, 545 ICMPType: header.ICMPv6ParamProblem, 546 ICMPCode: header.ICMPv6UnknownOption, 547 pointer: header.IPv6FixedHeaderSize + 8, 548 }, 549 { 550 name: "hopbyhop with unknown option discard and send icmp action unless multicast dest (unicast)", 551 extHdr: func(nextHdr uint8) ([]byte, uint8) { 552 return []byte{ 553 nextHdr, 1, 554 555 // Skippable unknown. 556 63, 4, 1, 2, 3, 4, 557 558 // Discard & send ICMP unless packet is for multicast destination if 559 // option is unknown. 560 255, 6, 1, 2, 3, 4, 5, 6, 561 //^ Unknown option. 562 }, hopByHopExtHdrID 563 }, 564 expectICMP: true, 565 ICMPType: header.ICMPv6ParamProblem, 566 ICMPCode: header.ICMPv6UnknownOption, 567 pointer: header.IPv6FixedHeaderSize + 8, 568 }, 569 { 570 name: "hopbyhop with unknown option discard and send icmp action unless multicast dest (multicast)", 571 extHdr: func(nextHdr uint8) ([]byte, uint8) { 572 return []byte{ 573 nextHdr, 1, 574 575 // Skippable unknown. 576 63, 4, 1, 2, 3, 4, 577 578 // Discard & send ICMP unless packet is for multicast destination if 579 // option is unknown. 580 255, 6, 1, 2, 3, 4, 5, 6, 581 //^ Unknown option. 582 }, hopByHopExtHdrID 583 }, 584 multicast: true, 585 shouldAccept: false, 586 expectICMP: false, 587 }, 588 { 589 name: "routing with zero segments left", 590 extHdr: func(nextHdr uint8) ([]byte, uint8) { 591 return []byte{ 592 nextHdr, 0, 593 1, 0, 2, 3, 4, 5, 594 }, routingExtHdrID 595 }, 596 shouldAccept: true, 597 }, 598 { 599 name: "routing with non-zero segments left", 600 extHdr: func(nextHdr uint8) ([]byte, uint8) { 601 return []byte{ 602 nextHdr, 0, 603 1, 1, 2, 3, 4, 5, 604 }, routingExtHdrID 605 }, 606 shouldAccept: false, 607 expectICMP: true, 608 ICMPType: header.ICMPv6ParamProblem, 609 ICMPCode: header.ICMPv6ErroneousHeader, 610 pointer: header.IPv6FixedHeaderSize + 2, 611 }, 612 { 613 name: "atomic fragment with zero ID", 614 extHdr: func(nextHdr uint8) ([]byte, uint8) { 615 return []byte{ 616 nextHdr, 0, 617 0, 0, 0, 0, 0, 0, 618 }, fragmentExtHdrID 619 }, 620 shouldAccept: true, 621 }, 622 { 623 name: "atomic fragment with non-zero ID", 624 extHdr: func(nextHdr uint8) ([]byte, uint8) { 625 return []byte{ 626 nextHdr, 0, 627 0, 0, 1, 2, 3, 4, 628 }, fragmentExtHdrID 629 }, 630 shouldAccept: true, 631 expectICMP: false, 632 }, 633 { 634 name: "fragment", 635 extHdr: func(nextHdr uint8) ([]byte, uint8) { 636 return []byte{ 637 nextHdr, 0, 638 1, 0, 1, 2, 3, 4, 639 }, fragmentExtHdrID 640 }, 641 shouldAccept: false, 642 expectICMP: false, 643 }, 644 { 645 name: "No next header", 646 extHdr: func(nextHdr uint8) ([]byte, uint8) { 647 return nil, noNextHdrID 648 }, 649 shouldAccept: false, 650 expectICMP: false, 651 }, 652 { 653 name: "unknown next header (first)", 654 extHdr: func(nextHdr uint8) ([]byte, uint8) { 655 return []byte{ 656 nextHdr, 0, 63, 4, 1, 2, 3, 4, 657 }, unknownHdrID 658 }, 659 shouldAccept: false, 660 expectICMP: true, 661 ICMPType: header.ICMPv6ParamProblem, 662 ICMPCode: header.ICMPv6UnknownHeader, 663 pointer: header.IPv6NextHeaderOffset, 664 }, 665 { 666 name: "unknown next header (not first)", 667 extHdr: func(nextHdr uint8) ([]byte, uint8) { 668 return []byte{ 669 unknownHdrID, 0, 670 63, 4, 1, 2, 3, 4, 671 }, hopByHopExtHdrID 672 }, 673 shouldAccept: false, 674 expectICMP: true, 675 ICMPType: header.ICMPv6ParamProblem, 676 ICMPCode: header.ICMPv6UnknownHeader, 677 pointer: header.IPv6FixedHeaderSize, 678 }, 679 { 680 name: "destination with unknown option skippable action", 681 extHdr: func(nextHdr uint8) ([]byte, uint8) { 682 return []byte{ 683 nextHdr, 1, 684 685 // Skippable unknown. 686 63, 4, 1, 2, 3, 4, 687 688 // Skippable unknown. 689 62, 6, 1, 2, 3, 4, 5, 6, 690 }, destinationExtHdrID 691 }, 692 shouldAccept: true, 693 expectICMP: false, 694 }, 695 { 696 name: "destination with unknown option discard action", 697 extHdr: func(nextHdr uint8) ([]byte, uint8) { 698 return []byte{ 699 nextHdr, 1, 700 701 // Skippable unknown. 702 63, 4, 1, 2, 3, 4, 703 704 // Discard unknown. 705 127, 6, 1, 2, 3, 4, 5, 6, 706 }, destinationExtHdrID 707 }, 708 shouldAccept: false, 709 expectICMP: false, 710 }, 711 { 712 name: "destination with unknown option discard and send icmp action (unicast)", 713 extHdr: func(nextHdr uint8) ([]byte, uint8) { 714 return []byte{ 715 nextHdr, 1, 716 717 // Skippable unknown. 718 63, 4, 1, 2, 3, 4, 719 720 // Discard & send ICMP if option is unknown. 721 191, 6, 1, 2, 3, 4, 5, 6, 722 //^ 191 is an unknown option. 723 }, destinationExtHdrID 724 }, 725 shouldAccept: false, 726 expectICMP: true, 727 ICMPType: header.ICMPv6ParamProblem, 728 ICMPCode: header.ICMPv6UnknownOption, 729 pointer: header.IPv6FixedHeaderSize + 8, 730 }, 731 { 732 name: "destination with unknown option discard and send icmp action (multicast)", 733 extHdr: func(nextHdr uint8) ([]byte, uint8) { 734 return []byte{ 735 nextHdr, 1, 736 737 // Skippable unknown. 738 63, 4, 1, 2, 3, 4, 739 740 // Discard & send ICMP if option is unknown. 741 191, 6, 1, 2, 3, 4, 5, 6, 742 //^ 191 is an unknown option. 743 }, destinationExtHdrID 744 }, 745 multicast: true, 746 shouldAccept: false, 747 expectICMP: true, 748 ICMPType: header.ICMPv6ParamProblem, 749 ICMPCode: header.ICMPv6UnknownOption, 750 pointer: header.IPv6FixedHeaderSize + 8, 751 }, 752 { 753 name: "destination with unknown option discard and send icmp action unless multicast dest (unicast)", 754 extHdr: func(nextHdr uint8) ([]byte, uint8) { 755 return []byte{ 756 nextHdr, 1, 757 758 // Skippable unknown. 759 63, 4, 1, 2, 3, 4, 760 761 // Discard & send ICMP unless packet is for multicast destination if 762 // option is unknown. 763 255, 6, 1, 2, 3, 4, 5, 6, 764 //^ 255 is unknown. 765 }, destinationExtHdrID 766 }, 767 shouldAccept: false, 768 expectICMP: true, 769 ICMPType: header.ICMPv6ParamProblem, 770 ICMPCode: header.ICMPv6UnknownOption, 771 pointer: header.IPv6FixedHeaderSize + 8, 772 }, 773 { 774 name: "destination with unknown option discard and send icmp action unless multicast dest (multicast)", 775 extHdr: func(nextHdr uint8) ([]byte, uint8) { 776 return []byte{ 777 nextHdr, 1, 778 779 // Skippable unknown. 780 63, 4, 1, 2, 3, 4, 781 782 // Discard & send ICMP unless packet is for multicast destination if 783 // option is unknown. 784 255, 6, 1, 2, 3, 4, 5, 6, 785 //^ 255 is unknown. 786 }, destinationExtHdrID 787 }, 788 shouldAccept: false, 789 expectICMP: false, 790 multicast: true, 791 }, 792 { 793 name: "atomic fragment - routing", 794 extHdr: func(nextHdr uint8) ([]byte, uint8) { 795 return []byte{ 796 // Fragment extension header. 797 routingExtHdrID, 0, 0, 0, 1, 2, 3, 4, 798 799 // Routing extension header. 800 nextHdr, 0, 1, 0, 2, 3, 4, 5, 801 }, fragmentExtHdrID 802 }, 803 shouldAccept: true, 804 }, 805 { 806 name: "hop by hop (with skippable unknown) - routing", 807 extHdr: func(nextHdr uint8) ([]byte, uint8) { 808 return []byte{ 809 // Hop By Hop extension header with skippable unknown option. 810 routingExtHdrID, 0, 62, 4, 1, 2, 3, 4, 811 812 // Routing extension header. 813 nextHdr, 0, 1, 0, 2, 3, 4, 5, 814 }, hopByHopExtHdrID 815 }, 816 shouldAccept: true, 817 }, 818 { 819 name: "routing - hop by hop (with skippable unknown)", 820 extHdr: func(nextHdr uint8) ([]byte, uint8) { 821 return []byte{ 822 // Routing extension header. 823 hopByHopExtHdrID, 0, 1, 0, 2, 3, 4, 5, 824 // ^^^ The HopByHop extension header may not appear after the first 825 // extension header. 826 827 // Hop By Hop extension header with skippable unknown option. 828 nextHdr, 0, 62, 4, 1, 2, 3, 4, 829 }, routingExtHdrID 830 }, 831 shouldAccept: false, 832 expectICMP: true, 833 ICMPType: header.ICMPv6ParamProblem, 834 ICMPCode: header.ICMPv6UnknownHeader, 835 pointer: header.IPv6FixedHeaderSize, 836 }, 837 { 838 name: "routing - hop by hop (with send icmp unknown)", 839 extHdr: func(nextHdr uint8) ([]byte, uint8) { 840 return []byte{ 841 // Routing extension header. 842 hopByHopExtHdrID, 0, 1, 0, 2, 3, 4, 5, 843 // ^^^ The HopByHop extension header may not appear after the first 844 // extension header. 845 846 nextHdr, 1, 847 848 // Skippable unknown. 849 63, 4, 1, 2, 3, 4, 850 851 // Skippable unknown. 852 191, 6, 1, 2, 3, 4, 5, 6, 853 }, routingExtHdrID 854 }, 855 shouldAccept: false, 856 expectICMP: true, 857 ICMPType: header.ICMPv6ParamProblem, 858 ICMPCode: header.ICMPv6UnknownHeader, 859 pointer: header.IPv6FixedHeaderSize, 860 }, 861 { 862 name: "hopbyhop (with skippable unknown) - routing - atomic fragment - destination (with skippable unknown)", 863 extHdr: func(nextHdr uint8) ([]byte, uint8) { 864 return []byte{ 865 // Hop By Hop extension header with skippable unknown option. 866 routingExtHdrID, 0, 62, 4, 1, 2, 3, 4, 867 868 // Routing extension header. 869 fragmentExtHdrID, 0, 1, 0, 2, 3, 4, 5, 870 871 // Fragment extension header. 872 destinationExtHdrID, 0, 0, 0, 1, 2, 3, 4, 873 874 // Destination extension header with skippable unknown option. 875 nextHdr, 0, 63, 4, 1, 2, 3, 4, 876 }, hopByHopExtHdrID 877 }, 878 shouldAccept: true, 879 }, 880 { 881 name: "hopbyhop (with discard unknown) - routing - atomic fragment - destination (with skippable unknown)", 882 extHdr: func(nextHdr uint8) ([]byte, uint8) { 883 return []byte{ 884 // Hop By Hop extension header with discard action for unknown option. 885 routingExtHdrID, 0, 65, 4, 1, 2, 3, 4, 886 887 // Routing extension header. 888 fragmentExtHdrID, 0, 1, 0, 2, 3, 4, 5, 889 890 // Fragment extension header. 891 destinationExtHdrID, 0, 0, 0, 1, 2, 3, 4, 892 893 // Destination extension header with skippable unknown option. 894 nextHdr, 0, 63, 4, 1, 2, 3, 4, 895 }, hopByHopExtHdrID 896 }, 897 shouldAccept: false, 898 expectICMP: false, 899 }, 900 { 901 name: "hopbyhop (with skippable unknown) - routing - atomic fragment - destination (with discard unknown)", 902 extHdr: func(nextHdr uint8) ([]byte, uint8) { 903 return []byte{ 904 // Hop By Hop extension header with skippable unknown option. 905 routingExtHdrID, 0, 62, 4, 1, 2, 3, 4, 906 907 // Routing extension header. 908 fragmentExtHdrID, 0, 1, 0, 2, 3, 4, 5, 909 910 // Fragment extension header. 911 destinationExtHdrID, 0, 0, 0, 1, 2, 3, 4, 912 913 // Destination extension header with discard action for unknown 914 // option. 915 nextHdr, 0, 65, 4, 1, 2, 3, 4, 916 }, hopByHopExtHdrID 917 }, 918 shouldAccept: false, 919 expectICMP: false, 920 }, 921 } 922 923 for _, test := range tests { 924 t.Run(test.name, func(t *testing.T) { 925 c := newTestContext() 926 defer c.cleanup() 927 s := c.s 928 929 e := channel.New(1, header.IPv6MinimumMTU, linkAddr1) 930 defer e.Close() 931 if err := s.CreateNIC(nicID, e); err != nil { 932 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 933 } 934 protocolAddr := tcpip.ProtocolAddress{ 935 Protocol: ProtocolNumber, 936 AddressWithPrefix: addr2.WithPrefix(), 937 } 938 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 939 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 940 } 941 942 // Add a default route so that a return packet knows where to go. 943 s.SetRouteTable([]tcpip.Route{ 944 { 945 Destination: header.IPv6EmptySubnet, 946 NIC: nicID, 947 }, 948 }) 949 950 wq := waiter.Queue{} 951 we, ch := waiter.NewChannelEntry(waiter.WritableEvents) 952 wq.EventRegister(&we) 953 defer wq.EventUnregister(&we) 954 defer close(ch) 955 ep, err := s.NewEndpoint(udp.ProtocolNumber, ProtocolNumber, &wq) 956 if err != nil { 957 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, ProtocolNumber, err) 958 } 959 defer ep.Close() 960 961 bindAddr := tcpip.FullAddress{Addr: addr2, Port: 80} 962 if err := ep.Bind(bindAddr); err != nil { 963 t.Fatalf("Bind(%+v): %s", bindAddr, err) 964 } 965 966 udpPayload := []byte{1, 2, 3, 4, 5, 6, 7, 8} 967 udpLength := header.UDPMinimumSize + len(udpPayload) 968 extHdrBytes, ipv6NextHdr := test.extHdr(uint8(header.UDPProtocolNumber)) 969 extHdrLen := len(extHdrBytes) 970 hdr := prependable.New(header.IPv6MinimumSize + extHdrLen + udpLength) 971 972 // Serialize UDP message. 973 u := header.UDP(hdr.Prepend(udpLength)) 974 u.Encode(&header.UDPFields{ 975 SrcPort: 5555, 976 DstPort: 80, 977 Length: uint16(udpLength), 978 }) 979 copy(u.Payload(), udpPayload) 980 981 dstAddr := tcpip.Address(addr2) 982 if test.multicast { 983 dstAddr = header.IPv6AllNodesMulticastAddress 984 } 985 986 sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, addr1, dstAddr, uint16(udpLength)) 987 sum = checksum.Checksum(udpPayload, sum) 988 u.SetChecksum(^u.CalculateChecksum(sum)) 989 990 // Copy extension header bytes between the UDP message and the IPv6 991 // fixed header. 992 copy(hdr.Prepend(extHdrLen), extHdrBytes) 993 994 // Serialize IPv6 fixed header. 995 payloadLength := hdr.UsedLength() 996 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 997 ip.Encode(&header.IPv6Fields{ 998 PayloadLength: uint16(payloadLength), 999 // We're lying about transport protocol here to be able to generate 1000 // raw extension headers from the test definitions. 1001 TransportProtocol: tcpip.TransportProtocolNumber(ipv6NextHdr), 1002 HopLimit: 255, 1003 SrcAddr: addr1, 1004 DstAddr: dstAddr, 1005 }) 1006 1007 stats := s.Stats() 1008 var counters []*tcpip.StatCounter 1009 // Make sure that the counters we expect to be incremented are initially 1010 // set to zero. 1011 if fn := test.countersToBeIncremented; fn != nil { 1012 counters = fn(&stats) 1013 } 1014 for i := range counters { 1015 if got := counters[i].Value(); got != 0 { 1016 t.Errorf("before writing packet: got test.countersToBeIncremented(&stats)[%d].Value() = %d, want = 0", i, got) 1017 } 1018 } 1019 1020 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 1021 Payload: buffer.MakeWithData(hdr.View()), 1022 }) 1023 e.InjectInbound(ProtocolNumber, pkt) 1024 pkt.DecRef() 1025 for i := range counters { 1026 if got := counters[i].Value(); got != 1 { 1027 t.Errorf("after writing packet: got test.countersToBeIncremented(&stats)[%d].Value() = %d, want = 1", i, got) 1028 } 1029 } 1030 1031 udpReceiveStat := stats.UDP.PacketsReceived 1032 if !test.shouldAccept { 1033 if got := udpReceiveStat.Value(); got != 0 { 1034 t.Errorf("got UDP Rx Packets = %d, want = 0", got) 1035 } 1036 1037 if !test.expectICMP { 1038 if p := e.Read(); p != nil { 1039 t.Fatalf("unexpected packet received: %#v", p) 1040 } 1041 return 1042 } 1043 1044 // ICMP required. 1045 p := e.Read() 1046 if p == nil { 1047 t.Fatalf("expected packet wasn't written out") 1048 } 1049 defer p.DecRef() 1050 1051 // Pack the output packet into a single buffer.View as the checkers 1052 // assume that. 1053 v := p.ToView() 1054 defer v.Release() 1055 pkt := v.AsSlice() 1056 if got, want := len(pkt), header.IPv6FixedHeaderSize+header.ICMPv6MinimumSize+hdr.UsedLength(); got != want { 1057 t.Fatalf("got an ICMP packet of size = %d, want = %d", got, want) 1058 } 1059 1060 checker.IPv6(t, v, checker.ICMPv6( 1061 checker.ICMPv6Type(test.ICMPType), 1062 checker.ICMPv6Code(test.ICMPCode))) 1063 1064 // We know we are looking at no extension headers in the error ICMP 1065 // packets. 1066 icm := header.ICMPv6(header.IPv6(pkt).Payload()) 1067 // We know we sent small packets that won't be truncated when reflected 1068 // back to us. 1069 originalPacket := icm.Payload() 1070 if got, want := icm.TypeSpecific(), test.pointer; got != want { 1071 t.Errorf("unexpected ICMPv6 pointer, got = %d, want = %d\n", got, want) 1072 } 1073 if diff := cmp.Diff([]byte(hdr.View()), originalPacket); diff != "" { 1074 t.Errorf("ICMPv6 payload mismatch (-want +got):\n%s", diff) 1075 } 1076 return 1077 } 1078 1079 // Expect a UDP packet. 1080 if got := udpReceiveStat.Value(); got != 1 { 1081 t.Errorf("got UDP Rx Packets = %d, want = 1", got) 1082 } 1083 var buf bytes.Buffer 1084 result, err := ep.Read(&buf, tcpip.ReadOptions{}) 1085 if err != nil { 1086 t.Fatalf("Read: %s", err) 1087 } 1088 if diff := cmp.Diff(tcpip.ReadResult{ 1089 Count: len(udpPayload), 1090 Total: len(udpPayload), 1091 }, result, checker.IgnoreCmpPath("ControlMessages")); diff != "" { 1092 t.Errorf("Read: unexpected result (-want +got):\n%s", diff) 1093 } 1094 if diff := cmp.Diff(udpPayload, buf.Bytes()); diff != "" { 1095 t.Errorf("got UDP payload mismatch (-want +got):\n%s", diff) 1096 } 1097 1098 // Should not have any more UDP packets. 1099 res, err := ep.Read(ioutil.Discard, tcpip.ReadOptions{}) 1100 if _, ok := err.(*tcpip.ErrWouldBlock); !ok { 1101 t.Fatalf("got Read = (%v, %v), want = (_, %s)", res, err, &tcpip.ErrWouldBlock{}) 1102 } 1103 }) 1104 } 1105 } 1106 1107 // fragmentData holds the IPv6 payload for a fragmented IPv6 packet. 1108 type fragmentData struct { 1109 srcAddr tcpip.Address 1110 dstAddr tcpip.Address 1111 nextHdr uint8 1112 data []byte 1113 } 1114 1115 func udpGen(payload []byte, multiplier uint8, src, dst tcpip.Address) []byte { 1116 payloadLen := len(payload) 1117 for i := 0; i < payloadLen; i++ { 1118 payload[i] = uint8(i) * multiplier 1119 } 1120 1121 udpLength := header.UDPMinimumSize + payloadLen 1122 1123 hdr := prependable.New(udpLength) 1124 u := header.UDP(hdr.Prepend(udpLength)) 1125 u.Encode(&header.UDPFields{ 1126 SrcPort: 5555, 1127 DstPort: 80, 1128 Length: uint16(udpLength), 1129 }) 1130 copy(u.Payload(), payload) 1131 sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, src, dst, uint16(udpLength)) 1132 sum = checksum.Checksum(payload, sum) 1133 u.SetChecksum(^u.CalculateChecksum(sum)) 1134 return hdr.View() 1135 } 1136 1137 func TestReceiveIPv6Fragments(t *testing.T) { 1138 const ( 1139 udpPayload1Length = 256 1140 udpPayload2Length = 128 1141 // Used to test cases where the fragment blocks are not a multiple of 1142 // the fragment block size of 8 (RFC 8200 section 4.5). 1143 udpPayload3Length = 127 1144 udpPayload4Length = header.IPv6MaximumPayloadSize - header.UDPMinimumSize 1145 udpMaximumSizeMinus15 = header.UDPMaximumSize - 15 1146 fragmentExtHdrLen = 8 1147 // Note, not all routing extension headers will be 8 bytes but this test 1148 // uses 8 byte routing extension headers for most sub tests. 1149 routingExtHdrLen = 8 1150 ) 1151 1152 var udpPayload1Addr1ToAddr2Buf [udpPayload1Length]byte 1153 udpPayload1Addr1ToAddr2 := udpPayload1Addr1ToAddr2Buf[:] 1154 ipv6Payload1Addr1ToAddr2 := udpGen(udpPayload1Addr1ToAddr2, 1, addr1, addr2) 1155 1156 var udpPayload1Addr3ToAddr2Buf [udpPayload1Length]byte 1157 udpPayload1Addr3ToAddr2 := udpPayload1Addr3ToAddr2Buf[:] 1158 ipv6Payload1Addr3ToAddr2 := udpGen(udpPayload1Addr3ToAddr2, 4, addr3, addr2) 1159 1160 var udpPayload2Addr1ToAddr2Buf [udpPayload2Length]byte 1161 udpPayload2Addr1ToAddr2 := udpPayload2Addr1ToAddr2Buf[:] 1162 ipv6Payload2Addr1ToAddr2 := udpGen(udpPayload2Addr1ToAddr2, 2, addr1, addr2) 1163 1164 var udpPayload3Addr1ToAddr2Buf [udpPayload3Length]byte 1165 udpPayload3Addr1ToAddr2 := udpPayload3Addr1ToAddr2Buf[:] 1166 ipv6Payload3Addr1ToAddr2 := udpGen(udpPayload3Addr1ToAddr2, 3, addr1, addr2) 1167 1168 var udpPayload4Addr1ToAddr2Buf [udpPayload4Length]byte 1169 udpPayload4Addr1ToAddr2 := udpPayload4Addr1ToAddr2Buf[:] 1170 ipv6Payload4Addr1ToAddr2 := udpGen(udpPayload4Addr1ToAddr2, 4, addr1, addr2) 1171 1172 tests := []struct { 1173 name string 1174 expectedPayload []byte 1175 fragments []fragmentData 1176 expectedPayloads [][]byte 1177 }{ 1178 { 1179 name: "No fragmentation", 1180 fragments: []fragmentData{ 1181 { 1182 srcAddr: addr1, 1183 dstAddr: addr2, 1184 nextHdr: uint8(header.UDPProtocolNumber), 1185 data: ipv6Payload1Addr1ToAddr2, 1186 }, 1187 }, 1188 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1189 }, 1190 { 1191 name: "Atomic fragment", 1192 fragments: []fragmentData{ 1193 { 1194 srcAddr: addr1, 1195 dstAddr: addr2, 1196 nextHdr: fragmentExtHdrID, 1197 data: append( 1198 // Fragment extension header. 1199 []byte{uint8(header.UDPProtocolNumber), 0, 0, 0, 0, 0, 0, 0}, 1200 ipv6Payload1Addr1ToAddr2..., 1201 ), 1202 }, 1203 }, 1204 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1205 }, 1206 { 1207 name: "Atomic fragment with size not a multiple of fragment block size", 1208 fragments: []fragmentData{ 1209 { 1210 srcAddr: addr1, 1211 dstAddr: addr2, 1212 nextHdr: fragmentExtHdrID, 1213 data: append( 1214 // Fragment extension header. 1215 []byte{uint8(header.UDPProtocolNumber), 0, 0, 0, 0, 0, 0, 0}, 1216 ipv6Payload3Addr1ToAddr2..., 1217 ), 1218 }, 1219 }, 1220 expectedPayloads: [][]byte{udpPayload3Addr1ToAddr2}, 1221 }, 1222 { 1223 name: "Two fragments", 1224 fragments: []fragmentData{ 1225 { 1226 srcAddr: addr1, 1227 dstAddr: addr2, 1228 nextHdr: fragmentExtHdrID, 1229 data: append( 1230 // Fragment extension header. 1231 // 1232 // Fragment offset = 0, More = true, ID = 1 1233 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1234 ipv6Payload1Addr1ToAddr2[:64]..., 1235 ), 1236 }, 1237 { 1238 srcAddr: addr1, 1239 dstAddr: addr2, 1240 nextHdr: fragmentExtHdrID, 1241 data: append( 1242 // Fragment extension header. 1243 // 1244 // Fragment offset = 8, More = false, ID = 1 1245 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1246 ipv6Payload1Addr1ToAddr2[64:]..., 1247 ), 1248 }, 1249 }, 1250 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1251 }, 1252 { 1253 name: "Two fragments out of order", 1254 fragments: []fragmentData{ 1255 { 1256 srcAddr: addr1, 1257 dstAddr: addr2, 1258 nextHdr: fragmentExtHdrID, 1259 data: append( 1260 // Fragment extension header. 1261 // 1262 // Fragment offset = 8, More = false, ID = 1 1263 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1264 ipv6Payload1Addr1ToAddr2[64:]..., 1265 ), 1266 }, 1267 { 1268 srcAddr: addr1, 1269 dstAddr: addr2, 1270 nextHdr: fragmentExtHdrID, 1271 data: append( 1272 // Fragment extension header. 1273 // 1274 // Fragment offset = 0, More = true, ID = 1 1275 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1276 ipv6Payload1Addr1ToAddr2[:64]..., 1277 ), 1278 }, 1279 }, 1280 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1281 }, 1282 { 1283 name: "Two fragments with different Next Header values", 1284 fragments: []fragmentData{ 1285 { 1286 srcAddr: addr1, 1287 dstAddr: addr2, 1288 nextHdr: fragmentExtHdrID, 1289 data: append( 1290 // Fragment extension header. 1291 // 1292 // Fragment offset = 0, More = true, ID = 1 1293 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1294 ipv6Payload1Addr1ToAddr2[:64]..., 1295 ), 1296 }, 1297 { 1298 srcAddr: addr1, 1299 dstAddr: addr2, 1300 nextHdr: fragmentExtHdrID, 1301 data: append( 1302 // Fragment extension header. 1303 // 1304 // Fragment offset = 8, More = false, ID = 1 1305 // NextHeader value is different than the one in the first fragment, so 1306 // this NextHeader should be ignored. 1307 []byte{uint8(header.IPv6NoNextHeaderIdentifier), 0, 0, 64, 0, 0, 0, 1}, 1308 ipv6Payload1Addr1ToAddr2[64:]..., 1309 ), 1310 }, 1311 }, 1312 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1313 }, 1314 { 1315 name: "Two fragments with last fragment size not a multiple of fragment block size", 1316 fragments: []fragmentData{ 1317 { 1318 srcAddr: addr1, 1319 dstAddr: addr2, 1320 nextHdr: fragmentExtHdrID, 1321 data: append( 1322 // Fragment extension header. 1323 // 1324 // Fragment offset = 0, More = true, ID = 1 1325 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1326 ipv6Payload3Addr1ToAddr2[:64]..., 1327 ), 1328 }, 1329 { 1330 srcAddr: addr1, 1331 dstAddr: addr2, 1332 nextHdr: fragmentExtHdrID, 1333 data: append( 1334 // Fragment extension header. 1335 // 1336 // Fragment offset = 8, More = false, ID = 1 1337 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1338 ipv6Payload3Addr1ToAddr2[64:]..., 1339 ), 1340 }, 1341 }, 1342 expectedPayloads: [][]byte{udpPayload3Addr1ToAddr2}, 1343 }, 1344 { 1345 name: "Two fragments with first fragment size not a multiple of fragment block size", 1346 fragments: []fragmentData{ 1347 { 1348 srcAddr: addr1, 1349 dstAddr: addr2, 1350 nextHdr: fragmentExtHdrID, 1351 data: append( 1352 // Fragment extension header. 1353 // 1354 // Fragment offset = 0, More = true, ID = 1 1355 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1356 ipv6Payload3Addr1ToAddr2[:63]..., 1357 ), 1358 }, 1359 { 1360 srcAddr: addr1, 1361 dstAddr: addr2, 1362 nextHdr: fragmentExtHdrID, 1363 data: append( 1364 // Fragment extension header. 1365 // 1366 // Fragment offset = 8, More = false, ID = 1 1367 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1368 ipv6Payload3Addr1ToAddr2[63:]..., 1369 ), 1370 }, 1371 }, 1372 expectedPayloads: nil, 1373 }, 1374 { 1375 name: "Two fragments with different IDs", 1376 fragments: []fragmentData{ 1377 { 1378 srcAddr: addr1, 1379 dstAddr: addr2, 1380 nextHdr: fragmentExtHdrID, 1381 data: append( 1382 // Fragment extension header. 1383 // 1384 // Fragment offset = 0, More = true, ID = 1 1385 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1386 ipv6Payload1Addr1ToAddr2[:64]..., 1387 ), 1388 }, 1389 { 1390 srcAddr: addr1, 1391 dstAddr: addr2, 1392 nextHdr: fragmentExtHdrID, 1393 data: append( 1394 // Fragment extension header. 1395 // 1396 // Fragment offset = 8, More = false, ID = 2 1397 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 2}, 1398 ipv6Payload1Addr1ToAddr2[64:]..., 1399 ), 1400 }, 1401 }, 1402 expectedPayloads: nil, 1403 }, 1404 { 1405 name: "Two fragments reassembled into a maximum UDP packet", 1406 fragments: []fragmentData{ 1407 { 1408 srcAddr: addr1, 1409 dstAddr: addr2, 1410 nextHdr: fragmentExtHdrID, 1411 data: append( 1412 // Fragment extension header. 1413 // 1414 // Fragment offset = 0, More = true, ID = 1 1415 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1416 ipv6Payload4Addr1ToAddr2[:udpMaximumSizeMinus15]..., 1417 ), 1418 }, 1419 { 1420 srcAddr: addr1, 1421 dstAddr: addr2, 1422 nextHdr: fragmentExtHdrID, 1423 data: append( 1424 // Fragment extension header. 1425 // 1426 // Fragment offset = udpMaximumSizeMinus15/8, More = false, ID = 1 1427 []byte{uint8(header.UDPProtocolNumber), 0, 1428 udpMaximumSizeMinus15 >> 8, 1429 udpMaximumSizeMinus15 & 0xff, 1430 0, 0, 0, 1}, 1431 ipv6Payload4Addr1ToAddr2[udpMaximumSizeMinus15:]..., 1432 ), 1433 }, 1434 }, 1435 expectedPayloads: [][]byte{udpPayload4Addr1ToAddr2}, 1436 }, 1437 { 1438 name: "Two fragments with MF flag reassembled into a maximum UDP packet", 1439 fragments: []fragmentData{ 1440 { 1441 srcAddr: addr1, 1442 dstAddr: addr2, 1443 nextHdr: fragmentExtHdrID, 1444 data: append( 1445 // Fragment extension header. 1446 // 1447 // Fragment offset = 0, More = true, ID = 1 1448 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1449 ipv6Payload4Addr1ToAddr2[:udpMaximumSizeMinus15]..., 1450 ), 1451 }, 1452 { 1453 srcAddr: addr1, 1454 dstAddr: addr2, 1455 nextHdr: fragmentExtHdrID, 1456 data: append( 1457 // Fragment extension header. 1458 // 1459 // Fragment offset = udpMaximumSizeMinus15/8, More = true, ID = 1 1460 []byte{uint8(header.UDPProtocolNumber), 0, 1461 udpMaximumSizeMinus15 >> 8, 1462 (udpMaximumSizeMinus15 & 0xff) + 1, 1463 0, 0, 0, 1}, 1464 1465 ipv6Payload4Addr1ToAddr2[udpMaximumSizeMinus15:]..., 1466 ), 1467 }, 1468 }, 1469 expectedPayloads: nil, 1470 }, 1471 { 1472 name: "Two fragments with per-fragment routing header with zero segments left", 1473 fragments: []fragmentData{ 1474 { 1475 srcAddr: addr1, 1476 dstAddr: addr2, 1477 nextHdr: routingExtHdrID, 1478 data: append( 1479 // Routing extension header. 1480 // 1481 // Segments left = 0. 1482 []byte{fragmentExtHdrID, 0, 1, 0, 2, 3, 4, 5}, 1483 append( 1484 // Fragment extension header. 1485 // 1486 // Fragment offset = 0, More = true, ID = 1 1487 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1488 ipv6Payload1Addr1ToAddr2[:64]..., 1489 )..., 1490 ), 1491 }, 1492 { 1493 srcAddr: addr1, 1494 dstAddr: addr2, 1495 nextHdr: routingExtHdrID, 1496 data: append( 1497 // Routing extension header. 1498 // 1499 // Segments left = 0. 1500 []byte{fragmentExtHdrID, 0, 1, 0, 2, 3, 4, 5}, 1501 append( 1502 // Fragment extension header. 1503 // 1504 // Fragment offset = 8, More = false, ID = 1 1505 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1506 ipv6Payload1Addr1ToAddr2[64:]..., 1507 )..., 1508 ), 1509 }, 1510 }, 1511 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1512 }, 1513 { 1514 name: "Two fragments with per-fragment routing header with non-zero segments left", 1515 fragments: []fragmentData{ 1516 { 1517 srcAddr: addr1, 1518 dstAddr: addr2, 1519 nextHdr: routingExtHdrID, 1520 data: append( 1521 // Routing extension header. 1522 // 1523 // Segments left = 1. 1524 []byte{fragmentExtHdrID, 0, 1, 1, 2, 3, 4, 5}, 1525 append( 1526 // Fragment extension header. 1527 // 1528 // Fragment offset = 0, More = true, ID = 1 1529 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1530 ipv6Payload1Addr1ToAddr2[:64]..., 1531 )..., 1532 ), 1533 }, 1534 { 1535 srcAddr: addr1, 1536 dstAddr: addr2, 1537 nextHdr: routingExtHdrID, 1538 data: append( 1539 // Routing extension header. 1540 // 1541 // Segments left = 1. 1542 []byte{fragmentExtHdrID, 0, 1, 1, 2, 3, 4, 5}, 1543 1544 append( 1545 // Fragment extension header. 1546 // 1547 // Fragment offset = 9, More = false, ID = 1 1548 []byte{uint8(header.UDPProtocolNumber), 0, 0, 72, 0, 0, 0, 1}, 1549 ipv6Payload1Addr1ToAddr2[64:]..., 1550 )..., 1551 ), 1552 }, 1553 }, 1554 expectedPayloads: nil, 1555 }, 1556 { 1557 name: "Two fragments with routing header with zero segments left", 1558 fragments: []fragmentData{ 1559 { 1560 srcAddr: addr1, 1561 dstAddr: addr2, 1562 nextHdr: fragmentExtHdrID, 1563 data: append( 1564 // Fragment extension header. 1565 // 1566 // Fragment offset = 0, More = true, ID = 1 1567 []byte{routingExtHdrID, 0, 0, 1, 0, 0, 0, 1}, 1568 append( 1569 // Routing extension header. 1570 // 1571 // Segments left = 0. 1572 []byte{uint8(header.UDPProtocolNumber), 0, 1, 0, 2, 3, 4, 5}, 1573 ipv6Payload1Addr1ToAddr2[:64]..., 1574 )..., 1575 ), 1576 }, 1577 { 1578 srcAddr: addr1, 1579 dstAddr: addr2, 1580 nextHdr: fragmentExtHdrID, 1581 data: append( 1582 // Fragment extension header. 1583 // 1584 // Fragment offset = 9, More = false, ID = 1 1585 []byte{routingExtHdrID, 0, 0, 72, 0, 0, 0, 1}, 1586 1587 ipv6Payload1Addr1ToAddr2[64:]..., 1588 ), 1589 }, 1590 }, 1591 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2}, 1592 }, 1593 { 1594 name: "Two fragments with routing header with non-zero segments left", 1595 fragments: []fragmentData{ 1596 { 1597 srcAddr: addr1, 1598 dstAddr: addr2, 1599 nextHdr: fragmentExtHdrID, 1600 data: append( 1601 // Fragment extension header. 1602 // 1603 // Fragment offset = 0, More = true, ID = 1 1604 []byte{routingExtHdrID, 0, 0, 1, 0, 0, 0, 1}, 1605 append( 1606 // Routing extension header. 1607 // 1608 // Segments left = 1. 1609 []byte{uint8(header.UDPProtocolNumber), 0, 1, 1, 2, 3, 4, 5}, 1610 ipv6Payload1Addr1ToAddr2[:64]..., 1611 )..., 1612 ), 1613 }, 1614 { 1615 srcAddr: addr1, 1616 dstAddr: addr2, 1617 nextHdr: fragmentExtHdrID, 1618 data: append( 1619 // Fragment extension header. 1620 // 1621 // Fragment offset = 9, More = false, ID = 1 1622 []byte{routingExtHdrID, 0, 0, 72, 0, 0, 0, 1}, 1623 ipv6Payload1Addr1ToAddr2[64:]..., 1624 ), 1625 }, 1626 }, 1627 expectedPayloads: nil, 1628 }, 1629 { 1630 name: "Two fragments with routing header with zero segments left across fragments", 1631 fragments: []fragmentData{ 1632 { 1633 srcAddr: addr1, 1634 dstAddr: addr2, 1635 nextHdr: fragmentExtHdrID, 1636 data: append( 1637 // Fragment offset = 0, More = true, ID = 1 1638 []byte{routingExtHdrID, 0, 0, 1, 0, 0, 0, 1}, 1639 // Routing extension header (part 1) 1640 // 1641 // Segments left = 0. 1642 []byte{uint8(header.UDPProtocolNumber), 1, 1, 0, 2, 3, 4, 5}..., 1643 ), 1644 }, 1645 { 1646 srcAddr: addr1, 1647 dstAddr: addr2, 1648 nextHdr: fragmentExtHdrID, 1649 data: append( 1650 // Fragment extension header. 1651 // 1652 // Fragment offset = 1, More = false, ID = 1 1653 []byte{routingExtHdrID, 0, 0, 8, 0, 0, 0, 1}, 1654 append( 1655 // Routing extension header (part 2) 1656 []byte{6, 7, 8, 9, 10, 11, 12, 13}, 1657 ipv6Payload1Addr1ToAddr2..., 1658 )..., 1659 ), 1660 }, 1661 }, 1662 expectedPayloads: nil, 1663 }, 1664 { 1665 name: "Two fragments with routing header with non-zero segments left across fragments", 1666 fragments: []fragmentData{ 1667 { 1668 srcAddr: addr1, 1669 dstAddr: addr2, 1670 nextHdr: fragmentExtHdrID, 1671 data: append( 1672 // Fragment extension header. 1673 // 1674 // Fragment offset = 0, More = true, ID = 1 1675 []byte{routingExtHdrID, 0, 0, 1, 0, 0, 0, 1}, 1676 1677 // Routing extension header (part 1) 1678 // 1679 // Segments left = 1. 1680 []byte{uint8(header.UDPProtocolNumber), 1, 1, 1, 2, 3, 4, 5}..., 1681 ), 1682 }, 1683 { 1684 srcAddr: addr1, 1685 dstAddr: addr2, 1686 nextHdr: fragmentExtHdrID, 1687 data: append( 1688 // Fragment extension header. 1689 // 1690 // Fragment offset = 1, More = false, ID = 1 1691 []byte{routingExtHdrID, 0, 0, 8, 0, 0, 0, 1}, 1692 append( 1693 // Routing extension header (part 2) 1694 []byte{6, 7, 8, 9, 10, 11, 12, 13}, 1695 ipv6Payload1Addr1ToAddr2..., 1696 )..., 1697 ), 1698 }, 1699 }, 1700 expectedPayloads: nil, 1701 }, 1702 // As per RFC 6946, IPv6 atomic fragments MUST NOT interfere with "normal" 1703 // fragmented traffic. 1704 { 1705 name: "Two fragments with atomic", 1706 fragments: []fragmentData{ 1707 { 1708 srcAddr: addr1, 1709 dstAddr: addr2, 1710 nextHdr: fragmentExtHdrID, 1711 data: append( 1712 // Fragment extension header. 1713 // 1714 // Fragment offset = 0, More = true, ID = 1 1715 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1716 ipv6Payload1Addr1ToAddr2[:64]..., 1717 ), 1718 }, 1719 // This fragment has the same ID as the other fragments but is an atomic 1720 // fragment. It should not interfere with the other fragments. 1721 { 1722 srcAddr: addr1, 1723 dstAddr: addr2, 1724 nextHdr: fragmentExtHdrID, 1725 data: append( 1726 // Fragment extension header. 1727 // 1728 // Fragment offset = 0, More = false, ID = 1 1729 []byte{uint8(header.UDPProtocolNumber), 0, 0, 0, 0, 0, 0, 1}, 1730 ipv6Payload2Addr1ToAddr2..., 1731 ), 1732 }, 1733 { 1734 srcAddr: addr1, 1735 dstAddr: addr2, 1736 nextHdr: fragmentExtHdrID, 1737 data: append( 1738 // Fragment extension header. 1739 // 1740 // Fragment offset = 8, More = false, ID = 1 1741 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1742 1743 ipv6Payload1Addr1ToAddr2[64:]..., 1744 ), 1745 }, 1746 }, 1747 expectedPayloads: [][]byte{udpPayload2Addr1ToAddr2, udpPayload1Addr1ToAddr2}, 1748 }, 1749 { 1750 name: "Two interleaved fragmented packets", 1751 fragments: []fragmentData{ 1752 { 1753 srcAddr: addr1, 1754 dstAddr: addr2, 1755 nextHdr: fragmentExtHdrID, 1756 data: append( 1757 // Fragment extension header. 1758 // 1759 // Fragment offset = 0, More = true, ID = 1 1760 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1761 ipv6Payload1Addr1ToAddr2[:64]..., 1762 ), 1763 }, 1764 { 1765 srcAddr: addr1, 1766 dstAddr: addr2, 1767 nextHdr: fragmentExtHdrID, 1768 data: append( 1769 // Fragment extension header. 1770 // 1771 // Fragment offset = 0, More = true, ID = 2 1772 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 2}, 1773 ipv6Payload2Addr1ToAddr2[:32]..., 1774 ), 1775 }, 1776 { 1777 srcAddr: addr1, 1778 dstAddr: addr2, 1779 nextHdr: fragmentExtHdrID, 1780 data: append( 1781 // Fragment extension header. 1782 // 1783 // Fragment offset = 8, More = false, ID = 1 1784 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1785 ipv6Payload1Addr1ToAddr2[64:]..., 1786 ), 1787 }, 1788 { 1789 srcAddr: addr1, 1790 dstAddr: addr2, 1791 nextHdr: fragmentExtHdrID, 1792 data: append( 1793 // Fragment extension header. 1794 // 1795 // Fragment offset = 4, More = false, ID = 2 1796 []byte{uint8(header.UDPProtocolNumber), 0, 0, 32, 0, 0, 0, 2}, 1797 ipv6Payload2Addr1ToAddr2[32:]..., 1798 ), 1799 }, 1800 }, 1801 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2, udpPayload2Addr1ToAddr2}, 1802 }, 1803 { 1804 name: "Two interleaved fragmented packets from different sources but with same ID", 1805 fragments: []fragmentData{ 1806 { 1807 srcAddr: addr1, 1808 dstAddr: addr2, 1809 nextHdr: fragmentExtHdrID, 1810 data: append( 1811 // Fragment extension header. 1812 // 1813 // Fragment offset = 0, More = true, ID = 1 1814 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1815 1816 ipv6Payload1Addr1ToAddr2[:64]..., 1817 ), 1818 }, 1819 { 1820 srcAddr: addr3, 1821 dstAddr: addr2, 1822 nextHdr: fragmentExtHdrID, 1823 data: append( 1824 // Fragment extension header. 1825 // 1826 // Fragment offset = 0, More = true, ID = 1 1827 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1828 ipv6Payload1Addr3ToAddr2[:32]..., 1829 ), 1830 }, 1831 { 1832 srcAddr: addr1, 1833 dstAddr: addr2, 1834 nextHdr: fragmentExtHdrID, 1835 data: append( 1836 // Fragment extension header. 1837 // 1838 // Fragment offset = 8, More = false, ID = 1 1839 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1840 ipv6Payload1Addr1ToAddr2[64:]..., 1841 ), 1842 }, 1843 { 1844 srcAddr: addr3, 1845 dstAddr: addr2, 1846 nextHdr: fragmentExtHdrID, 1847 data: append( 1848 // Fragment extension header. 1849 // 1850 // Fragment offset = 4, More = false, ID = 1 1851 []byte{uint8(header.UDPProtocolNumber), 0, 0, 32, 0, 0, 0, 1}, 1852 ipv6Payload1Addr3ToAddr2[32:]..., 1853 ), 1854 }, 1855 }, 1856 expectedPayloads: [][]byte{udpPayload1Addr1ToAddr2, udpPayload1Addr3ToAddr2}, 1857 }, 1858 } 1859 1860 for _, test := range tests { 1861 t.Run(test.name, func(t *testing.T) { 1862 c := newTestContext() 1863 defer c.cleanup() 1864 s := c.s 1865 1866 e := channel.New(0, header.IPv6MinimumMTU, linkAddr1) 1867 defer e.Close() 1868 if err := s.CreateNIC(nicID, e); err != nil { 1869 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 1870 } 1871 protocolAddr := tcpip.ProtocolAddress{ 1872 Protocol: ProtocolNumber, 1873 AddressWithPrefix: addr2.WithPrefix(), 1874 } 1875 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 1876 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 1877 } 1878 1879 wq := waiter.Queue{} 1880 we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) 1881 wq.EventRegister(&we) 1882 defer wq.EventUnregister(&we) 1883 defer close(ch) 1884 ep, err := s.NewEndpoint(udp.ProtocolNumber, ProtocolNumber, &wq) 1885 if err != nil { 1886 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, ProtocolNumber, err) 1887 } 1888 defer ep.Close() 1889 1890 bindAddr := tcpip.FullAddress{Addr: addr2, Port: 80} 1891 if err := ep.Bind(bindAddr); err != nil { 1892 t.Fatalf("Bind(%+v): %s", bindAddr, err) 1893 } 1894 1895 for _, f := range test.fragments { 1896 hdr := prependable.New(header.IPv6MinimumSize) 1897 1898 // Serialize IPv6 fixed header. 1899 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 1900 ip.Encode(&header.IPv6Fields{ 1901 PayloadLength: uint16(len(f.data)), 1902 // We're lying about transport protocol here so that we can generate 1903 // raw extension headers for the tests. 1904 TransportProtocol: tcpip.TransportProtocolNumber(f.nextHdr), 1905 HopLimit: 255, 1906 SrcAddr: f.srcAddr, 1907 DstAddr: f.dstAddr, 1908 }) 1909 1910 buf := buffer.MakeWithData(hdr.View()) 1911 buf.Append(buffer.NewViewWithData(f.data)) 1912 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 1913 Payload: buf, 1914 }) 1915 e.InjectInbound(ProtocolNumber, pkt) 1916 pkt.DecRef() 1917 } 1918 1919 if got, want := s.Stats().UDP.PacketsReceived.Value(), uint64(len(test.expectedPayloads)); got != want { 1920 t.Errorf("got UDP Rx Packets = %d, want = %d", got, want) 1921 } 1922 1923 for i, p := range test.expectedPayloads { 1924 var buf bytes.Buffer 1925 _, err := ep.Read(&buf, tcpip.ReadOptions{}) 1926 if err != nil { 1927 t.Fatalf("(i=%d) Read: %s", i, err) 1928 } 1929 if diff := cmp.Diff(p, buf.Bytes()); diff != "" { 1930 t.Errorf("(i=%d) got UDP payload mismatch (-want +got):\n%s", i, diff) 1931 } 1932 } 1933 1934 res, err := ep.Read(ioutil.Discard, tcpip.ReadOptions{}) 1935 if _, ok := err.(*tcpip.ErrWouldBlock); !ok { 1936 t.Fatalf("(last) got Read = (%v, %v), want = (_, %s)", res, err, &tcpip.ErrWouldBlock{}) 1937 } 1938 }) 1939 } 1940 } 1941 1942 func TestConcurrentFragmentWrites(t *testing.T) { 1943 const udpPayload1Length = 256 1944 const udpPayload2Length = 128 1945 var udpPayload1Addr1ToAddr2Buf [udpPayload1Length]byte 1946 udpPayload1Addr1ToAddr2 := udpPayload1Addr1ToAddr2Buf[:] 1947 ipv6Payload1Addr1ToAddr2 := udpGen(udpPayload1Addr1ToAddr2, 1, addr1, addr2) 1948 1949 var udpPayload2Addr1ToAddr2Buf [udpPayload2Length]byte 1950 udpPayload2Addr1ToAddr2 := udpPayload2Addr1ToAddr2Buf[:] 1951 ipv6Payload2Addr1ToAddr2 := udpGen(udpPayload2Addr1ToAddr2, 2, addr1, addr2) 1952 1953 fragments := []fragmentData{ 1954 { 1955 srcAddr: addr1, 1956 dstAddr: addr2, 1957 nextHdr: fragmentExtHdrID, 1958 data: append( 1959 // Fragment extension header. 1960 // 1961 // Fragment offset = 0, More = true, ID = 1 1962 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 1}, 1963 ipv6Payload1Addr1ToAddr2[:64]..., 1964 ), 1965 }, 1966 { 1967 srcAddr: addr1, 1968 dstAddr: addr2, 1969 nextHdr: fragmentExtHdrID, 1970 data: append( 1971 // Fragment extension header. 1972 // 1973 // Fragment offset = 0, More = true, ID = 2 1974 []byte{uint8(header.UDPProtocolNumber), 0, 0, 1, 0, 0, 0, 2}, 1975 ipv6Payload2Addr1ToAddr2[:32]..., 1976 ), 1977 }, 1978 { 1979 srcAddr: addr1, 1980 dstAddr: addr2, 1981 nextHdr: fragmentExtHdrID, 1982 data: append( 1983 // Fragment extension header. 1984 // 1985 // Fragment offset = 8, More = false, ID = 1 1986 []byte{uint8(header.UDPProtocolNumber), 0, 0, 64, 0, 0, 0, 1}, 1987 ipv6Payload1Addr1ToAddr2[64:]..., 1988 ), 1989 }, 1990 } 1991 1992 c := newTestContext() 1993 defer c.cleanup() 1994 s := c.s 1995 1996 e := channel.New(0, header.IPv6MinimumMTU, linkAddr1) 1997 defer e.Close() 1998 if err := s.CreateNIC(nicID, e); err != nil { 1999 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 2000 } 2001 protocolAddr := tcpip.ProtocolAddress{ 2002 Protocol: ProtocolNumber, 2003 AddressWithPrefix: addr2.WithPrefix(), 2004 } 2005 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 2006 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 2007 } 2008 2009 wq := waiter.Queue{} 2010 we, ch := waiter.NewChannelEntry(waiter.ReadableEvents) 2011 wq.EventRegister(&we) 2012 defer wq.EventUnregister(&we) 2013 defer close(ch) 2014 ep, err := s.NewEndpoint(udp.ProtocolNumber, ProtocolNumber, &wq) 2015 if err != nil { 2016 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, ProtocolNumber, err) 2017 } 2018 defer ep.Close() 2019 2020 bindAddr := tcpip.FullAddress{Addr: addr2, Port: 80} 2021 if err := ep.Bind(bindAddr); err != nil { 2022 t.Fatalf("Bind(%+v): %s", bindAddr, err) 2023 } 2024 2025 var wg sync.WaitGroup 2026 defer wg.Wait() 2027 for i := 0; i < 3; i++ { 2028 wg.Add(1) 2029 go func() { 2030 defer wg.Done() 2031 for i := 0; i < 10; i++ { 2032 for _, f := range fragments { 2033 hdr := prependable.New(header.IPv6MinimumSize) 2034 2035 // Serialize IPv6 fixed header. 2036 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 2037 ip.Encode(&header.IPv6Fields{ 2038 PayloadLength: uint16(len(f.data)), 2039 // We're lying about transport protocol here so that we can generate 2040 // raw extension headers for the tests. 2041 TransportProtocol: tcpip.TransportProtocolNumber(f.nextHdr), 2042 HopLimit: 255, 2043 SrcAddr: f.srcAddr, 2044 DstAddr: f.dstAddr, 2045 }) 2046 2047 buf := buffer.MakeWithData(hdr.View()) 2048 buf.Append(buffer.NewViewWithData(f.data)) 2049 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 2050 Payload: buf, 2051 }) 2052 e.InjectInbound(ProtocolNumber, pkt) 2053 pkt.DecRef() 2054 } 2055 } 2056 }() 2057 } 2058 } 2059 2060 func TestInvalidIPv6Fragments(t *testing.T) { 2061 const ( 2062 linkAddr1 = tcpip.LinkAddress("\x0a\x0b\x0c\x0d\x0e\x0e") 2063 nicID = 1 2064 hoplimit = 255 2065 ident = 1 2066 data = "TEST_INVALID_IPV6_FRAGMENTS" 2067 ) 2068 2069 var ( 2070 addr1 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) 2071 addr2 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02")) 2072 ) 2073 2074 type fragmentData struct { 2075 ipv6Fields header.IPv6Fields 2076 ipv6FragmentFields header.IPv6SerializableFragmentExtHdr 2077 payload []byte 2078 } 2079 2080 tests := []struct { 2081 name string 2082 fragments []fragmentData 2083 wantMalformedIPPackets uint64 2084 wantMalformedFragments uint64 2085 expectICMP bool 2086 expectICMPType header.ICMPv6Type 2087 expectICMPCode header.ICMPv6Code 2088 expectICMPTypeSpecific uint32 2089 }{ 2090 { 2091 name: "fragment size is not a multiple of 8 and the M flag is true", 2092 fragments: []fragmentData{ 2093 { 2094 ipv6Fields: header.IPv6Fields{ 2095 PayloadLength: header.IPv6FragmentHeaderSize + 9, 2096 TransportProtocol: header.UDPProtocolNumber, 2097 HopLimit: hoplimit, 2098 SrcAddr: addr1, 2099 DstAddr: addr2, 2100 }, 2101 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2102 FragmentOffset: 0 >> 3, 2103 M: true, 2104 Identification: ident, 2105 }, 2106 payload: []byte(data)[:9], 2107 }, 2108 }, 2109 wantMalformedIPPackets: 1, 2110 wantMalformedFragments: 1, 2111 expectICMP: true, 2112 expectICMPType: header.ICMPv6ParamProblem, 2113 expectICMPCode: header.ICMPv6ErroneousHeader, 2114 expectICMPTypeSpecific: header.IPv6PayloadLenOffset, 2115 }, 2116 { 2117 name: "fragments reassembled into a payload exceeding the max IPv6 payload size", 2118 fragments: []fragmentData{ 2119 { 2120 ipv6Fields: header.IPv6Fields{ 2121 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2122 TransportProtocol: header.UDPProtocolNumber, 2123 HopLimit: hoplimit, 2124 SrcAddr: addr1, 2125 DstAddr: addr2, 2126 }, 2127 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2128 FragmentOffset: ((header.IPv6MaximumPayloadSize + 1) - 16) >> 3, 2129 M: false, 2130 Identification: ident, 2131 }, 2132 payload: []byte(data)[:16], 2133 }, 2134 }, 2135 wantMalformedIPPackets: 1, 2136 wantMalformedFragments: 1, 2137 expectICMP: true, 2138 expectICMPType: header.ICMPv6ParamProblem, 2139 expectICMPCode: header.ICMPv6ErroneousHeader, 2140 expectICMPTypeSpecific: header.IPv6MinimumSize + 2, /* offset for 'Fragment Offset' in the fragment header */ 2141 }, 2142 } 2143 2144 for _, test := range tests { 2145 t.Run(test.name, func(t *testing.T) { 2146 c := newTestContext() 2147 defer c.cleanup() 2148 s := c.s 2149 2150 e := channel.New(1, 1500, linkAddr1) 2151 defer e.Close() 2152 if err := s.CreateNIC(nicID, e); err != nil { 2153 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 2154 } 2155 protocolAddr := tcpip.ProtocolAddress{ 2156 Protocol: ProtocolNumber, 2157 AddressWithPrefix: addr2.WithPrefix(), 2158 } 2159 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 2160 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 2161 } 2162 s.SetRouteTable([]tcpip.Route{{ 2163 Destination: header.IPv6EmptySubnet, 2164 NIC: nicID, 2165 }}) 2166 2167 var expectICMPPayload []byte 2168 for _, f := range test.fragments { 2169 hdr := prependable.New(header.IPv6MinimumSize + header.IPv6FragmentHeaderSize) 2170 2171 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize + header.IPv6FragmentHeaderSize)) 2172 encodeArgs := f.ipv6Fields 2173 encodeArgs.ExtensionHeaders = append(encodeArgs.ExtensionHeaders, &f.ipv6FragmentFields) 2174 ip.Encode(&encodeArgs) 2175 2176 buf := buffer.MakeWithData(append(hdr.View(), f.payload...)) 2177 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 2178 Payload: buf, 2179 }) 2180 2181 if test.expectICMP { 2182 payload := stack.PayloadSince(pkt.NetworkHeader()) 2183 defer payload.Release() 2184 expectICMPPayload = payload.AsSlice() 2185 } 2186 2187 e.InjectInbound(ProtocolNumber, pkt) 2188 pkt.DecRef() 2189 } 2190 2191 if got, want := s.Stats().IP.MalformedPacketsReceived.Value(), test.wantMalformedIPPackets; got != want { 2192 t.Errorf("got Stats.IP.MalformedPacketsReceived = %d, want = %d", got, want) 2193 } 2194 if got, want := s.Stats().IP.MalformedFragmentsReceived.Value(), test.wantMalformedFragments; got != want { 2195 t.Errorf("got Stats.IP.MalformedFragmentsReceived = %d, want = %d", got, want) 2196 } 2197 2198 reply := e.Read() 2199 if !test.expectICMP { 2200 if reply != nil { 2201 t.Fatalf("unexpected ICMP error message received: %#v", reply) 2202 } 2203 return 2204 } 2205 if reply == nil { 2206 t.Fatal("expected ICMP error message missing") 2207 } 2208 2209 payload := stack.PayloadSince(reply.NetworkHeader()) 2210 defer payload.Release() 2211 checker.IPv6(t, payload, 2212 checker.SrcAddr(addr2), 2213 checker.DstAddr(addr1), 2214 checker.IPFullLength(uint16(header.IPv6MinimumSize+header.ICMPv6MinimumSize+len(expectICMPPayload))), 2215 checker.ICMPv6( 2216 checker.ICMPv6Type(test.expectICMPType), 2217 checker.ICMPv6Code(test.expectICMPCode), 2218 checker.ICMPv6TypeSpecific(test.expectICMPTypeSpecific), 2219 checker.ICMPv6Payload(expectICMPPayload), 2220 ), 2221 ) 2222 reply.DecRef() 2223 }) 2224 } 2225 } 2226 2227 func TestFragmentReassemblyTimeout(t *testing.T) { 2228 const ( 2229 linkAddr1 = tcpip.LinkAddress("\x0a\x0b\x0c\x0d\x0e\x0e") 2230 nicID = 1 2231 hoplimit = 255 2232 ident = 1 2233 data = "TEST_FRAGMENT_REASSEMBLY_TIMEOUT" 2234 ) 2235 var ( 2236 addr1 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) 2237 addr2 = tcpip.AddrFromSlice([]byte("\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02")) 2238 ) 2239 2240 type fragmentData struct { 2241 ipv6Fields header.IPv6Fields 2242 ipv6FragmentFields header.IPv6SerializableFragmentExtHdr 2243 payload []byte 2244 } 2245 2246 tests := []struct { 2247 name string 2248 fragments []fragmentData 2249 expectICMP bool 2250 }{ 2251 { 2252 name: "first fragment only", 2253 fragments: []fragmentData{ 2254 { 2255 ipv6Fields: header.IPv6Fields{ 2256 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2257 TransportProtocol: header.UDPProtocolNumber, 2258 HopLimit: hoplimit, 2259 SrcAddr: addr1, 2260 DstAddr: addr2, 2261 }, 2262 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2263 FragmentOffset: 0, 2264 M: true, 2265 Identification: ident, 2266 }, 2267 payload: []byte(data)[:16], 2268 }, 2269 }, 2270 expectICMP: true, 2271 }, 2272 { 2273 name: "two first fragments", 2274 fragments: []fragmentData{ 2275 { 2276 ipv6Fields: header.IPv6Fields{ 2277 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2278 TransportProtocol: header.UDPProtocolNumber, 2279 HopLimit: hoplimit, 2280 SrcAddr: addr1, 2281 DstAddr: addr2, 2282 }, 2283 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2284 FragmentOffset: 0, 2285 M: true, 2286 Identification: ident, 2287 }, 2288 payload: []byte(data)[:16], 2289 }, 2290 { 2291 ipv6Fields: header.IPv6Fields{ 2292 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2293 TransportProtocol: header.UDPProtocolNumber, 2294 HopLimit: hoplimit, 2295 SrcAddr: addr1, 2296 DstAddr: addr2, 2297 }, 2298 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2299 FragmentOffset: 0, 2300 M: true, 2301 Identification: ident, 2302 }, 2303 payload: []byte(data)[:16], 2304 }, 2305 }, 2306 expectICMP: true, 2307 }, 2308 { 2309 name: "second fragment only", 2310 fragments: []fragmentData{ 2311 { 2312 ipv6Fields: header.IPv6Fields{ 2313 PayloadLength: uint16(header.IPv6FragmentHeaderSize + len(data) - 16), 2314 TransportProtocol: header.UDPProtocolNumber, 2315 HopLimit: hoplimit, 2316 SrcAddr: addr1, 2317 DstAddr: addr2, 2318 }, 2319 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2320 FragmentOffset: 8, 2321 M: false, 2322 Identification: ident, 2323 }, 2324 payload: []byte(data)[16:], 2325 }, 2326 }, 2327 expectICMP: false, 2328 }, 2329 { 2330 name: "two fragments with a gap", 2331 fragments: []fragmentData{ 2332 { 2333 ipv6Fields: header.IPv6Fields{ 2334 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2335 TransportProtocol: header.UDPProtocolNumber, 2336 HopLimit: hoplimit, 2337 SrcAddr: addr1, 2338 DstAddr: addr2, 2339 }, 2340 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2341 FragmentOffset: 0, 2342 M: true, 2343 Identification: ident, 2344 }, 2345 payload: []byte(data)[:16], 2346 }, 2347 { 2348 ipv6Fields: header.IPv6Fields{ 2349 PayloadLength: uint16(header.IPv6FragmentHeaderSize + len(data) - 16), 2350 TransportProtocol: header.UDPProtocolNumber, 2351 HopLimit: hoplimit, 2352 SrcAddr: addr1, 2353 DstAddr: addr2, 2354 }, 2355 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2356 FragmentOffset: 8, 2357 M: false, 2358 Identification: ident, 2359 }, 2360 payload: []byte(data)[16:], 2361 }, 2362 }, 2363 expectICMP: true, 2364 }, 2365 { 2366 name: "two fragments with a gap in reverse order", 2367 fragments: []fragmentData{ 2368 { 2369 ipv6Fields: header.IPv6Fields{ 2370 PayloadLength: uint16(header.IPv6FragmentHeaderSize + len(data) - 16), 2371 TransportProtocol: header.UDPProtocolNumber, 2372 HopLimit: hoplimit, 2373 SrcAddr: addr1, 2374 DstAddr: addr2, 2375 }, 2376 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2377 FragmentOffset: 8, 2378 M: false, 2379 Identification: ident, 2380 }, 2381 payload: []byte(data)[16:], 2382 }, 2383 { 2384 ipv6Fields: header.IPv6Fields{ 2385 PayloadLength: header.IPv6FragmentHeaderSize + 16, 2386 TransportProtocol: header.UDPProtocolNumber, 2387 HopLimit: hoplimit, 2388 SrcAddr: addr1, 2389 DstAddr: addr2, 2390 }, 2391 ipv6FragmentFields: header.IPv6SerializableFragmentExtHdr{ 2392 FragmentOffset: 0, 2393 M: true, 2394 Identification: ident, 2395 }, 2396 payload: []byte(data)[:16], 2397 }, 2398 }, 2399 expectICMP: true, 2400 }, 2401 } 2402 2403 for _, test := range tests { 2404 t.Run(test.name, func(t *testing.T) { 2405 c := newTestContext() 2406 defer c.cleanup() 2407 s := c.s 2408 2409 e := channel.New(1, 1500, linkAddr1) 2410 defer e.Close() 2411 if err := s.CreateNIC(nicID, e); err != nil { 2412 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 2413 } 2414 protocolAddr := tcpip.ProtocolAddress{ 2415 Protocol: ProtocolNumber, 2416 AddressWithPrefix: addr2.WithPrefix(), 2417 } 2418 if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 2419 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 2420 } 2421 s.SetRouteTable([]tcpip.Route{{ 2422 Destination: header.IPv6EmptySubnet, 2423 NIC: nicID, 2424 }}) 2425 2426 var firstFragmentSent []byte 2427 for _, f := range test.fragments { 2428 hdr := prependable.New(header.IPv6MinimumSize + header.IPv6FragmentHeaderSize) 2429 2430 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize + header.IPv6FragmentHeaderSize)) 2431 encodeArgs := f.ipv6Fields 2432 encodeArgs.ExtensionHeaders = append(encodeArgs.ExtensionHeaders, &f.ipv6FragmentFields) 2433 ip.Encode(&encodeArgs) 2434 2435 fragHDR := header.IPv6Fragment(hdr.View()[header.IPv6MinimumSize:]) 2436 2437 buf := buffer.MakeWithData(append(hdr.View(), f.payload...)) 2438 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 2439 Payload: buf, 2440 }) 2441 2442 if firstFragmentSent == nil && fragHDR.FragmentOffset() == 0 { 2443 payload := stack.PayloadSince(pkt.NetworkHeader()) 2444 defer payload.Release() 2445 firstFragmentSent = payload.AsSlice() 2446 } 2447 2448 e.InjectInbound(ProtocolNumber, pkt) 2449 pkt.DecRef() 2450 } 2451 2452 c.clock.Advance(ReassembleTimeout) 2453 2454 reply := e.Read() 2455 if !test.expectICMP { 2456 if reply != nil { 2457 t.Fatalf("unexpected ICMP error message received: %#v", reply) 2458 } 2459 return 2460 } 2461 if reply == nil { 2462 t.Fatal("expected ICMP error message missing") 2463 } 2464 if firstFragmentSent == nil { 2465 t.Fatalf("unexpected ICMP error message received: %#v", reply) 2466 } 2467 2468 payload := stack.PayloadSince(reply.NetworkHeader()) 2469 defer payload.Release() 2470 checker.IPv6(t, payload, 2471 checker.SrcAddr(addr2), 2472 checker.DstAddr(addr1), 2473 checker.IPFullLength(uint16(header.IPv6MinimumSize+header.ICMPv6MinimumSize+len(firstFragmentSent))), 2474 checker.ICMPv6( 2475 checker.ICMPv6Type(header.ICMPv6TimeExceeded), 2476 checker.ICMPv6Code(header.ICMPv6ReassemblyTimeout), 2477 checker.ICMPv6Payload(firstFragmentSent), 2478 ), 2479 ) 2480 reply.DecRef() 2481 }) 2482 } 2483 } 2484 2485 func TestWriteStats(t *testing.T) { 2486 const nPackets = 3 2487 tests := []struct { 2488 name string 2489 setup func(*testing.T, *stack.Stack) 2490 allowPackets int 2491 expectSent int 2492 expectOutputDropped int 2493 expectPostroutingDropped int 2494 expectWritten int 2495 }{ 2496 { 2497 name: "Accept all", 2498 // No setup needed, tables accept everything by default. 2499 setup: func(*testing.T, *stack.Stack) {}, 2500 allowPackets: math.MaxInt32, 2501 expectSent: nPackets, 2502 expectOutputDropped: 0, 2503 expectPostroutingDropped: 0, 2504 expectWritten: nPackets, 2505 }, { 2506 name: "Accept all with error", 2507 // No setup needed, tables accept everything by default. 2508 setup: func(*testing.T, *stack.Stack) {}, 2509 allowPackets: nPackets - 1, 2510 expectSent: nPackets - 1, 2511 expectOutputDropped: 0, 2512 expectPostroutingDropped: 0, 2513 expectWritten: nPackets - 1, 2514 }, { 2515 name: "Drop all with Output chain", 2516 setup: func(t *testing.T, stk *stack.Stack) { 2517 // Install Output DROP rule. 2518 ipt := stk.IPTables() 2519 filter := ipt.GetTable(stack.FilterID, true /* ipv6 */) 2520 ruleIdx := filter.BuiltinChains[stack.Output] 2521 filter.Rules[ruleIdx].Target = &stack.DropTarget{} 2522 ipt.ForceReplaceTable(stack.FilterID, filter, true /* ipv6 */) 2523 }, 2524 allowPackets: math.MaxInt32, 2525 expectSent: 0, 2526 expectOutputDropped: nPackets, 2527 expectPostroutingDropped: 0, 2528 expectWritten: nPackets, 2529 }, { 2530 name: "Drop all with Postrouting chain", 2531 setup: func(t *testing.T, stk *stack.Stack) { 2532 // Install Output DROP rule. 2533 ipt := stk.IPTables() 2534 filter := ipt.GetTable(stack.NATID, true /* ipv6 */) 2535 ruleIdx := filter.BuiltinChains[stack.Postrouting] 2536 filter.Rules[ruleIdx].Target = &stack.DropTarget{} 2537 ipt.ForceReplaceTable(stack.NATID, filter, true /* ipv6 */) 2538 }, 2539 allowPackets: math.MaxInt32, 2540 expectSent: 0, 2541 expectOutputDropped: 0, 2542 expectPostroutingDropped: nPackets, 2543 expectWritten: nPackets, 2544 }, { 2545 name: "Drop some with Output chain", 2546 setup: func(t *testing.T, stk *stack.Stack) { 2547 // Install Output DROP rule that matches only 1 2548 // of the 3 packets. 2549 ipt := stk.IPTables() 2550 filter := ipt.GetTable(stack.FilterID, true /* ipv6 */) 2551 // We'll match and DROP the last packet. 2552 ruleIdx := filter.BuiltinChains[stack.Output] 2553 filter.Rules[ruleIdx].Target = &stack.DropTarget{} 2554 filter.Rules[ruleIdx].Matchers = []stack.Matcher{&limitedMatcher{nPackets - 1}} 2555 // Make sure the next rule is ACCEPT. 2556 filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{} 2557 ipt.ForceReplaceTable(stack.FilterID, filter, true /* ipv6 */) 2558 }, 2559 allowPackets: math.MaxInt32, 2560 expectSent: nPackets - 1, 2561 expectOutputDropped: 1, 2562 expectPostroutingDropped: 0, 2563 expectWritten: nPackets, 2564 }, { 2565 name: "Drop some with Postrouting chain", 2566 setup: func(t *testing.T, stk *stack.Stack) { 2567 // Install Postrouting DROP rule that matches only 1 2568 // of the 3 packets. 2569 ipt := stk.IPTables() 2570 filter := ipt.GetTable(stack.NATID, true /* ipv6 */) 2571 // We'll match and DROP the last packet. 2572 ruleIdx := filter.BuiltinChains[stack.Postrouting] 2573 filter.Rules[ruleIdx].Target = &stack.DropTarget{} 2574 filter.Rules[ruleIdx].Matchers = []stack.Matcher{&limitedMatcher{nPackets - 1}} 2575 // Make sure the next rule is ACCEPT. 2576 filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{} 2577 ipt.ForceReplaceTable(stack.NATID, filter, true /* ipv6 */) 2578 }, 2579 allowPackets: math.MaxInt32, 2580 expectSent: nPackets - 1, 2581 expectOutputDropped: 0, 2582 expectPostroutingDropped: 1, 2583 expectWritten: nPackets, 2584 }, 2585 } 2586 2587 for _, test := range tests { 2588 t.Run(test.name, func(t *testing.T) { 2589 c := newTestContext() 2590 defer c.cleanup() 2591 2592 ep := iptestutil.NewMockLinkEndpoint(header.IPv6MinimumMTU, &tcpip.ErrInvalidEndpointState{}, test.allowPackets) 2593 defer ep.Close() 2594 2595 rt := buildRoute(t, c, ep) 2596 defer rt.Release() 2597 test.setup(t, rt.Stack()) 2598 2599 nWritten := 0 2600 for i := 0; i < nPackets; i++ { 2601 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 2602 ReserveHeaderBytes: header.UDPMinimumSize + int(rt.MaxHeaderLength()), 2603 Payload: buffer.Buffer{}, 2604 }) 2605 defer pkt.DecRef() 2606 pkt.TransportHeader().Push(header.UDPMinimumSize) 2607 if err := rt.WritePacket(stack.NetworkHeaderParams{}, pkt); err != nil { 2608 break 2609 } 2610 nWritten++ 2611 } 2612 2613 if got := int(rt.Stats().IP.PacketsSent.Value()); got != test.expectSent { 2614 t.Errorf("got rt.Stats().IP.PacketsSent.Value() = %d, want = %d", got, test.expectSent) 2615 } 2616 if got := int(rt.Stats().IP.IPTablesOutputDropped.Value()); got != test.expectOutputDropped { 2617 t.Errorf("got rt.Stats().IP.IPTablesOutputDropped.Value() = %d, want = %d", got, test.expectOutputDropped) 2618 } 2619 if got := int(rt.Stats().IP.IPTablesPostroutingDropped.Value()); got != test.expectPostroutingDropped { 2620 t.Errorf("got r.Stats().IP.IPTablesPostroutingDropped.Value() = %d, want = %d", got, test.expectPostroutingDropped) 2621 } 2622 if nWritten != test.expectWritten { 2623 t.Errorf("got nWritten = %d, want = %d", nWritten, test.expectWritten) 2624 } 2625 }) 2626 } 2627 } 2628 2629 func buildRoute(t *testing.T, c testContext, ep stack.LinkEndpoint) *stack.Route { 2630 s := c.s 2631 if err := s.CreateNIC(1, ep); err != nil { 2632 t.Fatalf("CreateNIC(1, _) failed: %s", err) 2633 } 2634 var ( 2635 src = tcpip.AddrFromSlice([]byte("\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) 2636 dst = tcpip.AddrFromSlice([]byte("\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02")) 2637 ) 2638 protocolAddr := tcpip.ProtocolAddress{ 2639 Protocol: ProtocolNumber, 2640 AddressWithPrefix: src.WithPrefix(), 2641 } 2642 if err := s.AddProtocolAddress(1, protocolAddr, stack.AddressProperties{}); err != nil { 2643 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", 1, protocolAddr, err) 2644 } 2645 { 2646 mask := tcpip.MaskFrom("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") 2647 subnet, err := tcpip.NewSubnet(dst, mask) 2648 if err != nil { 2649 t.Fatalf("NewSubnet(%s, %s) failed: %v", dst, mask, err) 2650 } 2651 s.SetRouteTable([]tcpip.Route{{ 2652 Destination: subnet, 2653 NIC: 1, 2654 }}) 2655 } 2656 rt, err := s.FindRoute(1, src, dst, ProtocolNumber, false /* multicastLoop */) 2657 if err != nil { 2658 t.Fatalf("FindRoute(1, %s, %s, %d, false) = %s, want = nil", src, dst, ProtocolNumber, err) 2659 } 2660 return rt 2661 } 2662 2663 // limitedMatcher is an iptables matcher that matches after a certain number of 2664 // packets are checked against it. 2665 type limitedMatcher struct { 2666 limit int 2667 } 2668 2669 // Name implements Matcher.Name. 2670 func (*limitedMatcher) Name() string { 2671 return "limitedMatcher" 2672 } 2673 2674 // Match implements Matcher.Match. 2675 func (lm *limitedMatcher) Match(stack.Hook, *stack.PacketBuffer, string, string) (bool, bool) { 2676 if lm.limit == 0 { 2677 return true, false 2678 } 2679 lm.limit-- 2680 return false, false 2681 } 2682 2683 func knownNICIDs(proto *protocol) []tcpip.NICID { 2684 var nicIDs []tcpip.NICID 2685 2686 for k := range proto.mu.eps { 2687 nicIDs = append(nicIDs, k) 2688 } 2689 2690 return nicIDs 2691 } 2692 2693 func TestClearEndpointFromProtocolOnClose(t *testing.T) { 2694 c := newTestContext() 2695 defer c.cleanup() 2696 s := c.s 2697 2698 proto := s.NetworkProtocolInstance(ProtocolNumber).(*protocol) 2699 var nic testInterface 2700 ep := proto.NewEndpoint(&nic, nil).(*endpoint) 2701 var nicIDs []tcpip.NICID 2702 2703 proto.mu.Lock() 2704 foundEP, hasEndpointBeforeClose := proto.mu.eps[nic.ID()] 2705 nicIDs = knownNICIDs(proto) 2706 proto.mu.Unlock() 2707 if !hasEndpointBeforeClose { 2708 t.Fatalf("expected to find the nic id %d in the protocol's known nic ids (%v)", nic.ID(), nicIDs) 2709 } 2710 if foundEP != ep { 2711 t.Fatalf("found an incorrect endpoint mapped to nic id %d", nic.ID()) 2712 } 2713 2714 ep.Close() 2715 2716 proto.mu.Lock() 2717 _, hasEndpointAfterClose := proto.mu.eps[nic.ID()] 2718 nicIDs = knownNICIDs(proto) 2719 proto.mu.Unlock() 2720 if hasEndpointAfterClose { 2721 t.Fatalf("unexpectedly found an endpoint mapped to the nic id %d in the protocol's known nic ids (%v)", nic.ID(), nicIDs) 2722 } 2723 } 2724 2725 type fragmentInfo struct { 2726 offset uint16 2727 more bool 2728 payloadSize uint16 2729 } 2730 2731 var fragmentationTests = []struct { 2732 description string 2733 mtu uint32 2734 transHdrLen int 2735 payloadSize int 2736 wantFragments []fragmentInfo 2737 }{ 2738 { 2739 description: "No fragmentation", 2740 mtu: header.IPv6MinimumMTU, 2741 transHdrLen: 0, 2742 payloadSize: 1000, 2743 wantFragments: []fragmentInfo{ 2744 {offset: 0, payloadSize: 1000, more: false}, 2745 }, 2746 }, 2747 { 2748 description: "Fragmented", 2749 mtu: header.IPv6MinimumMTU, 2750 transHdrLen: 0, 2751 payloadSize: 2000, 2752 wantFragments: []fragmentInfo{ 2753 {offset: 0, payloadSize: 1240, more: true}, 2754 {offset: 154, payloadSize: 776, more: false}, 2755 }, 2756 }, 2757 { 2758 description: "Fragmented with mtu not a multiple of 8", 2759 mtu: header.IPv6MinimumMTU + 1, 2760 transHdrLen: 0, 2761 payloadSize: 2000, 2762 wantFragments: []fragmentInfo{ 2763 {offset: 0, payloadSize: 1240, more: true}, 2764 {offset: 154, payloadSize: 776, more: false}, 2765 }, 2766 }, 2767 { 2768 description: "No fragmentation with big header", 2769 mtu: 2000, 2770 transHdrLen: 100, 2771 payloadSize: 1000, 2772 wantFragments: []fragmentInfo{ 2773 {offset: 0, payloadSize: 1100, more: false}, 2774 }, 2775 }, 2776 { 2777 description: "Fragmented with big header", 2778 mtu: header.IPv6MinimumMTU, 2779 transHdrLen: 100, 2780 payloadSize: 1200, 2781 wantFragments: []fragmentInfo{ 2782 {offset: 0, payloadSize: 1240, more: true}, 2783 {offset: 154, payloadSize: 76, more: false}, 2784 }, 2785 }, 2786 } 2787 2788 func TestFragmentationWritePacket(t *testing.T) { 2789 const ttl = 42 2790 2791 for _, ft := range fragmentationTests { 2792 t.Run(ft.description, func(t *testing.T) { 2793 c := newTestContext() 2794 defer c.cleanup() 2795 2796 pkt := iptestutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber) 2797 defer pkt.DecRef() 2798 source := pkt.Clone() 2799 defer source.DecRef() 2800 2801 ep := iptestutil.NewMockLinkEndpoint(ft.mtu, nil, math.MaxInt32) 2802 defer ep.Close() 2803 2804 r := buildRoute(t, c, ep) 2805 defer r.Release() 2806 err := r.WritePacket(stack.NetworkHeaderParams{ 2807 Protocol: tcp.ProtocolNumber, 2808 TTL: ttl, 2809 TOS: stack.DefaultTOS, 2810 }, pkt) 2811 if err != nil { 2812 t.Fatalf("WritePacket(_, _, _): = %s", err) 2813 } 2814 if got := len(ep.WrittenPackets); got != len(ft.wantFragments) { 2815 t.Errorf("got len(ep.WrittenPackets) = %d, want = %d", got, len(ft.wantFragments)) 2816 } 2817 if got := int(r.Stats().IP.PacketsSent.Value()); got != len(ft.wantFragments) { 2818 t.Errorf("got c.Route.Stats().IP.PacketsSent.Value() = %d, want = %d", got, len(ft.wantFragments)) 2819 } 2820 if got := r.Stats().IP.OutgoingPacketErrors.Value(); got != 0 { 2821 t.Errorf("got r.Stats().IP.OutgoingPacketErrors.Value() = %d, want = 0", got) 2822 } 2823 if err := compareFragments(ep.WrittenPackets, source, ft.mtu, ft.wantFragments, tcp.ProtocolNumber); err != nil { 2824 t.Error(err) 2825 } 2826 }) 2827 } 2828 } 2829 2830 // TestFragmentationErrors checks that errors are returned from WritePacket 2831 // correctly. 2832 func TestFragmentationErrors(t *testing.T) { 2833 const ttl = 42 2834 2835 tests := []struct { 2836 description string 2837 mtu uint32 2838 transHdrLen int 2839 payloadSize int 2840 allowPackets int 2841 outgoingErrors int 2842 mockError tcpip.Error 2843 wantError tcpip.Error 2844 }{ 2845 { 2846 description: "No frag", 2847 mtu: 2000, 2848 payloadSize: 1000, 2849 transHdrLen: 0, 2850 allowPackets: 0, 2851 outgoingErrors: 1, 2852 mockError: &tcpip.ErrAborted{}, 2853 wantError: &tcpip.ErrAborted{}, 2854 }, 2855 { 2856 description: "Error on first frag", 2857 mtu: 1300, 2858 payloadSize: 3000, 2859 transHdrLen: 0, 2860 allowPackets: 0, 2861 outgoingErrors: 3, 2862 mockError: &tcpip.ErrAborted{}, 2863 wantError: &tcpip.ErrAborted{}, 2864 }, 2865 { 2866 description: "Error on second frag", 2867 mtu: 1500, 2868 payloadSize: 4000, 2869 transHdrLen: 0, 2870 allowPackets: 1, 2871 outgoingErrors: 2, 2872 mockError: &tcpip.ErrAborted{}, 2873 wantError: &tcpip.ErrAborted{}, 2874 }, 2875 { 2876 description: "Error when MTU is smaller than transport header", 2877 mtu: header.IPv6MinimumMTU, 2878 transHdrLen: 1500, 2879 payloadSize: 500, 2880 allowPackets: 0, 2881 outgoingErrors: 1, 2882 mockError: nil, 2883 wantError: &tcpip.ErrMessageTooLong{}, 2884 }, 2885 { 2886 description: "Error when MTU is smaller than IPv6 minimum MTU", 2887 mtu: header.IPv6MinimumMTU - 1, 2888 transHdrLen: 0, 2889 payloadSize: 500, 2890 allowPackets: 0, 2891 outgoingErrors: 1, 2892 mockError: nil, 2893 wantError: &tcpip.ErrInvalidEndpointState{}, 2894 }, 2895 } 2896 2897 for _, ft := range tests { 2898 t.Run(ft.description, func(t *testing.T) { 2899 c := newTestContext() 2900 defer c.cleanup() 2901 2902 pkt := iptestutil.MakeRandPkt(ft.transHdrLen, extraHeaderReserve+header.IPv6MinimumSize, []int{ft.payloadSize}, header.IPv6ProtocolNumber) 2903 defer pkt.DecRef() 2904 ep := iptestutil.NewMockLinkEndpoint(ft.mtu, ft.mockError, ft.allowPackets) 2905 defer ep.Close() 2906 2907 r := buildRoute(t, c, ep) 2908 defer r.Release() 2909 err := r.WritePacket(stack.NetworkHeaderParams{ 2910 Protocol: tcp.ProtocolNumber, 2911 TTL: ttl, 2912 TOS: stack.DefaultTOS, 2913 }, pkt) 2914 if diff := cmp.Diff(ft.wantError, err); diff != "" { 2915 t.Errorf("unexpected error from WritePacket(_, _, _), (-want, +got):\n%s", diff) 2916 } 2917 if got := int(r.Stats().IP.PacketsSent.Value()); got != ft.allowPackets { 2918 t.Errorf("got r.Stats().IP.PacketsSent.Value() = %d, want = %d", got, ft.allowPackets) 2919 } 2920 if got := int(r.Stats().IP.OutgoingPacketErrors.Value()); got != ft.outgoingErrors { 2921 t.Errorf("got r.Stats().IP.OutgoingPacketErrors.Value() = %d, want = %d", got, ft.outgoingErrors) 2922 } 2923 }) 2924 } 2925 } 2926 2927 type icmpError struct { 2928 icmpType header.ICMPv6Type 2929 icmpCode header.ICMPv6Code 2930 } 2931 2932 const ( 2933 incomingNICID = 1 2934 outgoingNICID = 2 2935 randomSequence = 123 2936 randomIdent = 42 2937 ) 2938 2939 var ( 2940 incomingIPv6Addr = tcpip.AddressWithPrefix{ 2941 Address: tcpip.AddrFromSlice(net.ParseIP("10::1").To16()), 2942 PrefixLen: 64, 2943 } 2944 outgoingIPv6Addr = tcpip.AddressWithPrefix{ 2945 Address: tcpip.AddrFromSlice(net.ParseIP("11::1").To16()), 2946 PrefixLen: 64, 2947 } 2948 multicastIPv6Addr = tcpip.AddressWithPrefix{ 2949 Address: tcpip.AddrFromSlice(net.ParseIP("ff00::").To16()), 2950 PrefixLen: 64, 2951 } 2952 remoteIPv6Addr1 = tcpip.AddrFromSlice(net.ParseIP("10::2").To16()) 2953 remoteIPv6Addr2 = tcpip.AddrFromSlice(net.ParseIP("11::2").To16()) 2954 unreachableIPv6Addr = tcpip.AddrFromSlice(net.ParseIP("12::2").To16()) 2955 linkLocalIPv6Addr = tcpip.AddrFromSlice(net.ParseIP("fe80::").To16()) 2956 defaultEndpointConfigs = map[tcpip.NICID]tcpip.AddressWithPrefix{ 2957 incomingNICID: incomingIPv6Addr, 2958 outgoingNICID: outgoingIPv6Addr, 2959 } 2960 ) 2961 2962 func TestForwarding(t *testing.T) { 2963 tests := []struct { 2964 name string 2965 extHdr func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) 2966 TTL uint8 2967 payloadLength int 2968 srcAddr tcpip.Address 2969 dstAddr tcpip.Address 2970 expectedPacketUnrouteableErrors uint64 2971 expectedInitializingSourceErrors uint64 2972 expectedLinkLocalSourceErrors uint64 2973 expectedLinkLocalDestErrors uint64 2974 expectedExtensionHeaderErrors uint64 2975 expectedPacketTooBigErrors uint64 2976 expectedExhaustedTTLErrors uint64 2977 expectPacketForwarded bool 2978 expectedFragmentsForwarded []fragmentInfo 2979 expectedICMPError *icmpError 2980 }{ 2981 { 2982 name: "TTL of zero", 2983 TTL: 0, 2984 srcAddr: remoteIPv6Addr1, 2985 dstAddr: remoteIPv6Addr2, 2986 expectedICMPError: &icmpError{ 2987 icmpType: header.ICMPv6TimeExceeded, 2988 icmpCode: header.ICMPv6HopLimitExceeded, 2989 }, 2990 expectedExhaustedTTLErrors: 1, 2991 expectPacketForwarded: false, 2992 }, 2993 { 2994 name: "TTL of one", 2995 TTL: 1, 2996 srcAddr: remoteIPv6Addr1, 2997 dstAddr: remoteIPv6Addr2, 2998 expectedICMPError: &icmpError{ 2999 icmpType: header.ICMPv6TimeExceeded, 3000 icmpCode: header.ICMPv6HopLimitExceeded, 3001 }, 3002 expectedExhaustedTTLErrors: 1, 3003 expectPacketForwarded: false, 3004 }, 3005 { 3006 name: "TTL of two", 3007 TTL: 2, 3008 srcAddr: remoteIPv6Addr1, 3009 dstAddr: remoteIPv6Addr2, 3010 expectPacketForwarded: true, 3011 }, 3012 { 3013 name: "TTL of three", 3014 TTL: 3, 3015 srcAddr: remoteIPv6Addr1, 3016 dstAddr: remoteIPv6Addr2, 3017 expectPacketForwarded: true, 3018 }, 3019 { 3020 name: "Max TTL", 3021 TTL: math.MaxUint8, 3022 srcAddr: remoteIPv6Addr1, 3023 dstAddr: remoteIPv6Addr2, 3024 expectPacketForwarded: true, 3025 }, 3026 { 3027 name: "Network unreachable", 3028 TTL: 2, 3029 srcAddr: remoteIPv6Addr1, 3030 dstAddr: unreachableIPv6Addr, 3031 expectedICMPError: &icmpError{ 3032 icmpType: header.ICMPv6DstUnreachable, 3033 icmpCode: header.ICMPv6NetworkUnreachable, 3034 }, 3035 expectedPacketUnrouteableErrors: 1, 3036 expectPacketForwarded: false, 3037 }, 3038 { 3039 name: "Link local destination", 3040 TTL: 2, 3041 srcAddr: remoteIPv6Addr1, 3042 dstAddr: linkLocalIPv6Addr, 3043 expectedLinkLocalDestErrors: 1, 3044 expectPacketForwarded: false, 3045 }, 3046 { 3047 name: "Link local source", 3048 TTL: 2, 3049 srcAddr: linkLocalIPv6Addr, 3050 dstAddr: remoteIPv6Addr2, 3051 expectedLinkLocalSourceErrors: 1, 3052 expectPacketForwarded: false, 3053 }, 3054 { 3055 name: "Unspecified source", 3056 TTL: 2, 3057 srcAddr: header.IPv6Any, 3058 dstAddr: remoteIPv6Addr2, 3059 expectedInitializingSourceErrors: 1, 3060 expectPacketForwarded: false, 3061 }, 3062 { 3063 name: "Hopbyhop with unknown option skippable action", 3064 TTL: 2, 3065 srcAddr: remoteIPv6Addr1, 3066 dstAddr: remoteIPv6Addr2, 3067 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3068 return []byte{ 3069 nextHdr, 1, 3070 3071 // Skippable unknown. 3072 63, 4, 1, 2, 3, 4, 3073 3074 // Skippable unknown. 3075 62, 6, 1, 2, 3, 4, 5, 6, 3076 }, hopByHopExtHdrID, checker.IPv6ExtHdr(checker.IPv6HopByHopExtensionHeader(checker.IPv6UnknownOption(), checker.IPv6UnknownOption())) 3077 }, 3078 expectPacketForwarded: true, 3079 }, 3080 { 3081 name: "Hopbyhop with unknown option discard action", 3082 TTL: 2, 3083 srcAddr: remoteIPv6Addr1, 3084 dstAddr: remoteIPv6Addr2, 3085 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3086 return []byte{ 3087 nextHdr, 1, 3088 3089 // Skippable unknown. 3090 63, 4, 1, 2, 3, 4, 3091 3092 // Discard unknown. 3093 127, 6, 1, 2, 3, 4, 5, 6, 3094 }, hopByHopExtHdrID, nil 3095 }, 3096 expectedExtensionHeaderErrors: 1, 3097 expectPacketForwarded: false, 3098 }, 3099 { 3100 name: "Hopbyhop with unknown option discard and send icmp action", 3101 TTL: 2, 3102 srcAddr: remoteIPv6Addr1, 3103 dstAddr: remoteIPv6Addr2, 3104 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3105 return []byte{ 3106 nextHdr, 1, 3107 3108 // Skippable unknown. 3109 63, 4, 1, 2, 3, 4, 3110 3111 // Discard & send ICMP if option is unknown. 3112 191, 6, 1, 2, 3, 4, 5, 6, 3113 }, hopByHopExtHdrID, nil 3114 }, 3115 expectedICMPError: &icmpError{ 3116 icmpType: header.ICMPv6ParamProblem, 3117 icmpCode: header.ICMPv6UnknownOption, 3118 }, 3119 expectedExtensionHeaderErrors: 1, 3120 expectPacketForwarded: false, 3121 }, 3122 { 3123 name: "Hopbyhop with unknown option discard and send icmp action", 3124 TTL: 2, 3125 srcAddr: remoteIPv6Addr1, 3126 dstAddr: remoteIPv6Addr2, 3127 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3128 return []byte{ 3129 nextHdr, 1, 3130 3131 // Skippable unknown. 3132 63, 4, 1, 2, 3, 4, 3133 3134 // Discard & send ICMP unless packet is for multicast destination if 3135 // option is unknown. 3136 255, 6, 1, 2, 3, 4, 5, 6, 3137 }, hopByHopExtHdrID, nil 3138 }, 3139 expectedICMPError: &icmpError{ 3140 icmpType: header.ICMPv6ParamProblem, 3141 icmpCode: header.ICMPv6UnknownOption, 3142 }, 3143 expectedExtensionHeaderErrors: 1, 3144 expectPacketForwarded: false, 3145 }, 3146 { 3147 name: "Hopbyhop with router alert option", 3148 TTL: 2, 3149 srcAddr: remoteIPv6Addr1, 3150 dstAddr: remoteIPv6Addr2, 3151 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3152 return []byte{ 3153 nextHdr, 0, 3154 3155 // Router Alert option. 3156 5, 2, 0, 0, 0, 0, 3157 }, hopByHopExtHdrID, checker.IPv6ExtHdr(checker.IPv6HopByHopExtensionHeader(checker.IPv6RouterAlert(header.IPv6RouterAlertMLD))) 3158 }, 3159 expectPacketForwarded: true, 3160 }, 3161 { 3162 name: "Hopbyhop with two router alert options", 3163 TTL: 2, 3164 srcAddr: remoteIPv6Addr1, 3165 dstAddr: remoteIPv6Addr2, 3166 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3167 return []byte{ 3168 nextHdr, 1, 3169 3170 // Router Alert option. 3171 5, 2, 0, 0, 0, 0, 3172 3173 // Router Alert option. 3174 5, 2, 0, 0, 0, 0, 3175 }, hopByHopExtHdrID, nil 3176 }, 3177 expectedExtensionHeaderErrors: 1, 3178 expectPacketForwarded: false, 3179 }, 3180 { 3181 name: "Can't fragment", 3182 TTL: 2, 3183 payloadLength: header.IPv6MinimumMTU + 1, 3184 srcAddr: remoteIPv6Addr1, 3185 dstAddr: remoteIPv6Addr2, 3186 expectedICMPError: &icmpError{ 3187 icmpType: header.ICMPv6PacketTooBig, 3188 icmpCode: header.ICMPv6UnusedCode, 3189 }, 3190 expectedPacketTooBigErrors: 1, 3191 expectPacketForwarded: false, 3192 }, 3193 } 3194 3195 for _, test := range tests { 3196 t.Run(test.name, func(t *testing.T) { 3197 c := newTestContext() 3198 defer c.cleanup() 3199 s := c.s 3200 3201 endpoints := make(map[tcpip.NICID]*channel.Endpoint) 3202 for nicID, addr := range defaultEndpointConfigs { 3203 ep := channel.New(1, header.IPv6MinimumMTU, "") 3204 defer ep.Close() 3205 3206 if err := s.CreateNIC(nicID, ep); err != nil { 3207 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 3208 } 3209 addr := tcpip.ProtocolAddress{Protocol: ProtocolNumber, AddressWithPrefix: addr} 3210 if err := s.AddProtocolAddress(nicID, addr, stack.AddressProperties{}); err != nil { 3211 t.Fatalf("s.AddProtocolAddress(%d, %+v, {}): %s", nicID, addr, err) 3212 } 3213 s.SetNICMulticastForwarding(nicID, ProtocolNumber, true /* enabled */) 3214 endpoints[nicID] = ep 3215 } 3216 3217 s.SetRouteTable([]tcpip.Route{ 3218 { 3219 Destination: incomingIPv6Addr.Subnet(), 3220 NIC: incomingNICID, 3221 }, 3222 { 3223 Destination: outgoingIPv6Addr.Subnet(), 3224 NIC: outgoingNICID, 3225 }, 3226 { 3227 Destination: multicastIPv6Addr.Subnet(), 3228 NIC: outgoingNICID, 3229 }, 3230 }) 3231 3232 if err := s.SetForwardingDefaultAndAllNICs(ProtocolNumber, true); err != nil { 3233 t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d, true): %s", ProtocolNumber, err) 3234 } 3235 3236 transportProtocol := header.ICMPv6ProtocolNumber 3237 var extHdrBytes []byte 3238 extHdrChecker := checker.IPv6ExtHdr() 3239 if test.extHdr != nil { 3240 nextHdrID := hopByHopExtHdrID 3241 extHdrBytes, nextHdrID, extHdrChecker = test.extHdr(uint8(header.ICMPv6ProtocolNumber)) 3242 transportProtocol = tcpip.TransportProtocolNumber(nextHdrID) 3243 } 3244 extHdrLen := len(extHdrBytes) 3245 3246 ipHeaderLength := header.IPv6MinimumSize 3247 icmpHeaderLength := header.ICMPv6MinimumSize 3248 payloadLength := icmpHeaderLength + test.payloadLength + extHdrLen 3249 totalLength := ipHeaderLength + payloadLength 3250 hdr := prependable.New(totalLength) 3251 hdr.Prepend(test.payloadLength) 3252 icmpH := header.ICMPv6(hdr.Prepend(icmpHeaderLength)) 3253 3254 icmpH.SetIdent(randomIdent) 3255 icmpH.SetSequence(randomSequence) 3256 icmpH.SetType(header.ICMPv6EchoRequest) 3257 icmpH.SetCode(header.ICMPv6UnusedCode) 3258 icmpH.SetChecksum(0) 3259 icmpH.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 3260 Header: icmpH, 3261 Src: test.srcAddr, 3262 Dst: test.dstAddr, 3263 })) 3264 copy(hdr.Prepend(extHdrLen), extHdrBytes) 3265 ip := header.IPv6(hdr.Prepend(ipHeaderLength)) 3266 ip.Encode(&header.IPv6Fields{ 3267 PayloadLength: uint16(payloadLength), 3268 TransportProtocol: transportProtocol, 3269 HopLimit: test.TTL, 3270 SrcAddr: test.srcAddr, 3271 DstAddr: test.dstAddr, 3272 }) 3273 request := stack.NewPacketBuffer(stack.PacketBufferOptions{ 3274 Payload: buffer.MakeWithData(hdr.View()), 3275 }) 3276 3277 incomingEndpoint, ok := endpoints[incomingNICID] 3278 if !ok { 3279 t.Fatalf("endpoints[%d] = (_, false), want (_, true)", incomingNICID) 3280 } 3281 3282 incomingEndpoint.InjectInbound(ProtocolNumber, request) 3283 request.DecRef() 3284 3285 reply := incomingEndpoint.Read() 3286 3287 outgoingEndpoint, ok := endpoints[outgoingNICID] 3288 if !ok { 3289 t.Fatalf("endpoints[%d] = (_, false), want (_, true)", outgoingNICID) 3290 } 3291 3292 if test.expectedICMPError != nil { 3293 if reply == nil { 3294 t.Fatalf("Expected ICMP packet type %d through incoming NIC", test.expectedICMPError.icmpType) 3295 } 3296 3297 // As per RFC 4443, page 9: 3298 // 3299 // The returned ICMP packet will contain as much of invoking packet 3300 // as possible without the ICMPv6 packet exceeding the minimum IPv6 3301 // MTU. 3302 expectedICMPPayloadLength := func() int { 3303 maxICMPPayloadLength := header.IPv6MinimumMTU - ipHeaderLength - icmpHeaderLength 3304 if len(hdr.View()) > maxICMPPayloadLength { 3305 return maxICMPPayloadLength 3306 } 3307 return len(hdr.View()) 3308 } 3309 3310 payload := stack.PayloadSince(reply.NetworkHeader()) 3311 defer payload.Release() 3312 checker.IPv6(t, payload, 3313 checker.SrcAddr(incomingIPv6Addr.Address), 3314 checker.DstAddr(test.srcAddr), 3315 checker.TTL(DefaultTTL), 3316 checker.ICMPv6( 3317 checker.ICMPv6Type(test.expectedICMPError.icmpType), 3318 checker.ICMPv6Code(test.expectedICMPError.icmpCode), 3319 checker.ICMPv6Payload(hdr.View()[:expectedICMPPayloadLength()]), 3320 ), 3321 ) 3322 reply.DecRef() 3323 3324 if n := outgoingEndpoint.Drain(); n != 0 { 3325 t.Fatalf("e2.Drain() = %d, want = 0", n) 3326 } 3327 } else if reply != nil { 3328 t.Fatalf("Expected no ICMP packet through incoming NIC, instead found: %#v", reply) 3329 } 3330 3331 reply = outgoingEndpoint.Read() 3332 if test.expectPacketForwarded { 3333 if reply == nil { 3334 t.Fatal("Expected ICMP Echo Request packet through outgoing NIC") 3335 } 3336 3337 payload := stack.PayloadSince(reply.NetworkHeader()) 3338 defer payload.Release() 3339 checker.IPv6WithExtHdr(t, payload, 3340 checker.SrcAddr(test.srcAddr), 3341 checker.DstAddr(test.dstAddr), 3342 checker.TTL(test.TTL-1), 3343 extHdrChecker, 3344 checker.ICMPv6( 3345 checker.ICMPv6Type(header.ICMPv6EchoRequest), 3346 checker.ICMPv6Code(header.ICMPv6UnusedCode), 3347 checker.ICMPv6Payload(nil), 3348 ), 3349 ) 3350 reply.DecRef() 3351 3352 if n := incomingEndpoint.Drain(); n != 0 { 3353 t.Fatalf("e1.Drain() = %d, want = 0", n) 3354 } 3355 } else if reply != nil { 3356 t.Fatalf("Expected no ICMP Echo packet through outgoing NIC, instead found: %#v", reply) 3357 } 3358 3359 if got, want := s.Stats().IP.Forwarding.InitializingSource.Value(), test.expectedInitializingSourceErrors; got != want { 3360 t.Errorf("s.Stats().IP.Forwarding.InitializingSource.Value() = %d, want = %d", got, want) 3361 } 3362 3363 if got, want := s.Stats().IP.Forwarding.LinkLocalSource.Value(), test.expectedLinkLocalSourceErrors; got != want { 3364 t.Errorf("s.Stats().IP.Forwarding.LinkLocalSource.Value() = %d, want = %d", got, want) 3365 } 3366 3367 if got, want := s.Stats().IP.Forwarding.LinkLocalDestination.Value(), test.expectedLinkLocalDestErrors; got != want { 3368 t.Errorf("s.Stats().IP.Forwarding.LinkLocalDestination.Value() = %d, want = %d", got, want) 3369 } 3370 3371 if got, want := s.Stats().IP.Forwarding.ExhaustedTTL.Value(), test.expectedExhaustedTTLErrors; got != want { 3372 t.Errorf("s.Stats().IP.Forwarding.ExhaustedTTL.Value() = %d, want = %d", got, want) 3373 } 3374 3375 if got, want := s.Stats().IP.Forwarding.Unrouteable.Value(), test.expectedPacketUnrouteableErrors; got != want { 3376 t.Errorf("s.Stats().IP.Forwarding.Unrouteable.Value() = %d, want = %d", got, want) 3377 } 3378 3379 if got, want := s.Stats().IP.Forwarding.ExtensionHeaderProblem.Value(), test.expectedExtensionHeaderErrors; got != want { 3380 t.Errorf("s.Stats().IP.Forwarding.ExtensionHeaderProblem.Value() = %d, want = %d", got, want) 3381 } 3382 3383 if got, want := s.Stats().IP.Forwarding.PacketTooBig.Value(), test.expectedPacketTooBigErrors; got != want { 3384 t.Errorf("s.Stats().IP.Forwarding.PacketTooBig.Value() = %d, want = %d", got, want) 3385 } 3386 3387 totalExpectedErrors := test.expectedPacketUnrouteableErrors + test.expectedPacketTooBigErrors + test.expectedExtensionHeaderErrors + test.expectedLinkLocalSourceErrors + test.expectedLinkLocalDestErrors + test.expectedExhaustedTTLErrors + test.expectedInitializingSourceErrors 3388 if got, want := s.Stats().IP.Forwarding.Errors.Value(), totalExpectedErrors; got != want { 3389 t.Errorf("s.Stats().IP.Forwarding.Errors.Value() = %d, want = %d", got, want) 3390 } 3391 }) 3392 } 3393 } 3394 3395 func TestMulticastForwarding(t *testing.T) { 3396 const ( 3397 multicastRouteMinTTL = 2 3398 packetTTL = 2 3399 ) 3400 3401 tests := []struct { 3402 name string 3403 extHdr func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) 3404 payloadLength int 3405 expectedExtensionHeaderErrors uint64 3406 expectedPacketTooBigErrors uint64 3407 expectPacketForwarded bool 3408 expectedICMPError *icmpError 3409 }{ 3410 { 3411 name: "Hopbyhop with unknown option skippable action", 3412 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3413 return []byte{ 3414 nextHdr, 1, 3415 3416 // Skippable unknown. 3417 63, 4, 1, 2, 3, 4, 3418 3419 // Skippable unknown. 3420 62, 6, 1, 2, 3, 4, 5, 6, 3421 }, hopByHopExtHdrID, checker.IPv6ExtHdr(checker.IPv6HopByHopExtensionHeader(checker.IPv6UnknownOption(), checker.IPv6UnknownOption())) 3422 }, 3423 expectPacketForwarded: true, 3424 }, 3425 { 3426 name: "Hopbyhop with unknown option discard action", 3427 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3428 return []byte{ 3429 nextHdr, 1, 3430 3431 // Skippable unknown. 3432 63, 4, 1, 2, 3, 4, 3433 3434 // Discard unknown. 3435 127, 6, 1, 2, 3, 4, 5, 6, 3436 }, hopByHopExtHdrID, nil 3437 }, 3438 expectedExtensionHeaderErrors: 1, 3439 expectPacketForwarded: false, 3440 }, 3441 { 3442 name: "Hopbyhop with unknown option discard and send icmp action", 3443 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3444 return []byte{ 3445 nextHdr, 1, 3446 3447 // Skippable unknown. 3448 63, 4, 1, 2, 3, 4, 3449 3450 // Discard & send ICMP if option is unknown. 3451 191, 6, 1, 2, 3, 4, 5, 6, 3452 }, hopByHopExtHdrID, nil 3453 }, 3454 expectedICMPError: &icmpError{ 3455 icmpType: header.ICMPv6ParamProblem, 3456 icmpCode: header.ICMPv6UnknownOption, 3457 }, 3458 expectedExtensionHeaderErrors: 1, 3459 expectPacketForwarded: false, 3460 }, 3461 { 3462 name: "Hopbyhop with unknown option discard and don't send icmp action for multicast", 3463 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3464 return []byte{ 3465 nextHdr, 1, 3466 3467 // Skippable unknown. 3468 63, 4, 1, 2, 3, 4, 3469 3470 // Discard & send ICMP unless packet is for multicast destination if 3471 // option is unknown. 3472 255, 6, 1, 2, 3, 4, 5, 6, 3473 }, hopByHopExtHdrID, nil 3474 }, 3475 expectedExtensionHeaderErrors: 1, 3476 expectPacketForwarded: false, 3477 }, 3478 { 3479 name: "Hopbyhop with router alert option", 3480 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3481 return []byte{ 3482 nextHdr, 0, 3483 3484 // Router Alert option. 3485 5, 2, 0, 0, 0, 0, 3486 }, hopByHopExtHdrID, checker.IPv6ExtHdr(checker.IPv6HopByHopExtensionHeader(checker.IPv6RouterAlert(header.IPv6RouterAlertMLD))) 3487 }, 3488 expectPacketForwarded: true, 3489 }, 3490 { 3491 name: "Hopbyhop with two router alert options", 3492 extHdr: func(nextHdr uint8) ([]byte, uint8, checker.NetworkChecker) { 3493 return []byte{ 3494 nextHdr, 1, 3495 3496 // Router Alert option. 3497 5, 2, 0, 0, 0, 0, 3498 3499 // Router Alert option. 3500 5, 2, 0, 0, 0, 0, 3501 }, hopByHopExtHdrID, nil 3502 }, 3503 expectedExtensionHeaderErrors: 1, 3504 expectPacketForwarded: false, 3505 }, 3506 { 3507 name: "Can't fragment", 3508 payloadLength: header.IPv6MinimumMTU + 1, 3509 expectedICMPError: &icmpError{ 3510 icmpType: header.ICMPv6PacketTooBig, 3511 icmpCode: header.ICMPv6UnusedCode, 3512 }, 3513 expectedPacketTooBigErrors: 1, 3514 expectPacketForwarded: false, 3515 }, 3516 } 3517 3518 for _, test := range tests { 3519 t.Run(test.name, func(t *testing.T) { 3520 c := newTestContext() 3521 defer c.cleanup() 3522 s := c.s 3523 3524 if _, err := s.EnableMulticastForwardingForProtocol(ProtocolNumber, &fakeMulticastEventDispatcher{}); err != nil { 3525 t.Fatalf("s.EnableMulticastForwardingForProtocol(%d, _): (_, %s)", ProtocolNumber, err) 3526 } 3527 3528 endpoints := make(map[tcpip.NICID]*channel.Endpoint) 3529 for nicID, addr := range defaultEndpointConfigs { 3530 ep := channel.New(1, header.IPv6MinimumMTU, "") 3531 defer ep.Close() 3532 3533 if err := s.CreateNIC(nicID, ep); err != nil { 3534 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 3535 } 3536 addr := tcpip.ProtocolAddress{Protocol: ProtocolNumber, AddressWithPrefix: addr} 3537 if err := s.AddProtocolAddress(nicID, addr, stack.AddressProperties{}); err != nil { 3538 t.Fatalf("s.AddProtocolAddress(%d, %+v, {}): %s", nicID, addr, err) 3539 } 3540 s.SetNICMulticastForwarding(nicID, ProtocolNumber, true /* enabled */) 3541 endpoints[nicID] = ep 3542 } 3543 3544 s.SetRouteTable([]tcpip.Route{ 3545 { 3546 Destination: header.IPv6EmptySubnet, 3547 NIC: incomingNICID, 3548 }, 3549 }) 3550 3551 srcAddr := remoteIPv6Addr1 3552 dstAddr := multicastIPv6Addr.Address 3553 3554 outgoingInterfaces := []stack.MulticastRouteOutgoingInterface{ 3555 {ID: outgoingNICID, MinTTL: multicastRouteMinTTL}, 3556 } 3557 addresses := stack.UnicastSourceAndMulticastDestination{ 3558 Source: srcAddr, 3559 Destination: multicastIPv6Addr.Address, 3560 } 3561 3562 route := stack.MulticastRoute{ 3563 ExpectedInputInterface: incomingNICID, 3564 OutgoingInterfaces: outgoingInterfaces, 3565 } 3566 3567 if err := s.AddMulticastRoute(ProtocolNumber, addresses, route); err != nil { 3568 t.Fatalf("s.AddMulticastRoute(%d, %#v, %#v): = %s", ProtocolNumber, addresses, route, err) 3569 } 3570 3571 transportProtocol := header.ICMPv6ProtocolNumber 3572 var extHdrBytes []byte 3573 extHdrChecker := checker.IPv6ExtHdr() 3574 if test.extHdr != nil { 3575 nextHdrID := hopByHopExtHdrID 3576 extHdrBytes, nextHdrID, extHdrChecker = test.extHdr(uint8(header.ICMPv6ProtocolNumber)) 3577 transportProtocol = tcpip.TransportProtocolNumber(nextHdrID) 3578 } 3579 extHdrLen := len(extHdrBytes) 3580 3581 ipHeaderLength := header.IPv6MinimumSize 3582 icmpHeaderLength := header.ICMPv6MinimumSize 3583 payloadLength := icmpHeaderLength + test.payloadLength + extHdrLen 3584 totalLength := ipHeaderLength + payloadLength 3585 hdr := prependable.New(totalLength) 3586 hdr.Prepend(test.payloadLength) 3587 icmpH := header.ICMPv6(hdr.Prepend(icmpHeaderLength)) 3588 3589 icmpH.SetIdent(randomIdent) 3590 icmpH.SetSequence(randomSequence) 3591 icmpH.SetType(header.ICMPv6EchoRequest) 3592 icmpH.SetCode(header.ICMPv6UnusedCode) 3593 icmpH.SetChecksum(0) 3594 icmpH.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 3595 Header: icmpH, 3596 Src: srcAddr, 3597 Dst: dstAddr, 3598 })) 3599 copy(hdr.Prepend(extHdrLen), extHdrBytes) 3600 ip := header.IPv6(hdr.Prepend(ipHeaderLength)) 3601 ip.Encode(&header.IPv6Fields{ 3602 PayloadLength: uint16(payloadLength), 3603 TransportProtocol: transportProtocol, 3604 HopLimit: packetTTL, 3605 SrcAddr: srcAddr, 3606 DstAddr: dstAddr, 3607 }) 3608 request := stack.NewPacketBuffer(stack.PacketBufferOptions{ 3609 Payload: buffer.MakeWithData(hdr.View()), 3610 }) 3611 3612 incomingEndpoint, ok := endpoints[incomingNICID] 3613 if !ok { 3614 t.Fatalf("endpoints[%d] = (_, false), want (_, true)", incomingNICID) 3615 } 3616 3617 incomingEndpoint.InjectInbound(ProtocolNumber, request) 3618 request.DecRef() 3619 3620 reply := incomingEndpoint.Read() 3621 3622 outgoingEndpoint, ok := endpoints[outgoingNICID] 3623 if !ok { 3624 t.Fatalf("endpoints[%d] = (_, false), want (_, true)", outgoingNICID) 3625 } 3626 3627 if test.expectedICMPError != nil { 3628 if reply == nil { 3629 t.Fatalf("Expected ICMP packet type %d through incoming NIC", test.expectedICMPError.icmpType) 3630 } 3631 3632 // As per RFC 4443, page 9: 3633 // 3634 // The returned ICMP packet will contain as much of invoking packet 3635 // as possible without the ICMPv6 packet exceeding the minimum IPv6 3636 // MTU. 3637 expectedICMPPayloadLength := func() int { 3638 maxICMPPayloadLength := header.IPv6MinimumMTU - ipHeaderLength - icmpHeaderLength 3639 if len(hdr.View()) > maxICMPPayloadLength { 3640 return maxICMPPayloadLength 3641 } 3642 return len(hdr.View()) 3643 } 3644 3645 payload := stack.PayloadSince(reply.NetworkHeader()) 3646 defer payload.Release() 3647 checker.IPv6(t, payload, 3648 checker.SrcAddr(incomingIPv6Addr.Address), 3649 checker.DstAddr(srcAddr), 3650 checker.TTL(DefaultTTL), 3651 checker.ICMPv6( 3652 checker.ICMPv6Type(test.expectedICMPError.icmpType), 3653 checker.ICMPv6Code(test.expectedICMPError.icmpCode), 3654 checker.ICMPv6Payload(hdr.View()[:expectedICMPPayloadLength()]), 3655 ), 3656 ) 3657 reply.DecRef() 3658 3659 if n := outgoingEndpoint.Drain(); n != 0 { 3660 t.Fatalf("e2.Drain() = %d, want = 0", n) 3661 } 3662 } else if reply != nil { 3663 t.Fatalf("Expected no ICMP packet through incoming NIC, instead found: %#v", reply) 3664 } 3665 3666 reply = outgoingEndpoint.Read() 3667 if test.expectPacketForwarded { 3668 if reply == nil { 3669 t.Fatal("Expected ICMP Echo Request packet through outgoing NIC") 3670 } 3671 3672 payload := stack.PayloadSince(reply.NetworkHeader()) 3673 defer payload.Release() 3674 checker.IPv6WithExtHdr(t, payload, 3675 checker.SrcAddr(srcAddr), 3676 checker.DstAddr(dstAddr), 3677 checker.TTL(packetTTL-1), 3678 extHdrChecker, 3679 checker.ICMPv6( 3680 checker.ICMPv6Type(header.ICMPv6EchoRequest), 3681 checker.ICMPv6Code(header.ICMPv6UnusedCode), 3682 checker.ICMPv6Payload(nil), 3683 ), 3684 ) 3685 reply.DecRef() 3686 3687 if n := incomingEndpoint.Drain(); n != 0 { 3688 t.Fatalf("e1.Drain() = %d, want = 0", n) 3689 } 3690 } else if reply != nil { 3691 t.Fatalf("Expected no ICMP Echo packet through outgoing NIC, instead found: %#v", reply) 3692 } 3693 3694 if got, want := s.Stats().IP.Forwarding.ExtensionHeaderProblem.Value(), test.expectedExtensionHeaderErrors; got != want { 3695 t.Errorf("s.Stats().IP.Forwarding.ExtensionHeaderProblem.Value() = %d, want = %d", got, want) 3696 } 3697 3698 if got, want := s.Stats().IP.Forwarding.PacketTooBig.Value(), test.expectedPacketTooBigErrors; got != want { 3699 t.Errorf("s.Stats().IP.Forwarding.PacketTooBig.Value() = %d, want = %d", got, want) 3700 } 3701 3702 totalExpectedErrors := test.expectedPacketTooBigErrors + test.expectedExtensionHeaderErrors 3703 if got, want := s.Stats().IP.Forwarding.Errors.Value(), totalExpectedErrors; got != want { 3704 t.Errorf("s.Stats().IP.Forwarding.Errors.Value() = %d, want = %d", got, want) 3705 } 3706 }) 3707 } 3708 } 3709 3710 func TestMultiCounterStatsInitialization(t *testing.T) { 3711 c := newTestContext() 3712 defer c.cleanup() 3713 s := c.s 3714 3715 proto := s.NetworkProtocolInstance(ProtocolNumber).(*protocol) 3716 var nic testInterface 3717 ep := proto.NewEndpoint(&nic, nil).(*endpoint) 3718 // At this point, the Stack's stats and the NetworkEndpoint's stats are 3719 // supposed to be bound. 3720 refStack := s.Stats() 3721 refEP := ep.stats.localStats 3722 if err := testutil.ValidateMultiCounterStats(reflect.ValueOf(&ep.stats.ip).Elem(), []reflect.Value{reflect.ValueOf(&refStack.IP).Elem(), reflect.ValueOf(&refEP.IP).Elem()}, testutil.ValidateMultiCounterStatsOptions{ 3723 ExpectMultiCounterStat: true, 3724 ExpectMultiIntegralStatCounterMap: false, 3725 }); err != nil { 3726 t.Error(err) 3727 } 3728 if err := testutil.ValidateMultiCounterStats(reflect.ValueOf(&ep.stats.icmp).Elem(), []reflect.Value{reflect.ValueOf(&refStack.ICMP.V6).Elem(), reflect.ValueOf(&refEP.ICMP).Elem()}, testutil.ValidateMultiCounterStatsOptions{ 3729 ExpectMultiCounterStat: true, 3730 ExpectMultiIntegralStatCounterMap: false, 3731 }); err != nil { 3732 t.Error(err) 3733 } 3734 } 3735 3736 func TestIcmpRateLimit(t *testing.T) { 3737 var ( 3738 host1IPv6Addr = tcpip.ProtocolAddress{ 3739 Protocol: ProtocolNumber, 3740 AddressWithPrefix: tcpip.AddressWithPrefix{ 3741 Address: tcpip.AddrFromSlice(net.ParseIP("10::1").To16()), 3742 PrefixLen: 64, 3743 }, 3744 } 3745 host2IPv6Addr = tcpip.ProtocolAddress{ 3746 Protocol: ProtocolNumber, 3747 AddressWithPrefix: tcpip.AddressWithPrefix{ 3748 Address: tcpip.AddrFromSlice(net.ParseIP("10::2").To16()), 3749 PrefixLen: 64, 3750 }, 3751 } 3752 ) 3753 const icmpBurst = 5 3754 3755 c := newTestContext() 3756 defer c.cleanup() 3757 s := c.s 3758 3759 s.SetICMPBurst(icmpBurst) 3760 3761 e := channel.New(1, defaultMTU, tcpip.LinkAddress("")) 3762 defer e.Close() 3763 if err := s.CreateNIC(nicID, e); err != nil { 3764 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 3765 } 3766 if err := s.AddProtocolAddress(nicID, host1IPv6Addr, stack.AddressProperties{}); err != nil { 3767 t.Fatalf("s.AddProtocolAddress(%d, %+v, {}): %s", nicID, host1IPv6Addr, err) 3768 } 3769 s.SetRouteTable([]tcpip.Route{ 3770 { 3771 Destination: host1IPv6Addr.AddressWithPrefix.Subnet(), 3772 NIC: nicID, 3773 }, 3774 }) 3775 tests := []struct { 3776 name string 3777 createPacket func() []byte 3778 check func(*testing.T, *channel.Endpoint, int) 3779 }{ 3780 { 3781 name: "echo", 3782 createPacket: func() []byte { 3783 totalLength := header.IPv6MinimumSize + header.ICMPv6MinimumSize 3784 hdr := prependable.New(totalLength) 3785 icmpH := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize)) 3786 icmpH.SetIdent(1) 3787 icmpH.SetSequence(1) 3788 icmpH.SetType(header.ICMPv6EchoRequest) 3789 icmpH.SetCode(header.ICMPv6UnusedCode) 3790 icmpH.SetChecksum(0) 3791 icmpH.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 3792 Header: icmpH, 3793 Src: host2IPv6Addr.AddressWithPrefix.Address, 3794 Dst: host1IPv6Addr.AddressWithPrefix.Address, 3795 })) 3796 payloadLength := hdr.UsedLength() 3797 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 3798 ip.Encode(&header.IPv6Fields{ 3799 PayloadLength: uint16(payloadLength), 3800 TransportProtocol: header.ICMPv6ProtocolNumber, 3801 HopLimit: 1, 3802 SrcAddr: host2IPv6Addr.AddressWithPrefix.Address, 3803 DstAddr: host1IPv6Addr.AddressWithPrefix.Address, 3804 }) 3805 return hdr.View() 3806 }, 3807 check: func(t *testing.T, e *channel.Endpoint, round int) { 3808 p := e.Read() 3809 if p == nil { 3810 t.Fatalf("expected echo response, no packet read in endpoint in round %d", round) 3811 } 3812 defer p.DecRef() 3813 if got, want := p.NetworkProtocolNumber, header.IPv6ProtocolNumber; got != want { 3814 t.Errorf("got p.NetworkProtocolNumber = %d, want = %d", got, want) 3815 } 3816 payload := stack.PayloadSince(p.NetworkHeader()) 3817 defer payload.Release() 3818 checker.IPv6(t, payload, 3819 checker.SrcAddr(host1IPv6Addr.AddressWithPrefix.Address), 3820 checker.DstAddr(host2IPv6Addr.AddressWithPrefix.Address), 3821 checker.ICMPv6( 3822 checker.ICMPv6Type(header.ICMPv6EchoReply), 3823 )) 3824 }, 3825 }, 3826 { 3827 name: "dst unreachable", 3828 createPacket: func() []byte { 3829 totalLength := header.IPv6MinimumSize + header.UDPMinimumSize 3830 hdr := prependable.New(totalLength) 3831 udpH := header.UDP(hdr.Prepend(header.UDPMinimumSize)) 3832 udpH.Encode(&header.UDPFields{ 3833 SrcPort: 100, 3834 DstPort: 101, 3835 Length: header.UDPMinimumSize, 3836 }) 3837 3838 // Calculate the UDP checksum and set it. 3839 sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, header.UDPMinimumSize) 3840 sum = checksum.Checksum(nil, sum) 3841 udpH.SetChecksum(^udpH.CalculateChecksum(sum)) 3842 3843 payloadLength := hdr.UsedLength() 3844 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 3845 ip.Encode(&header.IPv6Fields{ 3846 PayloadLength: uint16(payloadLength), 3847 TransportProtocol: header.UDPProtocolNumber, 3848 HopLimit: 1, 3849 SrcAddr: host2IPv6Addr.AddressWithPrefix.Address, 3850 DstAddr: host1IPv6Addr.AddressWithPrefix.Address, 3851 }) 3852 return hdr.View() 3853 }, 3854 check: func(t *testing.T, e *channel.Endpoint, round int) { 3855 p := e.Read() 3856 if round >= icmpBurst { 3857 if p != nil { 3858 t.Errorf("got packet %x in round %d, expected ICMP rate limit to stop it", p.Data().AsRange().ToSlice(), round) 3859 p.DecRef() 3860 } 3861 return 3862 } 3863 if p == nil { 3864 t.Fatalf("expected unreachable in round %d, no packet read in endpoint", round) 3865 } 3866 payload := stack.PayloadSince(p.NetworkHeader()) 3867 defer payload.Release() 3868 checker.IPv6(t, payload, 3869 checker.SrcAddr(host1IPv6Addr.AddressWithPrefix.Address), 3870 checker.DstAddr(host2IPv6Addr.AddressWithPrefix.Address), 3871 checker.ICMPv6( 3872 checker.ICMPv6Type(header.ICMPv6DstUnreachable), 3873 )) 3874 p.DecRef() 3875 }, 3876 }, 3877 } 3878 for _, testCase := range tests { 3879 t.Run(testCase.name, func(t *testing.T) { 3880 for round := 0; round < icmpBurst+1; round++ { 3881 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 3882 Payload: buffer.MakeWithData(testCase.createPacket()), 3883 }) 3884 e.InjectInbound(header.IPv6ProtocolNumber, pkt) 3885 pkt.DecRef() 3886 testCase.check(t, e, round) 3887 } 3888 }) 3889 } 3890 } 3891 3892 // TestRejectMartianMappedPackets tests that IPv6 endpoints reject packets 3893 // containing IPv4-mapped IPv6 addresses. 3894 func TestRejectMartianMappedPackets(t *testing.T) { 3895 tcs := []struct { 3896 name string 3897 wantSrcReceived uint64 3898 wantDstReceived uint64 3899 wantDelivered uint64 3900 srcAddr tcpip.Address 3901 dstAddr tcpip.Address 3902 }{ 3903 { 3904 name: "bad source", 3905 wantSrcReceived: 1, 3906 srcAddr: testutil.MustParse6("::ffff:1.2.3.4"), 3907 dstAddr: testutil.MustParse6("fe80::2"), 3908 }, 3909 { 3910 name: "bad destination", 3911 wantDstReceived: 1, 3912 srcAddr: testutil.MustParse6("fe80::2"), 3913 dstAddr: testutil.MustParse6("::ffff:1.2.3.4"), 3914 }, 3915 { 3916 name: "bad source and destination", 3917 wantSrcReceived: 1, 3918 wantDstReceived: 1, 3919 srcAddr: testutil.MustParse6("::ffff:1.2.3.4"), 3920 dstAddr: testutil.MustParse6("::ffff:5.6.7.8"), 3921 }, 3922 { 3923 name: "valid source and destination", 3924 wantDelivered: 1, 3925 srcAddr: testutil.MustParse6("fe80::2"), 3926 dstAddr: header.IPv6AllNodesMulticastAddress, 3927 }, 3928 } 3929 3930 for _, tc := range tcs { 3931 t.Run(tc.name, func(t *testing.T) { 3932 // Initialize the stack and add an address. 3933 ctx := newTestContext() 3934 defer ctx.cleanup() 3935 stk := ctx.s 3936 3937 channelEP := channel.New(1, header.IPv6MinimumMTU, linkAddr1) 3938 defer channelEP.Close() 3939 if err := stk.CreateNIC(nicID, channelEP); err != nil { 3940 t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) 3941 } 3942 3943 stk.SetRouteTable([]tcpip.Route{ 3944 { 3945 Destination: header.IPv6EmptySubnet, 3946 NIC: nicID, 3947 }, 3948 }) 3949 3950 protocolAddr := tcpip.ProtocolAddress{ 3951 Protocol: ProtocolNumber, 3952 AddressWithPrefix: addr2.WithPrefix(), 3953 } 3954 if err := stk.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil { 3955 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err) 3956 } 3957 3958 // We don't have to setup the UDP header properly, as 3959 // it should be rejected at the IP layer. 3960 hdr := prependable.New(header.IPv6MinimumSize + header.UDPMinimumSize) 3961 _ = header.UDP(hdr.Prepend(header.UDPMinimumSize)) 3962 3963 payloadLength := hdr.UsedLength() 3964 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 3965 ip.Encode(&header.IPv6Fields{ 3966 PayloadLength: uint16(payloadLength), 3967 TransportProtocol: udp.ProtocolNumber, 3968 HopLimit: 255, 3969 SrcAddr: tc.srcAddr, 3970 DstAddr: tc.dstAddr, 3971 }) 3972 3973 // Send the packet out. 3974 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 3975 Payload: buffer.MakeWithData(hdr.View()), 3976 }) 3977 channelEP.InjectInbound(ProtocolNumber, pkt) 3978 pkt.DecRef() 3979 3980 // Verify that stat counters are appropriately updated. 3981 srcStat := stk.Stats().IP.InvalidSourceAddressesReceived 3982 if got := srcStat.Value(); got != tc.wantSrcReceived { 3983 t.Errorf("got InvalidSourceAddressesReceived = %d, want = %d", got, tc.wantSrcReceived) 3984 } 3985 dstStat := stk.Stats().IP.InvalidDestinationAddressesReceived 3986 if got := dstStat.Value(); got != tc.wantDstReceived { 3987 t.Errorf("got InvalidDestinationAddressesReceived = %d, want = %d", got, tc.wantDstReceived) 3988 } 3989 deliveredStat := stk.Stats().IP.PacketsDelivered 3990 if got := deliveredStat.Value(); got != tc.wantDelivered { 3991 t.Errorf("got PacketsDelivered = %d, want = %d", got, tc.wantDelivered) 3992 } 3993 }) 3994 } 3995 }