diff --git a/app/redirect/getsockopt_linux.go b/app/redirect/getsockopt_linux.go new file mode 100644 index 0000000..33c8cf4 --- /dev/null +++ b/app/redirect/getsockopt_linux.go @@ -0,0 +1,17 @@ +//go:build !386 +// +build !386 + +package redirect + +import ( + "syscall" + "unsafe" +) + +func getsockopt(s uintptr, level uintptr, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { + _, _, e := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, level, name, uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e != 0 { + err = e + } + return +} diff --git a/app/redirect/getsockopt_linux_386.go b/app/redirect/getsockopt_linux_386.go new file mode 100644 index 0000000..de930ec --- /dev/null +++ b/app/redirect/getsockopt_linux_386.go @@ -0,0 +1,22 @@ +package redirect + +import ( + "syscall" + "unsafe" +) + +const ( + SYS_GETSOCKOPT = 15 +) + +// we cannot call socketcall with syscall.Syscall6, it always fails with EFAULT. +// we have to call syscall.socketcall with this trick. +func syscall_socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err syscall.Errno) + +func getsockopt(s uintptr, level uintptr, name uintptr, val unsafe.Pointer, vallen *uint32) (err error) { + _, e := syscall_socketcall(SYS_GETSOCKOPT, s, level, name, uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e != 0 { + err = e + } + return +} diff --git a/app/redirect/origdst_linux.go b/app/redirect/origdst_linux.go index 82edf7b..3907bc7 100644 --- a/app/redirect/origdst_linux.go +++ b/app/redirect/origdst_linux.go @@ -1,6 +1,3 @@ -//go:build !386 -// +build !386 - package redirect import ( @@ -23,13 +20,11 @@ func getOrigDst(fd uintptr) (*sockAddr, error) { var addr sockAddr addrSize := uint32(unsafe.Sizeof(addr)) // try IPv6 first - _, _, err := syscall.Syscall6(syscall.SYS_GETSOCKOPT, fd, syscall.SOL_IPV6, IP6T_SO_ORIGINAL_DST, - uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&addrSize)), 0) - if err != 0 { + err := getsockopt(fd, syscall.SOL_IPV6, IP6T_SO_ORIGINAL_DST, unsafe.Pointer(&addr), &addrSize) + if err != nil { // try IPv4 - _, _, err = syscall.Syscall6(syscall.SYS_GETSOCKOPT, fd, syscall.SOL_IP, SO_ORIGINAL_DST, - uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&addrSize)), 0) - if err != 0 { + err = getsockopt(fd, syscall.SOL_IP, SO_ORIGINAL_DST, unsafe.Pointer(&addr), &addrSize) + if err != nil { // failed return nil, err } diff --git a/app/redirect/origdst_linux_386.go b/app/redirect/origdst_linux_386.go deleted file mode 100644 index 7055bbe..0000000 --- a/app/redirect/origdst_linux_386.go +++ /dev/null @@ -1,36 +0,0 @@ -package redirect - -import ( - "syscall" - "unsafe" -) - -const ( - SYS_GETSOCKOPT = 15 - SO_ORIGINAL_DST = 80 - IP6T_SO_ORIGINAL_DST = 80 -) - -type sockAddr struct { - family uint16 - port [2]byte // big endian regardless of host byte order - data [24]byte // check sockaddr_in or sockaddr_in6 for more information -} - -func getOrigDst(fd uintptr) (*sockAddr, error) { - var addr sockAddr - addrSize := uint32(unsafe.Sizeof(addr)) - // try IPv6 first - _, _, err := syscall.Syscall6(syscall.SYS_SOCKETCALL, SYS_GETSOCKOPT, fd, syscall.SOL_IPV6, IP6T_SO_ORIGINAL_DST, - uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&addrSize))) - if err != 0 { - // try IPv4 - _, _, err = syscall.Syscall6(syscall.SYS_SOCKETCALL, SYS_GETSOCKOPT, fd, syscall.SOL_IP, SO_ORIGINAL_DST, - uintptr(unsafe.Pointer(&addr)), uintptr(unsafe.Pointer(&addrSize))) - if err != 0 { - // failed - return nil, err - } - } - return &addr, nil -} diff --git a/app/redirect/syscall_socketcall_linux_386.s b/app/redirect/syscall_socketcall_linux_386.s new file mode 100644 index 0000000..2dab43a --- /dev/null +++ b/app/redirect/syscall_socketcall_linux_386.s @@ -0,0 +1,7 @@ +//go:build gc +// +build gc + +#include "textflag.h" + +TEXT ·syscall_socketcall(SB),NOSPLIT,$0-36 + JMP syscall·socketcall(SB)