Support IPv6-less kernels
This commit is contained in:
parent
0ba551807f
commit
6a5d0e2bcd
|
@ -11,7 +11,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* This code is meant to be a temporary solution
|
/* 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
|
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) {
|
func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||||
var err error
|
var err error
|
||||||
var bind NativeBind
|
var bind NativeBind
|
||||||
|
@ -94,13 +108,15 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||||
port := int(uport)
|
port := int(uport)
|
||||||
|
|
||||||
bind.ipv4, port, err = listenNet("udp4", port)
|
bind.ipv4, port, err = listenNet("udp4", port)
|
||||||
if err != nil {
|
if err != nil && extractErrno(err) != syscall.EAFNOSUPPORT {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bind.ipv6, port, err = listenNet("udp6", port)
|
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.Close()
|
||||||
|
bind.ipv4 = nil
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +124,13 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bind *NativeBind) Close() error {
|
func (bind *NativeBind) Close() error {
|
||||||
err1 := bind.ipv4.Close()
|
var err1, err2 error
|
||||||
err2 := bind.ipv6.Close()
|
if bind.ipv4 != nil {
|
||||||
|
err1 = bind.ipv4.Close()
|
||||||
|
}
|
||||||
|
if bind.ipv6 != nil {
|
||||||
|
err2 = bind.ipv6.Close()
|
||||||
|
}
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
@ -117,6 +138,9 @@ func (bind *NativeBind) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, 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)
|
n, endpoint, err := bind.ipv4.ReadFromUDP(buff)
|
||||||
if endpoint != nil {
|
if endpoint != nil {
|
||||||
endpoint.IP = endpoint.IP.To4()
|
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) {
|
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)
|
n, endpoint, err := bind.ipv6.ReadFromUDP(buff)
|
||||||
return n, (*NativeEndpoint)(endpoint), err
|
return n, (*NativeEndpoint)(endpoint), err
|
||||||
}
|
}
|
||||||
|
@ -133,8 +160,14 @@ func (bind *NativeBind) Send(buff []byte, endpoint Endpoint) error {
|
||||||
var err error
|
var err error
|
||||||
nend := endpoint.(*NativeEndpoint)
|
nend := endpoint.(*NativeEndpoint)
|
||||||
if nend.IP.To4() != nil {
|
if nend.IP.To4() != nil {
|
||||||
|
if bind.ipv4 == nil {
|
||||||
|
return syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
_, err = bind.ipv4.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
_, err = bind.ipv4.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
||||||
} else {
|
} else {
|
||||||
|
if bind.ipv6 == nil {
|
||||||
|
return syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
_, err = bind.ipv6.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
_, err = bind.ipv6.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -157,31 +190,29 @@ func (bind *NativeBind) SetMark(mark uint32) error {
|
||||||
if fwmarkIoctl == 0 {
|
if fwmarkIoctl == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fd4, err1 := bind.ipv4.SyscallConn()
|
if bind.ipv4 != nil {
|
||||||
fd6, err2 := bind.ipv6.SyscallConn()
|
fd, err := bind.ipv4.SyscallConn()
|
||||||
if err1 != nil {
|
if err != nil {
|
||||||
return err1
|
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 err2 != nil {
|
if bind.ipv6 != nil {
|
||||||
return err2
|
fd, err := bind.ipv6.SyscallConn()
|
||||||
}
|
if err != nil {
|
||||||
err3 := fd4.Control(func(fd uintptr) {
|
return err
|
||||||
err1 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
}
|
||||||
})
|
err = fd.Control(func(fd uintptr) {
|
||||||
err4 := fd6.Control(func(fd uintptr) {
|
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
||||||
err2 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
})
|
||||||
})
|
if err != nil {
|
||||||
if err1 != nil {
|
return err
|
||||||
return err1
|
}
|
||||||
}
|
|
||||||
if err2 != nil {
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
if err3 != nil {
|
|
||||||
return err3
|
|
||||||
}
|
|
||||||
if err4 != nil {
|
|
||||||
return err4
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -140,40 +141,45 @@ func CreateBind(port uint16, device *Device) (*NativeBind, uint16, error) {
|
||||||
go bind.routineRouteListener(device)
|
go bind.routineRouteListener(device)
|
||||||
|
|
||||||
bind.sock6, port, err = create6(port)
|
bind.sock6, port, err = create6(port)
|
||||||
if err != nil {
|
if err != nil && err != syscall.EAFNOSUPPORT {
|
||||||
bind.netlinkCancel.Cancel()
|
bind.netlinkCancel.Cancel()
|
||||||
return nil, port, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bind.sock4, port, err = create4(port)
|
bind.sock4, port, err = create4(port)
|
||||||
if err != nil {
|
if err != nil && err != syscall.EAFNOSUPPORT {
|
||||||
bind.netlinkCancel.Cancel()
|
bind.netlinkCancel.Cancel()
|
||||||
unix.Close(bind.sock6)
|
unix.Close(bind.sock6)
|
||||||
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
return &bind, port, err
|
return &bind, port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bind *NativeBind) SetMark(value uint32) error {
|
func (bind *NativeBind) SetMark(value uint32) error {
|
||||||
err := unix.SetsockoptInt(
|
if bind.sock6 != -1 {
|
||||||
bind.sock6,
|
err := unix.SetsockoptInt(
|
||||||
unix.SOL_SOCKET,
|
bind.sock6,
|
||||||
unix.SO_MARK,
|
unix.SOL_SOCKET,
|
||||||
int(value),
|
unix.SO_MARK,
|
||||||
)
|
int(value),
|
||||||
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = unix.SetsockoptInt(
|
if bind.sock4 != -1 {
|
||||||
bind.sock4,
|
err := unix.SetsockoptInt(
|
||||||
unix.SOL_SOCKET,
|
bind.sock4,
|
||||||
unix.SO_MARK,
|
unix.SOL_SOCKET,
|
||||||
int(value),
|
unix.SO_MARK,
|
||||||
)
|
int(value),
|
||||||
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bind.lastMark = value
|
bind.lastMark = value
|
||||||
|
@ -187,9 +193,14 @@ func closeUnblock(fd int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bind *NativeBind) Close() error {
|
func (bind *NativeBind) Close() error {
|
||||||
err1 := closeUnblock(bind.sock6)
|
var err1, err2, err3 error
|
||||||
err2 := closeUnblock(bind.sock4)
|
if bind.sock6 != -1 {
|
||||||
err3 := bind.netlinkCancel.Cancel()
|
err1 = closeUnblock(bind.sock6)
|
||||||
|
}
|
||||||
|
if bind.sock4 != -1 {
|
||||||
|
err2 = closeUnblock(bind.sock4)
|
||||||
|
}
|
||||||
|
err3 = bind.netlinkCancel.Cancel()
|
||||||
|
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return err1
|
return err1
|
||||||
|
@ -202,6 +213,9 @@ func (bind *NativeBind) Close() error {
|
||||||
|
|
||||||
func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
||||||
var end NativeEndpoint
|
var end NativeEndpoint
|
||||||
|
if bind.sock6 == -1 {
|
||||||
|
return 0, nil, syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
n, err := receive6(
|
n, err := receive6(
|
||||||
bind.sock6,
|
bind.sock6,
|
||||||
buff,
|
buff,
|
||||||
|
@ -212,6 +226,9 @@ func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
||||||
|
|
||||||
func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||||
var end NativeEndpoint
|
var end NativeEndpoint
|
||||||
|
if bind.sock4 == -1 {
|
||||||
|
return 0, nil, syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
n, err := receive4(
|
n, err := receive4(
|
||||||
bind.sock4,
|
bind.sock4,
|
||||||
buff,
|
buff,
|
||||||
|
@ -223,8 +240,14 @@ func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||||
func (bind *NativeBind) Send(buff []byte, end Endpoint) error {
|
func (bind *NativeBind) Send(buff []byte, end Endpoint) error {
|
||||||
nend := end.(*NativeEndpoint)
|
nend := end.(*NativeEndpoint)
|
||||||
if !nend.isV6 {
|
if !nend.isV6 {
|
||||||
|
if bind.sock4 == -1 {
|
||||||
|
return syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
return send4(bind.sock4, nend, buff)
|
return send4(bind.sock4, nend, buff)
|
||||||
} else {
|
} else {
|
||||||
|
if bind.sock6 == -1 {
|
||||||
|
return syscall.EAFNOSUPPORT
|
||||||
|
}
|
||||||
return send6(bind.sock6, nend, buff)
|
return send6(bind.sock6, nend, buff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue