func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } c, err := net.ListenPacket("udp6", "[::1]:0") if err != nil { t.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String()) if err != nil { t.Fatal(err) } cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, Src: net.IPv6loopback, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) if ifi != nil { cm.IfIndex = ifi.Index } wb := []byte("HELLO-R-U-THERE") for i, toggle := range []bool{true, false, true} { if err := p.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Skipf("not supported on %s", runtime.GOOS) } t.Fatal(err) } cm.HopLimit = i + 1 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Fatal(err) } else if n != len(wb) { t.Fatalf("got %v; want %v", n, len(wb)) } rb := make([]byte, 128) if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, _, _, err := p.ReadFrom(rb); err != nil { t.Fatal(err) } else if !bytes.Equal(rb[:n], wb) { t.Fatalf("got %v; want %v", rb[:n], wb) } } }
func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } c, err := net.ListenPacket("udp6", "[::1]:0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String()) if err != nil { t.Fatalf("net.ResolveUDPAddr failed: %v", err) } cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, Src: net.IPv6loopback, Dst: net.IPv6loopback, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU ifi := loopbackInterface() if ifi != nil { cm.IfIndex = ifi.Index } wb := []byte("HELLO-R-U-THERE") for i, toggle := range []bool{true, false, true} { if err := p.SetControlMessage(cf, toggle); err != nil { t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err) } cm.HopLimit = i + 1 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err) } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err) } else if n != len(wb) { t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n) } rb := make([]byte, 128) if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err) } if n, cm, _, err := p.ReadFrom(rb); err != nil { t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err) } else if !bytes.Equal(rb[:n], wb) { t.Fatalf("got %v; expected %v", rb[:n], wb) } else { t.Logf("rcvd cmsg: %v", cm) } } }
func (s *Server) sendRA(src net.Addr) { var srcIP net.IP var ipAddr net.Addr iface, err := net.InterfaceByName("tap" + s.name) if err != nil { return } addrs, err := iface.Addrs() if err != nil { l.Info("can't get addresses from " + iface.Name + " " + err.Error()) return } for _, addr := range addrs { ip, _, err := net.ParseCIDR(addr.String()) if err != nil { l.Info(err.Error()) continue } if ip.To4() == nil && strings.HasPrefix(addr.String(), "fe80") { srcIP = ip if src == nil { ipAddr = net.Addr(&net.IPAddr{IP: net.IPv6linklocalallnodes, Zone: "tap" + s.name}) } else { ipAddr = src } break } } if ipAddr == nil || srcIP == nil { l.Info(fmt.Sprintf("ipv6 add missing for tap %s %s", s.name, srcIP)) return } res, err := s.ServeICMPv6(srcIP, &ICMPv6{Type: uint8(ipv6.ICMPTypeRouterSolicitation)}) if err != nil { l.Info(err.Error()) return } for _, msg := range res { buf := make([]byte, msg.Len()) buf, err = msg.Marshal() if err != nil { l.Info(fmt.Sprintf("%s err %s", s.name, err.Error())) continue } wcm := ipv6.ControlMessage{HopLimit: 255} wcm.Dst = net.IPv6linklocalallnodes wcm.IfIndex = iface.Index if _, err = s.ipv6conn.WriteTo(buf, &wcm, ipAddr); err != nil { l.Info(fmt.Sprintf("%s err %s", s.name, err.Error())) continue } } }
func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) { cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, HopLimit: 1, } if ifi != nil { cm.IfIndex = ifi.Index } if n, err := p.WriteTo(wb, &cm, dst); err != nil { b.Fatal(err) } else if n != len(wb) { b.Fatalf("got %v; want %v", n, len(wb)) } if _, _, _, err := p.ReadFrom(rb); err != nil { b.Fatal(err) } }
func ExamplePacketConn_servingOneShotMulticastDNS() { c, err := net.ListenPacket("udp6", "[::]:5353") // mDNS over UDP if err != nil { log.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) en0, err := net.InterfaceByName("en0") if err != nil { log.Fatal(err) } mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")} if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil { log.Fatal(err) } defer p.LeaveGroup(en0, &mDNSLinkLocal) if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { log.Fatal(err) } var wcm ipv6.ControlMessage b := make([]byte, 1500) for { _, rcm, peer, err := p.ReadFrom(b) if err != nil { log.Fatal(err) } if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) { continue } wcm.IfIndex = rcm.IfIndex answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this if _, err := p.WriteTo(answers, &wcm, peer); err != nil { log.Fatal(err) } } }
func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } if os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") if err != nil { t.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveIPAddr("ip6", "::1") if err != nil { t.Fatal(err) } pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP) cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, Src: net.IPv6loopback, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) if ifi != nil { cm.IfIndex = ifi.Index } var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { t.Fatal(err) } var psh []byte for i, toggle := range []bool{true, false, true} { if toggle { psh = nil if err := p.SetChecksum(true, 2); err != nil { t.Fatal(err) } } else { psh = pshicmp // Some platforms never allow to disable the // kernel checksum processing. p.SetChecksum(false, -1) } wb, err := (&icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(psh) if err != nil { t.Fatal(err) } if err := p.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Skipf("not supported on %q", runtime.GOOS) } t.Fatal(err) } cm.HopLimit = i + 1 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Fatal(err) } else if n != len(wb) { t.Fatalf("got %v; want %v", n, len(wb)) } rb := make([]byte, 128) if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, cm, _, err := p.ReadFrom(rb); err != nil { switch runtime.GOOS { case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket t.Logf("not supported on %q", runtime.GOOS) continue } t.Fatal(err) } else { t.Logf("rcvd cmsg: %v", cm) if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { t.Fatal(err) } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) } } } }
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } c, err := net.ListenPacket("udp6", "[::1]:0") if err != nil { t.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String()) if err != nil { t.Fatal(err) } ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU wb := []byte("HELLO-R-U-THERE") if err := p.SetControlMessage(cf, true); err != nil { // probe before test if nettest.ProtocolNotSupported(err) { t.Skipf("not supported on %s", runtime.GOOS) } t.Fatal(err) } var wg sync.WaitGroup reader := func() { defer wg.Done() rb := make([]byte, 128) if n, cm, _, err := p.ReadFrom(rb); err != nil { t.Error(err) return } else if !bytes.Equal(rb[:n], wb) { t.Errorf("got %v; want %v", rb[:n], wb) return } else { s := cm.String() if strings.Contains(s, ",") { t.Errorf("should be space-separated values: %s", s) } } } writer := func(toggle bool) { defer wg.Done() cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, Src: net.IPv6loopback, } if ifi != nil { cm.IfIndex = ifi.Index } if err := p.SetControlMessage(cf, toggle); err != nil { t.Error(err) return } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Error(err) return } else if n != len(wb) { t.Errorf("got %v; want %v", n, len(wb)) return } } const N = 10 wg.Add(N) for i := 0; i < N; i++ { go reader() } wg.Add(2 * N) for i := 0; i < 2*N; i++ { go writer(i%2 != 0) } wg.Add(N) for i := 0; i < N; i++ { go reader() } wg.Wait() }
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } c, err := net.ListenPacket("udp6", "[::1]:0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String()) if err != nil { t.Fatalf("net.ResolveUDPAddr failed: %v", err) } ifi := loopbackInterface() cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU wb := []byte("HELLO-R-U-THERE") var wg sync.WaitGroup reader := func() { defer wg.Done() rb := make([]byte, 128) if n, cm, _, err := p.ReadFrom(rb); err != nil { t.Errorf("ipv6.PacketConn.ReadFrom failed: %v", err) return } else if !bytes.Equal(rb[:n], wb) { t.Errorf("got %v; expected %v", rb[:n], wb) return } else { t.Logf("rcvd cmsg: %v", cm) } } writer := func(toggle bool) { defer wg.Done() cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, Src: net.IPv6loopback, Dst: net.IPv6loopback, } if ifi != nil { cm.IfIndex = ifi.Index } if err := p.SetControlMessage(cf, toggle); err != nil { t.Errorf("ipv6.PacketConn.SetControlMessage failed: %v", err) return } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Errorf("ipv6.PacketConn.WriteTo failed: %v", err) return } else if n != len(wb) { t.Errorf("ipv6.PacketConn.WriteTo failed: short write: %v", n) return } } const N = 10 wg.Add(N) for i := 0; i < N; i++ { go reader() } wg.Add(2 * N) for i := 0; i < 2*N; i++ { go writer(i%2 != 0) } wg.Add(N) for i := 0; i < N; i++ { go reader() } wg.Wait() }