func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { case "dragonfly", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } for _, gaddr := range udpMultipleGroupListenerTests { c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c1.Close() c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c2.Close() var ps [2]*ipv6.PacketConn ps[0] = ipv6.NewPacketConn(c1) ps[1] = ipv6.NewPacketConn(c2) var mift []*net.Interface ift, err := net.Interfaces() if err != nil { t.Fatalf("net.Interfaces failed: %v", err) } for i, ifi := range ift { if _, ok := isMulticastAvailable(&ifi); !ok { continue } for _, p := range ps { if err := p.JoinGroup(&ifi, gaddr); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err) } } mift = append(mift, &ift[i]) } for _, ifi := range mift { for _, p := range ps { if err := p.LeaveGroup(ifi, gaddr); err != nil { t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err) } } } } }
func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "dragonfly", "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 TestSetICMPFilter(t *testing.T) { switch runtime.GOOS { case "plan9", "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.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) var f ipv6.ICMPFilter f.SetAll(true) f.Set(ipv6.ICMPTypeEchoRequest, false) f.Set(ipv6.ICMPTypeEchoReply, false) if err := p.SetICMPFilter(&f); err != nil { t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err) } kf, err := p.ICMPFilter() if err != nil { t.Fatalf("ipv6.PacketConn.ICMPFilter failed: %v", err) } if !reflect.DeepEqual(kf, &f) { t.Fatalf("got unexpected filter %#v; expected %#v", kf, f) } }
// setInterface is used to set the query interface, uses sytem // default if not provided func (c *client) setInterface(iface *net.Interface) error { p := ipv4.NewPacketConn(c.ipv4UnicastConn) if err := p.SetMulticastInterface(iface); err != nil { return err } p2 := ipv6.NewPacketConn(c.ipv6UnicastConn) if err := p2.SetMulticastInterface(iface); err != nil { return err } p = ipv4.NewPacketConn(c.ipv4MulticastConn) if err := p.SetMulticastInterface(iface); err != nil { return err } p2 = ipv6.NewPacketConn(c.ipv6MulticastConn) if err := p2.SetMulticastInterface(iface); err != nil { return err } return nil }
func TestPacketConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { case "plan9", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } ifi := loopbackInterface() if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } for _, tt := range packetConnMulticastSocketOptionTests { if tt.net == "ip6" && os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) hoplim := 255 if err := p.SetMulticastHopLimit(hoplim); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastHopLimit failed: %v", err) } if v, err := p.MulticastHopLimit(); err != nil { t.Fatalf("ipv6.PacketConn.MulticastHopLimit failed: %v", err) } else if v != hoplim { t.Fatalf("got unexpected multicast hop limit %v; expected %v", v, hoplim) } for _, toggle := range []bool{true, false} { if err := p.SetMulticastLoopback(toggle); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err) } if v, err := p.MulticastLoopback(); err != nil { t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err) } else if v != toggle { t.Fatalf("got unexpected multicast loopback %v; expected %v", v, toggle) } } if err := p.JoinGroup(ifi, tt.gaddr); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup(%v, %v) failed: %v", ifi, tt.gaddr, err) } if err := p.LeaveGroup(ifi, tt.gaddr); err != nil { t.Fatalf("ipv6.PacketConn.LeaveGroup(%v, %v) failed: %v", ifi, tt.gaddr, err) } } }
func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "plan9", "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() dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String()) if err != nil { t.Fatalf("net.ResolveUDPAddr failed: %v", err) } p := ipv6.NewPacketConn(c) defer p.Close() cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU ifi := loopbackInterface() if ifi != nil { cm.IfIndex = ifi.Index } 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(time.Millisecond * 100)); err != nil { t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err) } if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil { t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err) } b := make([]byte, 128) if err := p.SetReadDeadline(time.Now().Add(time.Millisecond * 100)); err != nil { t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err) } if _, cm, _, err := p.ReadFrom(b); err != nil { t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) } } }
func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "darwin", "dragonfly", "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") } gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727 type ml struct { c *ipv6.PacketConn ifi *net.Interface } var mlt []*ml ift, err := net.Interfaces() if err != nil { t.Fatalf("net.Interfaces failed: %v", err) } for i, ifi := range ift { ip, ok := isMulticastAvailable(&ifi) if !ok { continue } c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) if err := p.JoinGroup(&ifi, &gaddr); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err) } mlt = append(mlt, &ml{p, &ift[i]}) } for _, m := range mlt { if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err) } } }
func BenchmarkReadWriteIPv6UDP(b *testing.B) { c, dst, err := benchmarkUDPListener() if err != nil { b.Fatalf("benchmarkUDPListener failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU if err := p.SetControlMessage(cf, true); err != nil { b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err) } ifi := loopbackInterface() for i := 0; i < b.N; i++ { benchmarkReadWriteIPv6UDP(b, p, dst, ifi) } }
func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "dragonfly", "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", "::") // wildcard address if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727 var mift []*net.Interface ift, err := net.Interfaces() if err != nil { t.Fatalf("net.Interfaces failed: %v", err) } for i, ifi := range ift { if _, ok := isMulticastAvailable(&ifi); !ok { continue } if err := p.JoinGroup(&ifi, &gaddr); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err) } mift = append(mift, &ift[i]) } for _, ifi := range mift { if err := p.LeaveGroup(ifi, &gaddr); err != nil { t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", ifi, err) } } }
func TestPacketConnUnicastSocketOptions(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") } for _, tt := range packetConnUnicastSocketOptionTests { if tt.net == "ip6" && os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) if err != nil { t.Fatalf("net.ListenPacket(%q, %q) failed: %v", tt.net+tt.proto, tt.addr, err) } defer c.Close() testUnicastSocketOptions(t, ipv6.NewPacketConn(c)) } }
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { case "plan9", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } for _, gaddr := range udpMultipleGroupListenerTests { c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) var mift []*net.Interface ift, err := net.Interfaces() if err != nil { t.Fatalf("net.Interfaces failed: %v", err) } for i, ifi := range ift { if _, ok := isMulticastAvailable(&ifi); !ok { continue } if err := p.JoinGroup(&ifi, gaddr); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err) } mift = append(mift, &ift[i]) } for _, ifi := range mift { if err := p.LeaveGroup(ifi, gaddr); err != nil { t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err) } } } }
func TestPacketConnChecksum(t *testing.T) { switch runtime.GOOS { case "dragonfly", "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:89", "::") // OSPF for IPv6 if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) offset := 12 // see RFC 5340 for _, toggle := range []bool{false, true} { if err := p.SetChecksum(toggle, offset); err != nil { if toggle { t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err) } else { // Some platforms never allow to disable the kernel // checksum processing. t.Logf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err) } } if on, offset, err := p.Checksum(); err != nil { t.Fatalf("ipv6.PacketConn.Checksum failed: %v", err) } else { t.Logf("kernel checksum processing enabled=%v, offset=%v", on, offset) } } }
func TestPacketConnReadWriteMulticastICMP(t *testing.T) { switch runtime.GOOS { case "plan9", "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") } ifi := loopbackInterface() if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip6:ipv6-icmp", "::") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() dst, err := net.ResolveIPAddr("ip6", "ff02::114") // see RFC 4727 if err != nil { t.Fatalf("net.ResolveIPAddr failed: %v", err) } p := ipv6.NewPacketConn(c) if err := p.JoinGroup(ifi, dst); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err) } if err := p.SetMulticastInterface(ifi); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err) } if err := p.SetMulticastLoopback(true); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err) } cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, IfIndex: ifi.Index, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU var f ipv6.ICMPFilter f.SetAll(true) f.Set(ipv6.ICMPTypeEchoReply, false) if err := p.SetICMPFilter(&f); err != nil { t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err) } for i, toggle := range []bool{true, false, true} { wb, err := (&icmpMessage{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmpEcho{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal() if err != nil { t.Fatalf("icmpMessage.Marshal failed: %v", err) } if err := p.SetControlMessage(cf, toggle); err != nil { t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err) } cm.HopLimit = i + 1 if _, err := p.WriteTo(wb, &cm, dst); err != nil { t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err) } b := make([]byte, 128) if n, cm, _, err := p.ReadFrom(b); err != nil { t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) if m, err := parseICMPMessage(b[:n]); err != nil { t.Fatalf("parseICMPMessage failed: %v", err) } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) } } } }
func TestPacketConnReadWriteMulticastUDP(t *testing.T) { switch runtime.GOOS { case "freebsd": // due to a bug on loopback marking t.Skipf("not supported on %q", runtime.GOOS) case "plan9", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } ifi := loopbackInterface() if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("udp6", "[ff02::114]:0") // see RFC 4727 if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() _, port, err := net.SplitHostPort(c.LocalAddr().String()) if err != nil { t.Fatalf("net.SplitHostPort failed: %v", err) } dst, err := net.ResolveUDPAddr("udp6", "[ff02::114]:"+port) // see RFC 4727 if err != nil { t.Fatalf("net.ResolveUDPAddr failed: %v", err) } p := ipv6.NewPacketConn(c) if err := p.JoinGroup(ifi, dst); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err) } if err := p.SetMulticastInterface(ifi); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err) } if err := p.SetMulticastLoopback(true); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err) } cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, IfIndex: ifi.Index, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU 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.WriteTo([]byte("HELLO-R-U-THERE"), &cm, dst); err != nil { t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err) } b := make([]byte, 128) if _, cm, _, err := p.ReadFrom(b); err != nil { t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) } } }
func (b *Beacon) start() (err error) { if b.iface == "" { b.iface = os.Getenv("BEACON_INTERFACE") } if b.iface == "" { b.iface = os.Getenv("ZSYS_INTERFACE") } var ifs []net.Interface if b.iface == "" { ifs, err = net.Interfaces() if err != nil { return err } } else { iface, err := net.InterfaceByName(b.iface) if err != nil { return err } ifs = append(ifs, *iface) } conn, err := net.ListenPacket("udp4", net.JoinHostPort("224.0.0.0", strconv.Itoa(b.port))) if err == nil { b.ipv4Conn = ipv4.NewPacketConn(conn) b.ipv4Conn.SetMulticastLoopback(true) b.ipv4Conn.SetControlMessage(ipv4.FlagSrc, true) } if !b.ipv4 { conn, err := net.ListenPacket("udp6", net.JoinHostPort(net.IPv6linklocalallnodes.String(), strconv.Itoa(b.port))) if err != nil { return err } b.ipv6Conn = ipv6.NewPacketConn(conn) b.ipv6Conn.SetMulticastLoopback(true) b.ipv6Conn.SetControlMessage(ipv6.FlagSrc, true) } broadcast := os.Getenv("BEACON_BROADCAST") != "" for _, iface := range ifs { if b.ipv4Conn != nil { b.inAddr = &net.UDPAddr{ IP: net.ParseIP(ipv4Group), } b.ipv4Conn.JoinGroup(&iface, b.inAddr) // Find IP of the interface // TODO(armen): Let user set the ipaddress which here can be verified to be valid addrs, err := iface.Addrs() if err != nil { return err } if len(addrs) <= 0 { return errors.New("no address to bind to") } ip, ipnet, err := net.ParseCIDR(addrs[0].String()) if err != nil { return err } b.addr = ip.String() switch { case broadcast: bcast := ipnet.IP for i := 0; i < len(ipnet.Mask); i++ { bcast[i] |= ^ipnet.Mask[i] } b.outAddr = &net.UDPAddr{IP: bcast, Port: b.port} case iface.Flags&net.FlagLoopback != 0: b.outAddr = &net.UDPAddr{IP: net.IPv4allsys, Port: b.port} default: b.outAddr = &net.UDPAddr{IP: net.ParseIP(ipv4Group), Port: b.port} } break } else if b.ipv6Conn != nil { b.inAddr = &net.UDPAddr{ IP: net.ParseIP(ipv6Group), } b.ipv6Conn.JoinGroup(&iface, b.inAddr) // Find IP of the interface // TODO(armen): Let user set the ipaddress which here can be verified to be valid addrs, err := iface.Addrs() if err != nil { return err } ip, ipnet, err := net.ParseCIDR(addrs[0].String()) if err != nil { return err } b.addr = ip.String() switch { case broadcast: bcast := ipnet.IP for i := 0; i < len(ipnet.Mask); i++ { bcast[i] |= ^ipnet.Mask[i] } b.outAddr = &net.UDPAddr{IP: bcast, Port: b.port} case iface.Flags&net.FlagLoopback != 0: b.outAddr = &net.UDPAddr{IP: net.IPv6interfacelocalallnodes, Port: b.port} default: b.outAddr = &net.UDPAddr{IP: net.ParseIP(ipv6Group), Port: b.port} } break } } if b.ipv4Conn == nil && b.ipv6Conn == nil { return errors.New("no interfaces to bind to") } go b.listen() go b.signal() return nil }
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() }
func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { case "dragonfly", "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.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveIPAddr("ip6", "::1") if err != nil { t.Fatalf("net.ResolveIPAddr failed: %v", err) } pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP) 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 } var f ipv6.ICMPFilter f.SetAll(true) f.Set(ipv6.ICMPTypeEchoReply, false) if err := p.SetICMPFilter(&f); err != nil { t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", 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.Fatalf("ipv6.PacketConn.SetChecksum failed: %v", err) } } else { psh = pshicmp // Some platforms never allow to disable the // kernel checksum processing. p.SetChecksum(false, -1) } wb, err := (&icmpMessage{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmpEcho{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(psh) if err != nil { t.Fatalf("icmpMessage.Marshal failed: %v", err) } 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 { t.Logf("rcvd cmsg: %v", cm) if m, err := parseICMPMessage(rb[:n]); err != nil { t.Fatalf("parseICMPMessage failed: %v", err) } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) } } } }
func TestPacketConnReadWriteMulticastUDP(t *testing.T) { switch runtime.GOOS { case "freebsd": // due to a bug on loopback marking // See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065. t.Skipf("not supported on %q", runtime.GOOS) case "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } ifi := loopbackInterface() if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("udp6", "[ff02::114]:0") // see RFC 4727 if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() _, port, err := net.SplitHostPort(c.LocalAddr().String()) if err != nil { t.Fatalf("net.SplitHostPort failed: %v", err) } dst, err := net.ResolveUDPAddr("udp6", "[ff02::114]:"+port) // see RFC 4727 if err != nil { t.Fatalf("net.ResolveUDPAddr failed: %v", err) } p := ipv6.NewPacketConn(c) defer p.Close() if err := p.JoinGroup(ifi, dst); err != nil { t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err) } if err := p.SetMulticastInterface(ifi); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err) } if _, err := p.MulticastInterface(); err != nil { t.Fatalf("ipv6.PacketConn.MulticastInterface failed: %v", err) } if err := p.SetMulticastLoopback(true); err != nil { t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err) } if _, err := p.MulticastLoopback(); err != nil { t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err) } cm := ipv6.ControlMessage{ TrafficClass: DiffServAF11 | CongestionExperienced, Src: net.IPv6loopback, IfIndex: ifi.Index, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 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) } if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err) } cm.HopLimit = i + 1 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 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) } } }