diff options
-rw-r--r-- | dhcpv4/nclient4/client_test.go | 2 | ||||
-rw-r--r-- | dhcpv4/nclient4/conn_linux.go | 38 | ||||
-rw-r--r-- | dhcpv4/server4/conn.go | 45 | ||||
-rw-r--r-- | dhcpv4/server4/server.go | 4 | ||||
-rw-r--r-- | dhcpv4/server4/server_test.go | 4 |
5 files changed, 50 insertions, 43 deletions
diff --git a/dhcpv4/nclient4/client_test.go b/dhcpv4/nclient4/client_test.go index c299697..df851ab 100644 --- a/dhcpv4/nclient4/client_test.go +++ b/dhcpv4/nclient4/client_test.go @@ -61,7 +61,7 @@ func serveAndClient(ctx context.Context, responses [][]*dhcpv4.DHCPv4, opts ...C } h := &handler{responses: responses} - s, err := server4.NewServer(nil, h.handle, server4.WithConn(serverConn)) + s, err := server4.NewServer("", nil, h.handle, server4.WithConn(serverConn)) if err != nil { panic(err) } diff --git a/dhcpv4/nclient4/conn_linux.go b/dhcpv4/nclient4/conn_linux.go index af6485f..064e6ca 100644 --- a/dhcpv4/nclient4/conn_linux.go +++ b/dhcpv4/nclient4/conn_linux.go @@ -10,13 +10,10 @@ import ( "fmt" "io" "net" - "os" - "github.com/insomniacslk/dhcp/dhcpv4" "github.com/mdlayher/ethernet" "github.com/mdlayher/raw" "github.com/u-root/u-root/pkg/uio" - "golang.org/x/sys/unix" ) var ( @@ -26,41 +23,6 @@ var ( BroadcastMac = net.HardwareAddr([]byte{255, 255, 255, 255, 255, 255}) ) -// NewIPv4UDPConn returns a UDP connection bound to both the interface and port -// given based on a IPv4 DGRAM socket. The UDP connection allows broadcasting. -// -// The interface must already be configured. -func NewIPv4UDPConn(iface string, port int) (net.PacketConn, error) { - fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP) - if err != nil { - return nil, fmt.Errorf("cannot get a UDP socket: %v", err) - } - f := os.NewFile(uintptr(fd), "") - // net.FilePacketConn dups the FD, so we have to close this in any case. - defer f.Close() - - // Allow broadcasting. - if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_BROADCAST, 1); err != nil { - return nil, fmt.Errorf("cannot set broadcasting on socket: %v", err) - } - // Allow reusing the addr to aid debugging. - if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil { - return nil, fmt.Errorf("cannot set reuseaddr on socket: %v", err) - } - if len(iface) != 0 { - // Bind directly to the interface. - if err := dhcpv4.BindToInterface(fd, iface); err != nil { - return nil, fmt.Errorf("cannot bind to interface %s: %v", iface, err) - } - } - // Bind to the port. - if err := unix.Bind(fd, &unix.SockaddrInet4{Port: port}); err != nil { - return nil, fmt.Errorf("cannot bind to port %d: %v", port, err) - } - - return net.FilePacketConn(f) -} - // NewRawUDPConn returns a UDP connection bound to the interface and port // given based on a raw packet socket. All packets are broadcasted. // diff --git a/dhcpv4/server4/conn.go b/dhcpv4/server4/conn.go new file mode 100644 index 0000000..84d6aa3 --- /dev/null +++ b/dhcpv4/server4/conn.go @@ -0,0 +1,45 @@ +package server4 + +import ( + "fmt" + "net" + "os" + + "github.com/insomniacslk/dhcp/dhcpv4" + "golang.org/x/sys/unix" +) + +// NewIPv4UDPConn returns a UDP connection bound to both the interface and port +// given based on a IPv4 DGRAM socket. The UDP connection allows broadcasting. +// +// The interface must already be configured. +func NewIPv4UDPConn(iface string, port int) (net.PacketConn, error) { + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP) + if err != nil { + return nil, fmt.Errorf("cannot get a UDP socket: %v", err) + } + f := os.NewFile(uintptr(fd), "") + // net.FilePacketConn dups the FD, so we have to close this in any case. + defer f.Close() + + // Allow broadcasting. + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_BROADCAST, 1); err != nil { + return nil, fmt.Errorf("cannot set broadcasting on socket: %v", err) + } + // Allow reusing the addr to aid debugging. + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil { + return nil, fmt.Errorf("cannot set reuseaddr on socket: %v", err) + } + if len(iface) != 0 { + // Bind directly to the interface. + if err := dhcpv4.BindToInterface(fd, iface); err != nil { + return nil, fmt.Errorf("cannot bind to interface %s: %v", iface, err) + } + } + // Bind to the port. + if err := unix.Bind(fd, &unix.SockaddrInet4{Port: port}); err != nil { + return nil, fmt.Errorf("cannot bind to port %d: %v", port, err) + } + + return net.FilePacketConn(f) +} diff --git a/dhcpv4/server4/server.go b/dhcpv4/server4/server.go index 5567bae..fe4ef09 100644 --- a/dhcpv4/server4/server.go +++ b/dhcpv4/server4/server.go @@ -123,7 +123,7 @@ func WithConn(c net.PacketConn) ServerOpt { } // NewServer initializes and returns a new Server object -func NewServer(addr *net.UDPAddr, handler Handler, opt ...ServerOpt) (*Server, error) { +func NewServer(ifname string, addr *net.UDPAddr, handler Handler, opt ...ServerOpt) (*Server, error) { s := &Server{ Handler: handler, } @@ -133,7 +133,7 @@ func NewServer(addr *net.UDPAddr, handler Handler, opt ...ServerOpt) (*Server, e } if s.conn == nil { var err error - conn, err := net.ListenUDP("udp4", addr) + conn, err := NewIPv4UDPConn(ifname, addr.Port) if err != nil { return nil, err } diff --git a/dhcpv4/server4/server_test.go b/dhcpv4/server4/server_test.go index d24d49b..a596d04 100644 --- a/dhcpv4/server4/server_test.go +++ b/dhcpv4/server4/server_test.go @@ -73,7 +73,7 @@ func setUpClientAndServer(t *testing.T, iface net.Interface, handler Handler) (* IP: loAddr, Port: randPort(), } - s, err := NewServer(&saddr, handler) + s, err := NewServer("", &saddr, handler) if err != nil { t.Fatal(err) } @@ -81,7 +81,7 @@ func setUpClientAndServer(t *testing.T, iface net.Interface, handler Handler) (* _ = s.Serve() }() - clientConn, err := nclient4.NewIPv4UDPConn("", caddr.Port) + clientConn, err := NewIPv4UDPConn("", caddr.Port) if err != nil { t.Fatal(err) } |