summaryrefslogtreecommitdiffhomepage
path: root/dhcpv4/server4/conn.go
diff options
context:
space:
mode:
authorborna-blazevic <54031251+borna-blazevic@users.noreply.github.com>2019-08-14 10:20:28 +0200
committerPablo Mazzini <pmazzini@gmail.com>2019-08-14 09:20:28 +0100
commit393ae75a101b4e8d93f82dd7242401dd50ac0868 (patch)
tree725ec5a42fd2066e71ba284bb9823d08bb0d138b /dhcpv4/server4/conn.go
parent6d0d21cc633742eb4de9b08ad7a53572a6907623 (diff)
Bind interface fix (#310)
Added a bind to interface functionality.
Diffstat (limited to 'dhcpv4/server4/conn.go')
-rw-r--r--dhcpv4/server4/conn.go45
1 files changed, 45 insertions, 0 deletions
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)
+}