- dhcp: CheckIfOtherDHCPServersPresent: fix
Sometimes request from DHCP server couldn't be received because we were bound to a specific IP address.
This commit is contained in:
parent
6090400ea0
commit
23752377b7
@ -7,12 +7,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
||||||
"github.com/insomniacslk/dhcp/iana"
|
"github.com/insomniacslk/dhcp/iana"
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckIfOtherDHCPServersPresent sends a DHCP request to the specified network interface,
|
// 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)
|
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]
|
srcIP := ifaceIPNet[0]
|
||||||
src := net.JoinHostPort(srcIP.String(), "68")
|
src := net.JoinHostPort(srcIP.String(), "68")
|
||||||
dst := "255.255.255.255:67"
|
dst := "255.255.255.255:67"
|
||||||
@ -60,7 +65,7 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) {
|
|||||||
|
|
||||||
// bind to 0.0.0.0:68
|
// bind to 0.0.0.0:68
|
||||||
log.Tracef("Listening to udp4 %+v", udpAddr)
|
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 {
|
if c != nil {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
}
|
}
|
||||||
@ -69,8 +74,7 @@ func CheckIfOtherDHCPServersPresent(ifaceName string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send to 255.255.255.255:67
|
// send to 255.255.255.255:67
|
||||||
cm := ipv4.ControlMessage{}
|
_, err = c.WriteTo(req.ToBytes(), dstAddr)
|
||||||
_, err = c.WriteTo(req.ToBytes(), &cm, dstAddr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, wrapErrPrint(err, "Couldn't send a packet to %s", dst)
|
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
|
// TODO: replicate dhclient's behaviour of retrying several times with progressively bigger timeouts
|
||||||
b := make([]byte, 1500)
|
b := make([]byte, 1500)
|
||||||
_ = c.SetReadDeadline(time.Now().Add(defaultDiscoverTime))
|
_ = c.SetReadDeadline(time.Now().Add(defaultDiscoverTime))
|
||||||
n, _, _, err := c.ReadFrom(b)
|
n, _, err := c.ReadFrom(b)
|
||||||
if isTimeout(err) {
|
if isTimeout(err) {
|
||||||
// timed out -- no DHCP servers
|
// timed out -- no DHCP servers
|
||||||
|
log.Debug("DHCPv4: didn't receive DHCP response")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user