From 23752377b76895dbcd78f25ed6df58e1bbcae153 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Wed, 12 Aug 2020 18:13:07 +0300 Subject: [PATCH] - dhcp: CheckIfOtherDHCPServersPresent: fix Sometimes request from DHCP server couldn't be received because we were bound to a specific IP address. --- dhcpd/check_other_dhcp.go | 15 ++++++++----- dhcpd/os_linux.go | 45 --------------------------------------- dhcpd/os_unix.go | 44 -------------------------------------- 3 files changed, 10 insertions(+), 94 deletions(-) delete mode 100644 dhcpd/os_linux.go delete mode 100644 dhcpd/os_unix.go diff --git a/dhcpd/check_other_dhcp.go b/dhcpd/check_other_dhcp.go index 83c9ca1b..099673f0 100644 --- a/dhcpd/check_other_dhcp.go +++ b/dhcpd/check_other_dhcp.go @@ -7,12 +7,13 @@ import ( "fmt" "net" "os" + "runtime" "time" "github.com/AdguardTeam/golibs/log" "github.com/insomniacslk/dhcp/dhcpv4" + "github.com/insomniacslk/dhcp/dhcpv4/nclient4" "github.com/insomniacslk/dhcp/iana" - "golang.org/x/net/ipv4" ) // CheckIfOtherDHCPServersPresent sends a DHCP request to the specified network interface, @@ -29,6 +30,10 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) { return false, fmt.Errorf("couldn't find IPv4 address of interface %s %+v", ifaceName, iface) } + if runtime.GOOS == "darwin" { + return false, fmt.Errorf("Can't find DHCP server: not supported on macOS") + } + srcIP := ifaceIPNet[0] src := net.JoinHostPort(srcIP.String(), "68") dst := "255.255.255.255:67" @@ -60,7 +65,7 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) { // bind to 0.0.0.0:68 log.Tracef("Listening to udp4 %+v", udpAddr) - c, err := newBroadcastPacketConn(net.IPv4(0, 0, 0, 0), 68, ifaceName) + c, err := nclient4.NewRawUDPConn(ifaceName, 68) if c != nil { defer c.Close() } @@ -69,8 +74,7 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) { } // send to 255.255.255.255:67 - cm := ipv4.ControlMessage{} - _, err = c.WriteTo(req.ToBytes(), &cm, dstAddr) + _, err = c.WriteTo(req.ToBytes(), dstAddr) if err != nil { return false, wrapErrPrint(err, "Couldn't send a packet to %s", dst) } @@ -81,9 +85,10 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) { // TODO: replicate dhclient's behaviour of retrying several times with progressively bigger timeouts b := make([]byte, 1500) _ = c.SetReadDeadline(time.Now().Add(defaultDiscoverTime)) - n, _, _, err := c.ReadFrom(b) + n, _, err := c.ReadFrom(b) if isTimeout(err) { // timed out -- no DHCP servers + log.Debug("DHCPv4: didn't receive DHCP response") return false, nil } if err != nil { diff --git a/dhcpd/os_linux.go b/dhcpd/os_linux.go deleted file mode 100644 index 5cbcfece..00000000 --- a/dhcpd/os_linux.go +++ /dev/null @@ -1,45 +0,0 @@ -package dhcpd - -import ( - "net" - "os" - "syscall" - - "golang.org/x/net/ipv4" -) - -// Create a socket for receiving broadcast packets -func newBroadcastPacketConn(bindAddr net.IP, port int, ifname string) (*ipv4.PacketConn, error) { - s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) - if err != nil { - return nil, err - } - - if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { - return nil, err - } - if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { - return nil, err - } - if err := syscall.SetsockoptString(s, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, ifname); err != nil { - return nil, err - } - - addr := syscall.SockaddrInet4{Port: port} - copy(addr.Addr[:], bindAddr.To4()) - err = syscall.Bind(s, &addr) - if err != nil { - syscall.Close(s) - return nil, err - } - - f := os.NewFile(uintptr(s), "") - c, err := net.FilePacketConn(f) - f.Close() - if err != nil { - return nil, err - } - - p := ipv4.NewPacketConn(c) - return p, nil -} diff --git a/dhcpd/os_unix.go b/dhcpd/os_unix.go deleted file mode 100644 index 11592d33..00000000 --- a/dhcpd/os_unix.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build aix darwin dragonfly freebsd netbsd openbsd solaris - -package dhcpd - -import ( - "net" - "os" - "syscall" - - "golang.org/x/net/ipv4" -) - -// Create a socket for receiving broadcast packets -func newBroadcastPacketConn(bindAddr net.IP, port int, ifname string) (*ipv4.PacketConn, error) { - s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) - if err != nil { - return nil, err - } - - if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { - return nil, err - } - if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { - return nil, err - } - - addr := syscall.SockaddrInet4{Port: port} - copy(addr.Addr[:], bindAddr.To4()) - err = syscall.Bind(s, &addr) - if err != nil { - syscall.Close(s) - return nil, err - } - - f := os.NewFile(uintptr(s), "") - c, err := net.FilePacketConn(f) - f.Close() - if err != nil { - return nil, err - } - - p := ipv4.NewPacketConn(c) - return p, nil -}