gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/packetimpact/tests/ipv6_unknown_options_action_test.go (about) 1 // Copyright 2020 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_unknown_options_action_test 16 17 import ( 18 "flag" 19 "net" 20 "testing" 21 "time" 22 23 "gvisor.dev/gvisor/pkg/tcpip/header" 24 "gvisor.dev/gvisor/test/packetimpact/testbench" 25 ) 26 27 func init() { 28 testbench.Initialize(flag.CommandLine) 29 } 30 31 func mkHopByHopOptionsExtHdr(optType byte) testbench.Layer { 32 return &testbench.IPv6HopByHopOptionsExtHdr{ 33 Options: []byte{optType, 0x04, 0x00, 0x00, 0x00, 0x00}, 34 } 35 } 36 37 func mkDestinationOptionsExtHdr(optType byte) testbench.Layer { 38 return &testbench.IPv6DestinationOptionsExtHdr{ 39 Options: []byte{optType, 0x04, 0x00, 0x00, 0x00, 0x00}, 40 } 41 } 42 43 func optionTypeFromAction(action header.IPv6OptionUnknownAction) byte { 44 return byte(action << 6) 45 } 46 47 func TestIPv6UnknownOptionAction(t *testing.T) { 48 for _, tt := range []struct { 49 description string 50 mkExtHdr func(optType byte) testbench.Layer 51 action header.IPv6OptionUnknownAction 52 multicastDst bool 53 wantICMPv6 bool 54 }{ 55 { 56 description: "0b00/hbh", 57 mkExtHdr: mkHopByHopOptionsExtHdr, 58 action: header.IPv6OptionUnknownActionSkip, 59 multicastDst: false, 60 wantICMPv6: false, 61 }, 62 { 63 description: "0b01/hbh", 64 mkExtHdr: mkHopByHopOptionsExtHdr, 65 action: header.IPv6OptionUnknownActionDiscard, 66 multicastDst: false, 67 wantICMPv6: false, 68 }, 69 { 70 description: "0b10/hbh/unicast", 71 mkExtHdr: mkHopByHopOptionsExtHdr, 72 action: header.IPv6OptionUnknownActionDiscardSendICMP, 73 multicastDst: false, 74 wantICMPv6: true, 75 }, 76 { 77 description: "0b10/hbh/multicast", 78 mkExtHdr: mkHopByHopOptionsExtHdr, 79 action: header.IPv6OptionUnknownActionDiscardSendICMP, 80 multicastDst: true, 81 wantICMPv6: true, 82 }, 83 { 84 description: "0b11/hbh/unicast", 85 mkExtHdr: mkHopByHopOptionsExtHdr, 86 action: header.IPv6OptionUnknownActionDiscardSendICMPNoMulticastDest, 87 multicastDst: false, 88 wantICMPv6: true, 89 }, 90 { 91 description: "0b11/hbh/multicast", 92 mkExtHdr: mkHopByHopOptionsExtHdr, 93 action: header.IPv6OptionUnknownActionDiscardSendICMPNoMulticastDest, 94 multicastDst: true, 95 wantICMPv6: false, 96 }, 97 { 98 description: "0b00/destination", 99 mkExtHdr: mkDestinationOptionsExtHdr, 100 action: header.IPv6OptionUnknownActionSkip, 101 multicastDst: false, 102 wantICMPv6: false, 103 }, 104 { 105 description: "0b01/destination", 106 mkExtHdr: mkDestinationOptionsExtHdr, 107 action: header.IPv6OptionUnknownActionDiscard, 108 multicastDst: false, 109 wantICMPv6: false, 110 }, 111 { 112 description: "0b10/destination/unicast", 113 mkExtHdr: mkDestinationOptionsExtHdr, 114 action: header.IPv6OptionUnknownActionDiscardSendICMP, 115 multicastDst: false, 116 wantICMPv6: true, 117 }, 118 { 119 description: "0b10/destination/multicast", 120 mkExtHdr: mkDestinationOptionsExtHdr, 121 action: header.IPv6OptionUnknownActionDiscardSendICMP, 122 multicastDst: true, 123 wantICMPv6: true, 124 }, 125 { 126 description: "0b11/destination/unicast", 127 mkExtHdr: mkDestinationOptionsExtHdr, 128 action: header.IPv6OptionUnknownActionDiscardSendICMPNoMulticastDest, 129 multicastDst: false, 130 wantICMPv6: true, 131 }, 132 { 133 description: "0b11/destination/multicast", 134 mkExtHdr: mkDestinationOptionsExtHdr, 135 action: header.IPv6OptionUnknownActionDiscardSendICMPNoMulticastDest, 136 multicastDst: true, 137 wantICMPv6: false, 138 }, 139 } { 140 t.Run(tt.description, func(t *testing.T) { 141 dut := testbench.NewDUT(t) 142 conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{}) 143 defer conn.Close(t) 144 145 outgoingOverride := testbench.Layers{} 146 if tt.multicastDst { 147 ip := net.ParseIP("ff02::1") 148 outgoingOverride = testbench.Layers{&testbench.IPv6{ 149 DstAddr: &ip, 150 }} 151 } 152 153 outgoing := conn.CreateFrame(t, outgoingOverride, tt.mkExtHdr(optionTypeFromAction(tt.action))) 154 conn.SendFrame(t, outgoing) 155 ipv6Sent := outgoing[1:] 156 icmpv6Payload, err := ipv6Sent.ToBytes() 157 if err != nil { 158 t.Fatalf("failed to serialize the outgoing packet: %s", err) 159 } 160 gotICMPv6, err := conn.ExpectFrame(t, testbench.Layers{ 161 &testbench.Ether{}, 162 &testbench.IPv6{}, 163 &testbench.ICMPv6{ 164 Type: testbench.ICMPv6Type(header.ICMPv6ParamProblem), 165 Code: testbench.ICMPv6Code(header.ICMPv6UnknownOption), 166 // The pointer in the ICMPv6 parameter problem message 167 // should point to the option type of the unknown option. In 168 // our test case, it is the first option in the extension 169 // header whose option type is 2 bytes after the IPv6 header 170 // (after NextHeader and ExtHdrLen). 171 Pointer: testbench.Uint32(header.IPv6MinimumSize + 2), 172 Payload: icmpv6Payload, 173 }, 174 }, time.Second) 175 if tt.wantICMPv6 && err != nil { 176 t.Fatalf("expected ICMPv6 Parameter Problem but got none: %s", err) 177 } 178 if !tt.wantICMPv6 && gotICMPv6 != nil { 179 t.Fatalf("expected no ICMPv6 Parameter Problem but got one: %s", gotICMPv6) 180 } 181 }) 182 } 183 }