1// Copyright 2012 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 5package net 6 7import ( 8 "errors" 9 "fmt" 10 "internal/testenv" 11 "net/netip" 12 "os" 13 "reflect" 14 "runtime" 15 "testing" 16 "time" 17) 18 19func BenchmarkUDP6LinkLocalUnicast(b *testing.B) { 20 testHookUninstaller.Do(uninstallTestHooks) 21 22 if !supportsIPv6() { 23 b.Skip("IPv6 is not supported") 24 } 25 ifi := loopbackInterface() 26 if ifi == nil { 27 b.Skip("loopback interface not found") 28 } 29 lla := ipv6LinkLocalUnicastAddr(ifi) 30 if lla == "" { 31 b.Skip("IPv6 link-local unicast address not found") 32 } 33 34 c1, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0")) 35 if err != nil { 36 b.Fatal(err) 37 } 38 defer c1.Close() 39 c2, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0")) 40 if err != nil { 41 b.Fatal(err) 42 } 43 defer c2.Close() 44 45 var buf [1]byte 46 for i := 0; i < b.N; i++ { 47 if _, err := c1.WriteTo(buf[:], c2.LocalAddr()); err != nil { 48 b.Fatal(err) 49 } 50 if _, _, err := c2.ReadFrom(buf[:]); err != nil { 51 b.Fatal(err) 52 } 53 } 54} 55 56type resolveUDPAddrTest struct { 57 network string 58 litAddrOrName string 59 addr *UDPAddr 60 err error 61} 62 63var resolveUDPAddrTests = []resolveUDPAddrTest{ 64 {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, 65 {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil}, 66 67 {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, 68 {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil}, 69 70 {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil}, 71 {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil}, 72 73 {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior 74 {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior 75 76 {"udp", ":12345", &UDPAddr{Port: 12345}, nil}, 77 78 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, 79 80 {"udp", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 81 {"udp", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 53}, nil}, 82 {"udp", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil}, 83 {"udp4", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 84 {"udp4", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil}, 85 {"udp6", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil}, 86 87 {"udp4", "[2001:db8::1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}}, 88 {"udp6", "127.0.0.1:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}}, 89 {"udp6", "[::ffff:127.0.0.1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}}, 90} 91 92func TestResolveUDPAddr(t *testing.T) { 93 origTestHookLookupIP := testHookLookupIP 94 defer func() { testHookLookupIP = origTestHookLookupIP }() 95 testHookLookupIP = lookupLocalhost 96 97 for _, tt := range resolveUDPAddrTests { 98 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName) 99 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) { 100 t.Errorf("ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err) 101 continue 102 } 103 if err == nil { 104 addr2, err := ResolveUDPAddr(addr.Network(), addr.String()) 105 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err { 106 t.Errorf("(%q, %q): ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err) 107 } 108 } 109 } 110} 111 112func TestWriteToUDP(t *testing.T) { 113 switch runtime.GOOS { 114 case "plan9": 115 t.Skipf("not supported on %s", runtime.GOOS) 116 } 117 118 if !testableNetwork("udp") { 119 t.Skipf("skipping: udp not supported") 120 } 121 122 c, err := ListenPacket("udp", "127.0.0.1:0") 123 if err != nil { 124 t.Fatal(err) 125 } 126 defer c.Close() 127 128 testWriteToConn(t, c.LocalAddr().String()) 129 testWriteToPacketConn(t, c.LocalAddr().String()) 130} 131 132func testWriteToConn(t *testing.T, raddr string) { 133 c, err := Dial("udp", raddr) 134 if err != nil { 135 t.Fatal(err) 136 } 137 defer c.Close() 138 139 ra, err := ResolveUDPAddr("udp", raddr) 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 b := []byte("CONNECTED-MODE SOCKET") 145 _, err = c.(*UDPConn).WriteToUDP(b, ra) 146 if err == nil { 147 t.Fatal("should fail") 148 } 149 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 150 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 151 } 152 _, err = c.(*UDPConn).WriteTo(b, ra) 153 if err == nil { 154 t.Fatal("should fail") 155 } 156 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 157 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 158 } 159 _, err = c.Write(b) 160 if err != nil { 161 t.Fatal(err) 162 } 163 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 164 if err == nil { 165 t.Fatal("should fail") 166 } 167 if err != nil && err.(*OpError).Err != ErrWriteToConnected { 168 t.Fatalf("should fail as ErrWriteToConnected: %v", err) 169 } 170 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 171 if err != nil { 172 t.Fatal(err) 173 } 174} 175 176func testWriteToPacketConn(t *testing.T, raddr string) { 177 c, err := ListenPacket("udp", "127.0.0.1:0") 178 if err != nil { 179 t.Fatal(err) 180 } 181 defer c.Close() 182 183 ra, err := ResolveUDPAddr("udp", raddr) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 b := []byte("UNCONNECTED-MODE SOCKET") 189 _, err = c.(*UDPConn).WriteToUDP(b, ra) 190 if err != nil { 191 t.Fatal(err) 192 } 193 _, err = c.WriteTo(b, ra) 194 if err != nil { 195 t.Fatal(err) 196 } 197 _, err = c.(*UDPConn).Write(b) 198 if err == nil { 199 t.Fatal("should fail") 200 } 201 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil) 202 if err == nil { 203 t.Fatal("should fail") 204 } 205 if err != nil && err.(*OpError).Err != errMissingAddress { 206 t.Fatalf("should fail as errMissingAddress: %v", err) 207 } 208 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra) 209 if err != nil { 210 t.Fatal(err) 211 } 212} 213 214var udpConnLocalNameTests = []struct { 215 net string 216 laddr *UDPAddr 217}{ 218 {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}}, 219 {"udp4", &UDPAddr{}}, 220 {"udp4", nil}, 221} 222 223func TestUDPConnLocalName(t *testing.T) { 224 testenv.MustHaveExternalNetwork(t) 225 226 for _, tt := range udpConnLocalNameTests { 227 t.Run(fmt.Sprint(tt.laddr), func(t *testing.T) { 228 if !testableNetwork(tt.net) { 229 t.Skipf("skipping: %s not available", tt.net) 230 } 231 232 c, err := ListenUDP(tt.net, tt.laddr) 233 if err != nil { 234 t.Fatal(err) 235 } 236 defer c.Close() 237 la := c.LocalAddr() 238 if a, ok := la.(*UDPAddr); !ok || a.Port == 0 { 239 t.Fatalf("got %v; expected a proper address with non-zero port number", la) 240 } 241 }) 242 } 243} 244 245func TestUDPConnLocalAndRemoteNames(t *testing.T) { 246 if !testableNetwork("udp") { 247 t.Skipf("skipping: udp not available") 248 } 249 250 for _, laddr := range []string{"", "127.0.0.1:0"} { 251 c1, err := ListenPacket("udp", "127.0.0.1:0") 252 if err != nil { 253 t.Fatal(err) 254 } 255 defer c1.Close() 256 257 var la *UDPAddr 258 if laddr != "" { 259 var err error 260 if la, err = ResolveUDPAddr("udp", laddr); err != nil { 261 t.Fatal(err) 262 } 263 } 264 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr)) 265 if err != nil { 266 t.Fatal(err) 267 } 268 defer c2.Close() 269 270 var connAddrs = [4]struct { 271 got Addr 272 ok bool 273 }{ 274 {c1.LocalAddr(), true}, 275 {c1.(*UDPConn).RemoteAddr(), false}, 276 {c2.LocalAddr(), true}, 277 {c2.RemoteAddr(), true}, 278 } 279 for _, ca := range connAddrs { 280 if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 { 281 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got) 282 } 283 } 284 } 285} 286 287func TestIPv6LinkLocalUnicastUDP(t *testing.T) { 288 testenv.MustHaveExternalNetwork(t) 289 290 if !supportsIPv6() { 291 t.Skip("IPv6 is not supported") 292 } 293 294 for i, tt := range ipv6LinkLocalUnicastUDPTests { 295 c1, err := ListenPacket(tt.network, tt.address) 296 if err != nil { 297 // It might return "LookupHost returned no 298 // suitable address" error on some platforms. 299 t.Log(err) 300 continue 301 } 302 ls := (&packetListener{PacketConn: c1}).newLocalServer() 303 defer ls.teardown() 304 ch := make(chan error, 1) 305 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) } 306 if err := ls.buildup(handler); err != nil { 307 t.Fatal(err) 308 } 309 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 310 t.Fatalf("got %v; expected a proper address with zone identifier", la) 311 } 312 313 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String()) 314 if err != nil { 315 t.Fatal(err) 316 } 317 defer c2.Close() 318 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" { 319 t.Fatalf("got %v; expected a proper address with zone identifier", la) 320 } 321 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" { 322 t.Fatalf("got %v; expected a proper address with zone identifier", ra) 323 } 324 325 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil { 326 t.Fatal(err) 327 } 328 b := make([]byte, 32) 329 if _, err := c2.Read(b); err != nil { 330 t.Fatal(err) 331 } 332 333 for err := range ch { 334 t.Errorf("#%d: %v", i, err) 335 } 336 } 337} 338 339func TestUDPZeroBytePayload(t *testing.T) { 340 switch runtime.GOOS { 341 case "plan9": 342 t.Skipf("not supported on %s", runtime.GOOS) 343 case "darwin", "ios": 344 testenv.SkipFlaky(t, 29225) 345 } 346 if !testableNetwork("udp") { 347 t.Skipf("skipping: udp not available") 348 } 349 350 c := newLocalPacketListener(t, "udp") 351 defer c.Close() 352 353 for _, genericRead := range []bool{false, true} { 354 n, err := c.WriteTo(nil, c.LocalAddr()) 355 if err != nil { 356 t.Fatal(err) 357 } 358 if n != 0 { 359 t.Errorf("got %d; want 0", n) 360 } 361 c.SetReadDeadline(time.Now().Add(30 * time.Second)) 362 var b [1]byte 363 var name string 364 if genericRead { 365 _, err = c.(Conn).Read(b[:]) 366 name = "Read" 367 } else { 368 _, _, err = c.ReadFrom(b[:]) 369 name = "ReadFrom" 370 } 371 if err != nil { 372 t.Errorf("%s of zero byte packet failed: %v", name, err) 373 } 374 } 375} 376 377func TestUDPZeroByteBuffer(t *testing.T) { 378 switch runtime.GOOS { 379 case "plan9": 380 t.Skipf("not supported on %s", runtime.GOOS) 381 } 382 if !testableNetwork("udp") { 383 t.Skipf("skipping: udp not available") 384 } 385 386 c := newLocalPacketListener(t, "udp") 387 defer c.Close() 388 389 b := []byte("UDP ZERO BYTE BUFFER TEST") 390 for _, genericRead := range []bool{false, true} { 391 n, err := c.WriteTo(b, c.LocalAddr()) 392 if err != nil { 393 t.Fatal(err) 394 } 395 if n != len(b) { 396 t.Errorf("got %d; want %d", n, len(b)) 397 } 398 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 399 if genericRead { 400 _, err = c.(Conn).Read(nil) 401 } else { 402 _, _, err = c.ReadFrom(nil) 403 } 404 switch err { 405 case nil: // ReadFrom succeeds 406 default: // Read may timeout, it depends on the platform 407 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE 408 t.Fatal(err) 409 } 410 } 411 } 412} 413 414func TestUDPReadSizeError(t *testing.T) { 415 switch runtime.GOOS { 416 case "plan9": 417 t.Skipf("not supported on %s", runtime.GOOS) 418 } 419 if !testableNetwork("udp") { 420 t.Skipf("skipping: udp not available") 421 } 422 423 c1 := newLocalPacketListener(t, "udp") 424 defer c1.Close() 425 426 c2, err := Dial("udp", c1.LocalAddr().String()) 427 if err != nil { 428 t.Fatal(err) 429 } 430 defer c2.Close() 431 432 b1 := []byte("READ SIZE ERROR TEST") 433 for _, genericRead := range []bool{false, true} { 434 n, err := c2.Write(b1) 435 if err != nil { 436 t.Fatal(err) 437 } 438 if n != len(b1) { 439 t.Errorf("got %d; want %d", n, len(b1)) 440 } 441 b2 := make([]byte, len(b1)-1) 442 if genericRead { 443 n, err = c1.(Conn).Read(b2) 444 } else { 445 n, _, err = c1.ReadFrom(b2) 446 } 447 if err != nil && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE 448 t.Fatal(err) 449 } 450 if n != len(b1)-1 { 451 t.Fatalf("got %d; want %d", n, len(b1)-1) 452 } 453 } 454} 455 456// TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error 457// without data or an address. 458func TestUDPReadTimeout(t *testing.T) { 459 if !testableNetwork("udp4") { 460 t.Skipf("skipping: udp4 not available") 461 } 462 463 la, err := ResolveUDPAddr("udp4", "127.0.0.1:0") 464 if err != nil { 465 t.Fatal(err) 466 } 467 c, err := ListenUDP("udp4", la) 468 if err != nil { 469 t.Fatal(err) 470 } 471 defer c.Close() 472 473 c.SetDeadline(time.Now()) 474 b := make([]byte, 1) 475 n, addr, err := c.ReadFromUDP(b) 476 if !errors.Is(err, os.ErrDeadlineExceeded) { 477 t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err) 478 } 479 if n != 0 { 480 t.Errorf("ReadFromUDP got n %d want 0", n) 481 } 482 if addr != nil { 483 t.Errorf("ReadFromUDP got addr %+#v want nil", addr) 484 } 485} 486 487func TestAllocs(t *testing.T) { 488 switch runtime.GOOS { 489 case "plan9", "js", "wasip1": 490 // These implementations have not been optimized. 491 t.Skipf("skipping on %v", runtime.GOOS) 492 } 493 if !testableNetwork("udp4") { 494 t.Skipf("skipping: udp4 not available") 495 } 496 497 // Optimizations are required to remove the allocs. 498 testenv.SkipIfOptimizationOff(t) 499 500 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 501 if err != nil { 502 t.Fatal(err) 503 } 504 defer conn.Close() 505 addr := conn.LocalAddr() 506 addrPort := addr.(*UDPAddr).AddrPort() 507 buf := make([]byte, 8) 508 509 allocs := testing.AllocsPerRun(1000, func() { 510 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort) 511 if err != nil { 512 t.Fatal(err) 513 } 514 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) 515 if err != nil { 516 t.Fatal(err) 517 } 518 }) 519 if got := int(allocs); got != 0 { 520 t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got) 521 } 522 523 allocs = testing.AllocsPerRun(1000, func() { 524 _, err := conn.WriteToUDPAddrPort(buf, addrPort) 525 if err != nil { 526 t.Fatal(err) 527 } 528 _, _, err = conn.ReadFromUDPAddrPort(buf) 529 if err != nil { 530 t.Fatal(err) 531 } 532 }) 533 if got := int(allocs); got != 0 { 534 t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got) 535 } 536 537 allocs = testing.AllocsPerRun(1000, func() { 538 _, err := conn.WriteTo(buf, addr) 539 if err != nil { 540 t.Fatal(err) 541 } 542 _, _, err = conn.ReadFromUDP(buf) 543 if err != nil { 544 t.Fatal(err) 545 } 546 }) 547 if got := int(allocs); got != 1 { 548 t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got) 549 } 550} 551 552func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { 553 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 554 if err != nil { 555 b.Fatal(err) 556 } 557 defer conn.Close() 558 addr := conn.LocalAddr().(*UDPAddr).AddrPort() 559 buf := make([]byte, 8) 560 b.ResetTimer() 561 b.ReportAllocs() 562 for i := 0; i < b.N; i++ { 563 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr) 564 if err != nil { 565 b.Fatal(err) 566 } 567 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) 568 if err != nil { 569 b.Fatal(err) 570 } 571 } 572} 573 574func BenchmarkWriteToReadFromUDP(b *testing.B) { 575 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 576 if err != nil { 577 b.Fatal(err) 578 } 579 defer conn.Close() 580 addr := conn.LocalAddr() 581 buf := make([]byte, 8) 582 b.ResetTimer() 583 b.ReportAllocs() 584 for i := 0; i < b.N; i++ { 585 _, err := conn.WriteTo(buf, addr) 586 if err != nil { 587 b.Fatal(err) 588 } 589 _, _, err = conn.ReadFromUDP(buf) 590 if err != nil { 591 b.Fatal(err) 592 } 593 } 594} 595 596func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { 597 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 598 if err != nil { 599 b.Fatal(err) 600 } 601 defer conn.Close() 602 addr := conn.LocalAddr().(*UDPAddr).AddrPort() 603 buf := make([]byte, 8) 604 b.ResetTimer() 605 b.ReportAllocs() 606 for i := 0; i < b.N; i++ { 607 _, err := conn.WriteToUDPAddrPort(buf, addr) 608 if err != nil { 609 b.Fatal(err) 610 } 611 _, _, err = conn.ReadFromUDPAddrPort(buf) 612 if err != nil { 613 b.Fatal(err) 614 } 615 } 616} 617 618func TestUDPIPVersionReadMsg(t *testing.T) { 619 switch runtime.GOOS { 620 case "plan9": 621 t.Skipf("skipping on %v", runtime.GOOS) 622 } 623 if !testableNetwork("udp4") { 624 t.Skipf("skipping: udp4 not available") 625 } 626 627 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) 628 if err != nil { 629 t.Fatal(err) 630 } 631 defer conn.Close() 632 daddr := conn.LocalAddr().(*UDPAddr).AddrPort() 633 buf := make([]byte, 8) 634 _, err = conn.WriteToUDPAddrPort(buf, daddr) 635 if err != nil { 636 t.Fatal(err) 637 } 638 _, _, _, saddr, err := conn.ReadMsgUDPAddrPort(buf, nil) 639 if err != nil { 640 t.Fatal(err) 641 } 642 if !saddr.Addr().Is4() { 643 t.Error("returned AddrPort is not IPv4") 644 } 645 _, err = conn.WriteToUDPAddrPort(buf, daddr) 646 if err != nil { 647 t.Fatal(err) 648 } 649 _, _, _, soldaddr, err := conn.ReadMsgUDP(buf, nil) 650 if err != nil { 651 t.Fatal(err) 652 } 653 if len(soldaddr.IP) != 4 { 654 t.Error("returned UDPAddr is not IPv4") 655 } 656} 657 658// TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion verifies that 659// WriteMsgUDPAddrPort accepts IPv4, IPv4-mapped IPv6, and IPv6 target addresses 660// on a UDPConn listening on "::". 661func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { 662 if !testableNetwork("udp4") { 663 t.Skipf("skipping: udp4 not available") 664 } 665 if !testableNetwork("udp6") { 666 t.Skipf("skipping: udp6 not available") 667 } 668 669 switch runtime.GOOS { 670 case "dragonfly", "openbsd": 671 // DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page: 672 // https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY). 673 // OpenBSD's IPv6 sockets are always IPv6-only, according to the man page: 674 // https://man.openbsd.org/ip6#IPV6_V6ONLY 675 t.Skipf("skipping on %v", runtime.GOOS) 676 } 677 678 conn, err := ListenUDP("udp", nil) 679 if err != nil { 680 t.Fatal(err) 681 } 682 defer conn.Close() 683 684 daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345) 685 daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345) 686 daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345) 687 buf := make([]byte, 8) 688 689 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4) 690 if err != nil { 691 t.Fatal(err) 692 } 693 694 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) 695 if err != nil { 696 t.Fatal(err) 697 } 698 699 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6) 700 if err != nil { 701 t.Fatal(err) 702 } 703} 704