From 6a5d0e2bcd1fe64b48ac462ffff0a31154f1050f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 11 Jun 2018 19:04:38 +0200 Subject: Support IPv6-less kernels --- conn_default.go | 89 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 29 deletions(-) (limited to 'conn_default.go') diff --git a/conn_default.go b/conn_default.go index 14ed56c..92135cb 100644 --- a/conn_default.go +++ b/conn_default.go @@ -11,7 +11,9 @@ package main import ( "golang.org/x/sys/unix" "net" + "os" "runtime" + "syscall" ) /* This code is meant to be a temporary solution @@ -87,6 +89,18 @@ func listenNet(network string, port int) (*net.UDPConn, int, error) { return conn, uaddr.Port, nil } +func extractErrno(err error) error { + opErr, ok := err.(*net.OpError) + if !ok { + return nil + } + syscallErr, ok := opErr.Err.(*os.SyscallError) + if !ok { + return nil + } + return syscallErr.Err +} + func CreateBind(uport uint16, device *Device) (Bind, uint16, error) { var err error var bind NativeBind @@ -94,13 +108,15 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) { port := int(uport) bind.ipv4, port, err = listenNet("udp4", port) - if err != nil { + if err != nil && extractErrno(err) != syscall.EAFNOSUPPORT { return nil, 0, err } bind.ipv6, port, err = listenNet("udp6", port) - if err != nil { + if err != nil && extractErrno(err) != syscall.EAFNOSUPPORT { + return nil, 0, err bind.ipv4.Close() + bind.ipv4 = nil return nil, 0, err } @@ -108,8 +124,13 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) { } func (bind *NativeBind) Close() error { - err1 := bind.ipv4.Close() - err2 := bind.ipv6.Close() + var err1, err2 error + if bind.ipv4 != nil { + err1 = bind.ipv4.Close() + } + if bind.ipv6 != nil { + err2 = bind.ipv6.Close() + } if err1 != nil { return err1 } @@ -117,6 +138,9 @@ func (bind *NativeBind) Close() error { } func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) { + if bind.ipv4 == nil { + return 0, nil, syscall.EAFNOSUPPORT + } n, endpoint, err := bind.ipv4.ReadFromUDP(buff) if endpoint != nil { endpoint.IP = endpoint.IP.To4() @@ -125,6 +149,9 @@ func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) { } func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) { + if bind.ipv6 == nil { + return 0, nil, syscall.EAFNOSUPPORT + } n, endpoint, err := bind.ipv6.ReadFromUDP(buff) return n, (*NativeEndpoint)(endpoint), err } @@ -133,8 +160,14 @@ func (bind *NativeBind) Send(buff []byte, endpoint Endpoint) error { var err error nend := endpoint.(*NativeEndpoint) if nend.IP.To4() != nil { + if bind.ipv4 == nil { + return syscall.EAFNOSUPPORT + } _, err = bind.ipv4.WriteToUDP(buff, (*net.UDPAddr)(nend)) } else { + if bind.ipv6 == nil { + return syscall.EAFNOSUPPORT + } _, err = bind.ipv6.WriteToUDP(buff, (*net.UDPAddr)(nend)) } return err @@ -157,31 +190,29 @@ func (bind *NativeBind) SetMark(mark uint32) error { if fwmarkIoctl == 0 { return nil } - fd4, err1 := bind.ipv4.SyscallConn() - fd6, err2 := bind.ipv6.SyscallConn() - if err1 != nil { - return err1 - } - if err2 != nil { - return err2 - } - err3 := fd4.Control(func(fd uintptr) { - err1 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark)) - }) - err4 := fd6.Control(func(fd uintptr) { - err2 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark)) - }) - if err1 != nil { - return err1 - } - if err2 != nil { - return err2 - } - if err3 != nil { - return err3 - } - if err4 != nil { - return err4 + if bind.ipv4 != nil { + fd, err := bind.ipv4.SyscallConn() + if err != nil { + return err + } + err = fd.Control(func(fd uintptr) { + err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark)) + }) + if err != nil { + return err + } + } + if bind.ipv6 != nil { + fd, err := bind.ipv6.SyscallConn() + if err != nil { + return err + } + err = fd.Control(func(fd uintptr) { + err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark)) + }) + if err != nil { + return err + } } return nil } -- cgit v1.2.3-59-g8ed1b