aboutsummaryrefslogtreecommitdiffstats
path: root/conn_default.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-06-11 19:04:38 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-06-12 01:32:46 +0200
commit6a5d0e2bcd1fe64b48ac462ffff0a31154f1050f (patch)
tree73b2538633fe8cdbaf7b8136522a53e1c4536ea4 /conn_default.go
parentDo not build tun device on ios (diff)
downloadwireguard-go-6a5d0e2bcd1fe64b48ac462ffff0a31154f1050f.tar.xz
wireguard-go-6a5d0e2bcd1fe64b48ac462ffff0a31154f1050f.zip
Support IPv6-less kernels
Diffstat (limited to '')
-rw-r--r--conn_default.go89
1 files changed, 60 insertions, 29 deletions
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
}