golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/ipv6/unicast_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ipv6_test 6 7 import ( 8 "bytes" 9 "errors" 10 "net" 11 "os" 12 "runtime" 13 "testing" 14 "time" 15 16 "golang.org/x/net/icmp" 17 "golang.org/x/net/internal/iana" 18 "golang.org/x/net/ipv6" 19 "golang.org/x/net/nettest" 20 ) 21 22 func TestPacketConnReadWriteUnicastUDP(t *testing.T) { 23 switch runtime.GOOS { 24 case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": 25 t.Skipf("not supported on %s", runtime.GOOS) 26 } 27 if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil { 28 t.Skip("ipv6 is not enabled for loopback interface") 29 } 30 31 c, err := nettest.NewLocalPacketListener("udp6") 32 if err != nil { 33 t.Fatal(err) 34 } 35 defer c.Close() 36 p := ipv6.NewPacketConn(c) 37 defer p.Close() 38 39 dst := c.LocalAddr() 40 cm := ipv6.ControlMessage{ 41 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, 42 Src: net.IPv6loopback, 43 } 44 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 45 ifi, _ := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) 46 if ifi != nil { 47 cm.IfIndex = ifi.Index 48 } 49 wb := []byte("HELLO-R-U-THERE") 50 51 for i, toggle := range []bool{true, false, true} { 52 if err := p.SetControlMessage(cf, toggle); err != nil { 53 if protocolNotSupported(err) { 54 t.Logf("not supported on %s", runtime.GOOS) 55 continue 56 } 57 t.Fatal(err) 58 } 59 cm.HopLimit = i + 1 60 61 backoff := time.Millisecond 62 for { 63 n, err := p.WriteTo(wb, &cm, dst) 64 if err != nil { 65 if n == 0 && isENOBUFS(err) { 66 time.Sleep(backoff) 67 backoff *= 2 68 continue 69 } 70 t.Fatal(err) 71 } 72 if n != len(wb) { 73 t.Fatalf("got %d; want %d", n, len(wb)) 74 } 75 break 76 } 77 78 rb := make([]byte, 128) 79 if n, _, _, err := p.ReadFrom(rb); err != nil { 80 t.Fatal(err) 81 } else if !bytes.Equal(rb[:n], wb) { 82 t.Fatalf("got %v; want %v", rb[:n], wb) 83 } 84 } 85 } 86 87 func TestPacketConnReadWriteUnicastICMP(t *testing.T) { 88 if !nettest.SupportsIPv6() { 89 t.Skip("ipv6 is not supported") 90 } 91 if !nettest.SupportsRawSocket() { 92 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 93 } 94 95 c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") 96 if err != nil { 97 t.Fatal(err) 98 } 99 defer c.Close() 100 p := ipv6.NewPacketConn(c) 101 defer p.Close() 102 103 dst, err := net.ResolveIPAddr("ip6", "::1") 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP) 109 cm := ipv6.ControlMessage{ 110 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, 111 Src: net.IPv6loopback, 112 } 113 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 114 ifi, _ := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) 115 if ifi != nil { 116 cm.IfIndex = ifi.Index 117 } 118 119 var f ipv6.ICMPFilter 120 f.SetAll(true) 121 f.Accept(ipv6.ICMPTypeEchoReply) 122 if err := p.SetICMPFilter(&f); errors.Is(err, ipv6.ErrNotImplemented) { 123 t.Skipf("setting ICMP filter not supported: %v", err) 124 } else if err != nil { 125 t.Fatal(err) 126 } 127 128 var psh []byte 129 for i, toggle := range []bool{true, false, true} { 130 if toggle { 131 psh = nil 132 if err := p.SetChecksum(true, 2); err != nil { 133 // AIX, Illumos and Solaris never allow 134 // modification of ICMP properties. 135 switch runtime.GOOS { 136 case "aix", "illumos", "solaris": 137 default: 138 t.Fatal(err) 139 } 140 } 141 } else { 142 psh = pshicmp 143 // Some platforms never allow to disable the 144 // kernel checksum processing. 145 p.SetChecksum(false, -1) 146 } 147 wb, err := (&icmp.Message{ 148 Type: ipv6.ICMPTypeEchoRequest, Code: 0, 149 Body: &icmp.Echo{ 150 ID: os.Getpid() & 0xffff, Seq: i + 1, 151 Data: []byte("HELLO-R-U-THERE"), 152 }, 153 }).Marshal(psh) 154 if err != nil { 155 t.Fatal(err) 156 } 157 if err := p.SetControlMessage(cf, toggle); err != nil { 158 if protocolNotSupported(err) { 159 t.Logf("not supported on %s", runtime.GOOS) 160 continue 161 } 162 t.Fatal(err) 163 } 164 cm.HopLimit = i + 1 165 166 backoff := time.Millisecond 167 for { 168 n, err := p.WriteTo(wb, &cm, dst) 169 if err != nil { 170 if n == 0 && isENOBUFS(err) { 171 time.Sleep(backoff) 172 backoff *= 2 173 continue 174 } 175 t.Fatal(err) 176 } 177 if n != len(wb) { 178 t.Fatalf("got %d; want %d", n, len(wb)) 179 } 180 break 181 } 182 183 rb := make([]byte, 128) 184 if n, _, _, err := p.ReadFrom(rb); err != nil { 185 t.Fatal(err) 186 } else { 187 if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { 188 t.Fatal(err) 189 } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { 190 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) 191 } 192 } 193 } 194 }