func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { t.Skip("to avoid external network") } for _, gaddr := range udpMultipleGroupListenerTests { c1, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port if err != nil { t.Fatal(err) } defer c1.Close() c2, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port if err != nil { t.Fatal(err) } defer c2.Close() var ps [2]*ipv4.PacketConn ps[0] = ipv4.NewPacketConn(c1) ps[1] = ipv4.NewPacketConn(c2) var mift []*net.Interface ift, err := net.Interfaces() if err != nil { t.Fatal(err) } for i, ifi := range ift { if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok { continue } for _, p := range ps { if err := p.JoinGroup(&ifi, gaddr); err != nil { t.Fatal(err) } } mift = append(mift, &ift[i]) } for _, ifi := range mift { for _, p := range ps { if err := p.LeaveGroup(ifi, gaddr); err != nil { t.Fatal(err) } } } } }
// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting // packets into a UDP listener with a BPF program attached to it. func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) { l, err := net.ListenPacket("udp4", "127.0.0.1:0") if err != nil { t.Fatalf("failed to open OS VM UDP listener: %v", err) } prog, err := bpf.Assemble(filter) if err != nil { t.Fatalf("failed to compile BPF program: %v", err) } p := ipv4.NewPacketConn(l) if err = p.SetBPF(prog); err != nil { t.Fatalf("failed to attach BPF program to listener: %v", err) } s, err := net.Dial("udp4", l.LocalAddr().String()) if err != nil { t.Fatalf("failed to dial connection to listener: %v", err) } done := func() { _ = s.Close() _ = l.Close() } return &osVirtualMachine{ l: l, s: s, }, done }
// NewHTTPUClient creates a new HTTPUClient, opening up a new UDP socket for the // purpose. func NewHTTPUClient() (*HTTPUClient, error) { conn, err := net.ListenPacket("udp4", ":0") if err != nil { return nil, err } return &HTTPUClient{conn: ipv4.NewPacketConn(conn)}, nil }
// ServeIf does the same job as Serve(), but listens and responds on the // specified network interface (by index). It also doubles as an example of // how to leverage the dhcp4.ServeConn interface. // // If your target only has one interface, use Serve(). ServeIf() requires an // import outside the std library. Serving DHCP over multiple interfaces will // require your own dhcp4.ServeConn, as listening to broadcasts utilises all // interfaces (so you cannot have more than on listener). func ServeIf(ifIndex int, conn net.PacketConn, handler Handler) error { p := ipv4.NewPacketConn(conn) if err := p.SetControlMessage(ipv4.FlagInterface, true); err != nil { return err } return Serve(&serveIfConn{ifIndex: ifIndex, conn: p}, handler) }
func mcastOpen(bindAddr net.IP, port int, ifname string) (*ipv4.PacketConn, *net.UDPConn, error) { s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { log.Fatal(err) } if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { log.Fatal(err) } //syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) if err := syscall.SetsockoptString(s, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, ifname); err != nil { log.Fatal(err) } lsa := syscall.SockaddrInet4{Port: port} copy(lsa.Addr[:], bindAddr.To4()) if err := syscall.Bind(s, &lsa); err != nil { syscall.Close(s) log.Fatal(err) } f := os.NewFile(uintptr(s), "") c, err := net.FilePacketConn(f) f.Close() if err != nil { log.Fatal(err) } u := c.(*net.UDPConn) p := ipv4.NewPacketConn(c) return p, u, nil }
func TestSetICMPFilter(t *testing.T) { switch runtime.GOOS { case "linux": default: t.Skipf("not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket("ip4:icmp", "127.0.0.1") if err != nil { t.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) var f ipv4.ICMPFilter f.SetAll(true) f.Accept(ipv4.ICMPTypeEcho) f.Accept(ipv4.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { t.Fatal(err) } kf, err := p.ICMPFilter() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(kf, &f) { t.Fatalf("got %#v; want %#v", kf, f) } }
func main() { flag.Parse() c, err := net.ListenPacket("udp", net.JoinHostPort(*group, "0")) if err != nil { log.Fatal(err) } p := ipv4.NewPacketConn(c) defer p.Close() dst, err := net.ResolveUDPAddr("udp", net.JoinHostPort(*group, *port)) if err != nil { log.Fatal(err) } log.Println(c.LocalAddr()) go sender(p, dst) sig := make(chan os.Signal) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) for { select { case <-sig: os.Exit(0) } } }
func TestPacketConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9": t.Skipf("not supported on %s", runtime.GOOS) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } m, ok := nettest.SupportsRawIPSocket() for _, tt := range packetConnUnicastSocketOptionTests { if tt.net == "ip4" && !ok { t.Log(m) continue } c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) if err != nil { t.Fatal(err) } defer c.Close() testUnicastSocketOptions(t, ipv4.NewPacketConn(c)) } }
func (s *serfDiscovery) Start() error { conn, err := net.ListenPacket("udp4", "0.0.0.0:1024") if err != nil { return err } s.pconn = ipv4.NewPacketConn(conn) if err := s.pconn.JoinGroup(s.iface, &net.UDPAddr{IP: s.group}); err != nil { conn.Close() return err } if err := s.pconn.SetControlMessage(ipv4.FlagDst, true); err != nil { conn.Close() return err } go func() { <-s.stop conn.Close() }() go func() { b := make([]byte, 1500) for { _, cm, src, err := s.pconn.ReadFrom(b) if err != nil { if strings.Contains(err.Error(), "closed network connection") { log.Printf("Closed connection, stopping discovery listener...") return } log.Printf("Failed to read packet: %s", err) continue } if cm.Dst.IsMulticast() { if cm.Dst.Equal(s.group) { sip, _, err := net.SplitHostPort(src.String()) if err != nil { log.Printf("Multicast src '%s' has unexpected format: %s", src, err) } if sip == s.self.String() { continue } err = s.serf.Join(sip) if err != nil { log.Printf("Failed to join serf gossip at '%s': %s ", sip, err) } } else { continue } } } }() return nil }
func TestPacketConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris": t.Skipf("not supported on %s", runtime.GOOS) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } m, ok := nettest.SupportsRawIPSocket() for _, tt := range packetConnMulticastSocketOptionTests { if tt.net == "ip4" && !ok { t.Log(m) continue } c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) if err != nil { t.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) defer p.Close() if tt.src == nil { testMulticastSocketOptions(t, p, ifi, tt.grp) } else { testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src) } } }
// ListenPacket listens for incoming ICMP packets addressed to // address. See net.Dial for the syntax of address. // // For non-privileged datagram-oriented ICMP endpoints, network must // be "udp4" or "udp6". The endpoint allows to read, write a few // limited ICMP messages such as echo request and echo reply. // Currently only Darwin and Linux support this. // // Examples: // ListenPacket("udp4", "192.168.0.1") // ListenPacket("udp4", "0.0.0.0") // ListenPacket("udp6", "fe80::1%en0") // ListenPacket("udp6", "::") // // For privileged raw ICMP endpoints, network must be "ip4" or "ip6" // followed by a colon and an ICMP protocol number or name. // // Examples: // ListenPacket("ip4:icmp", "192.168.0.1") // ListenPacket("ip4:1", "0.0.0.0") // ListenPacket("ip6:ipv6-icmp", "fe80::1%en0") // ListenPacket("ip6:58", "::") func ListenPacket(network, address string) (*PacketConn, error) { var family, proto int switch network { case "udp4": family, proto = syscall.AF_INET, iana.ProtocolICMP case "udp6": family, proto = syscall.AF_INET6, iana.ProtocolIPv6ICMP default: i := last(network, ':') switch network[:i] { case "ip4": proto = iana.ProtocolICMP case "ip6": proto = iana.ProtocolIPv6ICMP } } var cerr error var c net.PacketConn switch family { case syscall.AF_INET, syscall.AF_INET6: s, err := syscall.Socket(family, syscall.SOCK_DGRAM, proto) if err != nil { return nil, os.NewSyscallError("socket", err) } if runtime.GOOS == "darwin" && family == syscall.AF_INET { if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil { syscall.Close(s) return nil, os.NewSyscallError("setsockopt", err) } } sa, err := sockaddr(family, address) if err != nil { syscall.Close(s) return nil, err } if err := syscall.Bind(s, sa); err != nil { syscall.Close(s) return nil, os.NewSyscallError("bind", err) } f := os.NewFile(uintptr(s), "datagram-oriented icmp") c, cerr = net.FilePacketConn(f) f.Close() default: c, cerr = net.ListenPacket(network, address) } if cerr != nil { return nil, cerr } switch proto { case iana.ProtocolICMP: return &PacketConn{c: c, p4: ipv4.NewPacketConn(c)}, nil case iana.ProtocolIPv6ICMP: return &PacketConn{c: c, p6: ipv6.NewPacketConn(c)}, nil default: return &PacketConn{c: c}, nil } }
func MulticastListener(port int, ifname string) (*MulticastSock, error) { /* s, err1 := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err1 != nil { return nil, fmt.Errorf("MulticastListener: could not create socket(port=%d,ifname=%s): %v", port, ifname, err1) } if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { syscall.Close(s) return nil, fmt.Errorf("MulticastListener: could not set reuse addr socket(port=%d,ifname=%s): %v", port, ifname, err) } if ifname != "" { if err := syscall.SetsockoptString(s, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, ifname); err != nil { syscall.Close(s) return nil, fmt.Errorf("MulticastListener: could not bind to device socket(port=%d,ifname=%s): %v", port, ifname, err) } } bindAddr := net.IP(net.IPv4(0, 0, 0, 0)) lsa := syscall.SockaddrInet4{Port: port} copy(lsa.Addr[:], bindAddr.To4()) if err := syscall.Bind(s, &lsa); err != nil { syscall.Close(s) return nil, fmt.Errorf("MulticastListener: could not bind socket to address %v,%d: %v", bindAddr, port, err) } f := os.NewFile(uintptr(s), "") c, err2 := net.FilePacketConn(f) f.Close() if err2 != nil { syscall.Close(s) return nil, fmt.Errorf("MulticastListener: could not get packet connection for socket(port=%d,ifname=%s): %v", port, ifname, err2) } u := c.(*net.UDPConn) p := ipv4.NewPacketConn(c) if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { return nil, fmt.Errorf("MulticastListener: could not set control message flags: %v", err) } return &MulticastSock{P: p, U: u}, nil */ c, err := udpConn(&net.UDPAddr{IP: net.IPv4zero, Port: port}, ifname) if err != nil { return nil, err } u := c.(*net.UDPConn) p := ipv4.NewPacketConn(c) if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { return nil, fmt.Errorf("MulticastListener: could not set control message flags: %v", err) } return &MulticastSock{P: p, U: u}, nil }
// 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 TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("udp4", "127.0.0.1:0") if err != nil { t.Fatal(err) } defer c.Close() dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String()) if err != nil { t.Fatal(err) } p := ipv4.NewPacketConn(c) defer p.Close() cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface 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.Logf("not supported on %q", runtime.GOOS) continue } t.Fatal(err) } p.SetTTL(i + 1) if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, err := p.WriteTo(wb, nil, 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 { t.Fatal(err) } else if !bytes.Equal(rb[:n], wb) { t.Fatalf("got %v; want %v", rb[:n], wb) } else { t.Logf("rcvd cmsg: %v", cm) } } }
// NewPacketConn returns a PacketConn based on the specified net.PacketConn. // It adds functionality to return the interface index from calls to ReadFrom // and include the interface index argument in calls to WriteTo. func NewPacketConn(pc net.PacketConn) (PacketConn, error) { ipv4pc := ipv4.NewPacketConn(pc) if err := ipv4pc.SetControlMessage(ipv4.FlagInterface, true); err != nil { return nil, err } p := packetConn{ PacketConn: pc, ipv4pc: ipv4pc, } return &p, nil }
func main() { var nic string flag.StringVar(&nic, "i", "", "") flag.Parse() iface, err := net.InterfaceByName(nic) if err != nil { panic(err) } addr, _ := iface.Addrs() ip, _, _ := net.ParseCIDR(addr[0].String()) listenPort := fmt.Sprintf("%s:%d", ip, 10718) packet, err := net.ListenPacket("udp4", listenPort) if err != nil { panic(err) } defer packet.Close() p := ipv4.NewPacketConn(packet) if err := p.SetControlMessage(ipv4.FlagInterface, true); err != nil { panic(err) } buffer := make([]byte, 1500) for { _, cm, addr, err := p.ReadFrom(buffer) if err != nil { panic(err) } fmt.Printf("%v:\n", addr) fmt.Printf("%s\n", buffer) _, portStr, err := net.SplitHostPort(addr.String()) if err != nil { panic(err) } port, _ := strconv.Atoi(portStr) addr = &net.UDPAddr{IP: net.IPv4bcast, Port: port} // nilをぶち込まないとエラーになる。。 // panic: write udp4: invalid argument cm.Src = nil if _, e := p.WriteTo(buffer, cm, addr); e != nil { panic(e) } } }
func main() { flag.Parse() ip := net.ParseIP(*group) s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) if err != nil { log.Fatal(err) } syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) lsa := syscall.SockaddrInet4{Port: *port} copy(lsa.Addr[:], ip.To4()) if err := syscall.Bind(s, &lsa); err != nil { syscall.Close(s) log.Fatal(err) } f := os.NewFile(uintptr(s), "") c, err := net.FilePacketConn(f) f.Close() if err != nil { log.Fatal(err) } p := ipv4.NewPacketConn(c) defer p.Close() ift, err := net.Interfaces() if err != nil { log.Fatal(err) } avail := net.FlagMulticast | net.FlagUp for _, ifi := range ift { if ifi.Flags&avail != avail { continue } if err := p.JoinGroup(&ifi, &net.UDPAddr{IP: ip}); err != nil { log.Println(err, "on", ifi) } } log.Println(c.LocalAddr()) go receiver(c) sig := make(chan os.Signal) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) for { select { case <-sig: os.Exit(0) } } }
// Constructs server structure func newServer(iface *net.Interface) (*Server, error) { // Create wildcard connections (because :5353 can be already taken by other apps) ipv4conn, err := net.ListenUDP("udp4", mdnsWildcardAddrIPv4) if err != nil { log.Printf("[ERR] bonjour: Failed to bind to udp4 port: %v", err) } ipv6conn, err := net.ListenUDP("udp6", mdnsWildcardAddrIPv6) if err != nil { log.Printf("[ERR] bonjour: Failed to bind to udp6 port: %v", err) } if ipv4conn == nil && ipv6conn == nil { return nil, fmt.Errorf("[ERR] bonjour: Failed to bind to any udp port!") } // Join multicast groups to receive announcements p1 := ipv4.NewPacketConn(ipv4conn) p2 := ipv6.NewPacketConn(ipv6conn) if iface != nil { if err := p1.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil { return nil, err } if err := p2.JoinGroup(iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil { return nil, err } } else { ifaces, err := net.Interfaces() if err != nil { return nil, err } errCount1, errCount2 := 0, 0 for _, iface := range ifaces { if err := p1.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv4}); err != nil { errCount1++ } if err := p2.JoinGroup(&iface, &net.UDPAddr{IP: mdnsGroupIPv6}); err != nil { errCount2++ } } if len(ifaces) == errCount1 && len(ifaces) == errCount2 { return nil, fmt.Errorf("Failed to join multicast group on all interfaces!") } } s := &Server{ ipv4conn: ipv4conn, ipv6conn: ipv6conn, ttl: 3200, } return s, nil }
func LocalMulticastPacketConn() (conn *ipv4.PacketConn, err error) { /* lo,err := LoopbackInterface() if err != nil { return } maddrs, err := lo.MulticastAddrs() if err != nil { return } var bestAddr net.Addr for _,maddr := range maddrs { Trace.Printf("looking at: `%s`", maddr.String()) parsedIP := net.ParseIP(maddr.String()) if parsedIP == nil { Error.Printf("could not parsed IP: `%s`", maddr.String()) continue } else if parsedIP.To4() == nil { continue } bestAddr = maddr break } if bestAddr == nil { err = fmt.Errorf("could not find a good address to bind to") return } localMulticastSpec := fmt.Sprintf("%s:%d", bestAddr, 5555) */ // TODO fundamentally change how multicast is sent. I can't get the API to work // without creating a listener socket first but I shouldn't need it. // Had issues with running multiple services (heka and sdk_service) so I'm // going to the let the OS pick the port. `127.0.0.1:5556` used to work! localMulticastSpec := "127.0.0.1:" Trace.Printf("announce binding to port: `%s`", localMulticastSpec) udpConn, err := net.ListenPacket("udp", localMulticastSpec) if err != nil { Error.Printf("could not listen to `%s`", localMulticastSpec) return } Trace.Printf("udpConn.LocalAddr(): %s", udpConn.LocalAddr()) conn = ipv4.NewPacketConn(udpConn) return }
func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) { ret, err = net.ListenMulticastUDP("udp", &ifi, NetAddr) if err != nil { return } p := ipv4.NewPacketConn(ret) if err := p.SetMulticastTTL(2); err != nil { log.Println(err) } if err := p.SetMulticastLoopback(true); err != nil { log.Println(err) } return }
func ServeProxyDHCP(port int, booter api.Booter) error { conn, err := net.ListenPacket("udp4", fmt.Sprintf(":%d", port)) if err != nil { return err } defer conn.Close() l := ipv4.NewPacketConn(conn) if err = l.SetControlMessage(ipv4.FlagInterface, true); err != nil { return err } log.Log("ProxyDHCP", "Listening on port %d", port) buf := make([]byte, 1024) for { n, msg, addr, err := l.ReadFrom(buf) if err != nil { log.Log("ProxyDHCP", "Error reading from socket: %s", err) continue } udpAddr := addr.(*net.UDPAddr) udpAddr.IP = net.IPv4bcast req, err := ParseDHCP(buf[:n]) if err != nil { log.Debug("ProxyDHCP", "ParseDHCP: %s", err) continue } if err = booter.ShouldBoot(req.MAC); err != nil { log.Debug("ProxyDHCP", "Not offering to boot %s: %s", req.MAC, err) continue } req.ServerIP, err = InterfaceIP(msg.IfIndex) if err != nil { log.Log("ProxyDHCP", "Couldn't find an IP address to use to reply to %s: %s", req.MAC, err) continue } log.Log("ProxyDHCP", "Offering to boot %s (via %s)", req.MAC, req.ServerIP) if _, err := l.WriteTo(OfferDHCP(req), &ipv4.ControlMessage{ IfIndex: msg.IfIndex, }, udpAddr); err != nil { log.Log("ProxyDHCP", "Responding to %s: %s", req.MAC, err) continue } } }
func multicastRead(ifname, proto, addrPort string) error { iface, err1 := net.InterfaceByName(ifname) if err1 != nil { return err1 } // open/bind socket conn, err2 := net.ListenPacket(proto, addrPort) if err2 != nil { return fmt.Errorf("join: %s/%s listen error: %v", proto, addrPort, err2) } // join multicast address p := ipv4.NewPacketConn(conn) if err := p.JoinGroup(iface, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 9)}); err != nil { conn.Close() return fmt.Errorf("join: join error: %v", err) } // is this needed for receive? if err := p.SetMulticastInterface(iface); err != nil { log.Printf("join: %s SetMulticastInterface(%s) error: %v", addrPort, iface.Name, err) } { ifi, err3 := p.MulticastInterface() if err3 != nil { log.Printf("join: %s %s multicastInterface error: %v", iface.Name, addrPort, err3) } else { if ifi == nil { log.Printf("join: %s %s multicastInterface=nil", iface.Name, addrPort) } else { log.Printf("join: %s %s multicastInterface=%s", iface.Name, addrPort, ifi.Name) } } } // request control messages if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { // warning only log.Printf("join: control message flags error: %v", err) } udpReader(p, iface.Name, addrPort) return nil }
func (a *announcer) Listen() error { if a.listening { return nil } interfaces := util.GetMulticastInterfaces() annSocket, err := net.ListenUDP("udp4", a.announceAddress) if err != nil { return err } annConn := ipv4.NewPacketConn(annSocket) for _, ifc := range interfaces { err = annConn.JoinGroup(ifc, a.announceAddress) if err != nil { return err } } go func() { defer annConn.Close() incomingBuf := make([]byte, 64*1024) for a.listening { n, _, src, err := annConn.ReadFrom(incomingBuf) if err != nil { log.Errorf("Error reading from connection (%v): %v", annConn, err) time.Sleep(time.Millisecond * 100) continue } if !checkProtocolId(incomingBuf[:n]) { continue } a.addPeer(src.(*net.UDPAddr)) } }() return nil }
func ServePXE(pxeAddr string, httpPort int) error { conn, err := net.ListenPacket("udp4", pxeAddr) if err != nil { return err } defer conn.Close() l := ipv4.NewPacketConn(conn) if err = l.SetControlMessage(ipv4.FlagInterface, true); err != nil { return err } Log("PXE", "Listening on %s", pxeAddr) buf := make([]byte, 1024) for { n, msg, addr, err := l.ReadFrom(buf) if err != nil { Log("PXE", "Error reading from socket: %s", err) continue } req, err := ParsePXE(buf[:n]) if err != nil { Debug("PXE", "ParsePXE: %s", err) continue } req.ServerIP, err = interfaceIP(msg.IfIndex) if err != nil { Log("PXE", "Couldn't find an IP address to use to reply to %s: %s", req.MAC, err) continue } req.HTTPServer = fmt.Sprintf("http://%s:%d/", req.ServerIP, httpPort) Log("PXE", "Chainloading %s (%s) to pxelinux (via %s)", req.MAC, req.ClientIP, req.ServerIP) if _, err := l.WriteTo(ReplyPXE(req), &ipv4.ControlMessage{ IfIndex: msg.IfIndex, }, addr); err != nil { Log("PXE", "Responding to %s: %s", req.MAC, err) continue } } }
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { t.Skip("to avoid external network") } gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 type ml struct { c *ipv4.PacketConn ifi *net.Interface } var mlt []*ml ift, err := net.Interfaces() if err != nil { t.Fatal(err) } for i, ifi := range ift { ip, ok := nettest.IsMulticastCapable("ip4", &ifi) if !ok { continue } c, err := net.ListenPacket("udp4", ip.String()+":"+"1024") // unicast address with non-reusable port if err != nil { t.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) if err := p.JoinGroup(&ifi, &gaddr); err != nil { t.Fatal(err) } mlt = append(mlt, &ml{p, &ift[i]}) } for _, m := range mlt { if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { t.Fatal(err) } } }
func main() { group := net.IPv4(224, 0, 55, 56) dst := &net.UDPAddr{IP: group, Port: 5001} conn, c_err := net.ListenPacket("udp4", "0.0.0.0:5002") if c_err != nil { log.Fatal(c_err.Error()) } defer conn.Close() p := ipv4.NewPacketConn(conn) p.SetMulticastTTL(1) for { if _, write_err := p.WriteTo([]byte("hello there"), nil, dst); write_err != nil { log.Fatal(write_err.Error()) } time.Sleep(1 * time.Second) } }
func dial(ctx *Context) (MessageService, error) { group := net.ParseIP(ctx.Config.MessageService.BindGroup) ifaces, err := activeIfaces() if err != nil { return MessageService{}, err } myips, err := addressList(ifaces) if err != nil { return MessageService{}, err } c := make(chan Message) tcpAddr, err := net.ResolveTCPAddr("tcp4", ctx.Config.MessageService.BindAddress) if err != nil { return MessageService{}, err } port := tcpAddr.Port conn, err := net.ListenPacket("udp4", ctx.Config.MessageService.BindAddress) if err != nil { return MessageService{}, err } pconn := ipv4.NewPacketConn(conn) for _, iface := range ifaces { if err := pconn.JoinGroup(&iface, &net.UDPAddr{IP: group}); err != nil { return MessageService{}, err } } if err := pconn.SetControlMessage(ipv4.FlagDst, true); err != nil { return MessageService{}, err } pconn.SetTOS(0x0) pconn.SetTTL(16) return MessageService{group, port, conn, pconn, ifaces, ctx, ctx.Config.MessageService.Workers, c, myips}, nil }
// sendQuery is used to multicast a query out func (c *client) sendQuery(q *dns.Msg, iface *net.Interface) error { buf, err := q.Pack() if err != nil { return err } if c.ipv4UnicastConn != nil { p := ipv4.NewPacketConn(c.ipv4UnicastConn) if iface != nil { p.SetMulticastInterface(iface) } p.WriteTo(buf, nil, ipv4Addr) } if c.ipv6UnicastConn != nil { p := ipv6.NewPacketConn(c.ipv6UnicastConn) if iface != nil { p.SetMulticastInterface(iface) } p.WriteTo(buf, nil, ipv6Addr) } return nil }
func BenchmarkReadWriteIPv4UDP(b *testing.B) { c, dst, err := benchmarkUDPListener() if err != nil { b.Fatal(err) } defer c.Close() p := ipv4.NewPacketConn(c) defer p.Close() cf := ipv4.FlagTTL | ipv4.FlagInterface if err := p.SetControlMessage(cf, true); err != nil { b.Fatal(err) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128) b.ResetTimer() for i := 0; i < b.N; i++ { benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi) } }
func ServePXE(pxePort, httpPort int) error { conn, err := net.ListenPacket("udp4", fmt.Sprintf(":%d", pxePort)) if err != nil { return err } l := ipv4.NewPacketConn(conn) if err = l.SetControlMessage(ipv4.FlagInterface, true); err != nil { return err } Log("PXE", false, "Listening on port %d", pxePort) buf := make([]byte, 1024) for { n, msg, addr, err := l.ReadFrom(buf) if err != nil { Log("PXE", false, "Error reading from socket: %s", err) continue } req, err := ParsePXE(buf[:n]) if err != nil { Log("PXE", true, "ParsePXE: %s", err) continue } // TODO: figure out the correct IP req.ServerIP, err = interfaceIP(msg.IfIndex) req.HTTPServer = fmt.Sprintf("http://%s:%d/", req.ServerIP, httpPort) Log("PXE", false, "Chainloading %s to pxelinux (via %s)", req.MAC, req.ServerIP) if _, err := l.WriteTo(ReplyPXE(req), &ipv4.ControlMessage{ IfIndex: msg.IfIndex, }, addr); err != nil { Log("PXE", false, "Responding to %s: %s", req.MAC, err) continue } } }