From cbf8319eb2555faeec870e01bae00a10c95f5f0a Mon Sep 17 00:00:00 2001 From: Noel Cower Date: Wed, 11 Dec 2019 17:51:55 -0800 Subject: [PATCH] Add linux-386, linux-ppc64le targets (#56) * Use golang.org/x/sys/unix for _linux.go sources To support builds on GOARCH=386 and possibly elsewhere, it's necessary to use the x/sys/unix package instead of the syscall package. This is because the syscall package is frozen and does not support SYS_GETSOCKNAME, SYS_RECVFROM, nor SYS_SENDTO for GOARCH=386. This commit alone doesn't add support for 386 builds, just gets things onto x/sys/unix so that it's possible. The remaining uses of the syscall package relate to signals, which cannot be switched to the x/sys/unix package at this time. Windows support breaks, so they can either continue using the syscall package (it's frozen, this is safe for Go 1.x at minimum), or something can be written to just use both windows- and unix-compatible signals. * Add linux-386, ppc64le targets to Makefile Because 'linux' is linux-amd64 already, just add linux-386 and linux-ppc64le targets to distinguish them. Would rename the linux target but that might break existing uses. --- Makefile | 13 ++++++++++++- tun_linux.go | 39 +++++++++++++++++++-------------------- udp_linux.go | 52 ++++++++++++++++++++++++++-------------------------- 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index e566c7f..fc981b7 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ BUILD_NUMBER ?= dev+$(shell date -u '+%Y%m%d%H%M%S') GO111MODULE = on export GO111MODULE -all: bin-linux bin-arm bin-arm6 bin-arm64 bin-darwin bin-windows bin-mips bin-mipsle bin-mips64 bin-mips64le +all: bin-linux bin-linux-386 bin-linux-ppc64le bin-arm bin-arm6 bin-arm64 bin-darwin bin-windows bin-mips bin-mipsle bin-mips64 bin-mips64le bin: go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ${NEBULA_CMD_PATH} @@ -47,6 +47,15 @@ bin-linux: GOARCH=amd64 GOOS=linux go build -o build/linux/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=amd64 GOOS=linux go build -o build/linux/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert +bin-linux-386: + mkdir -p build/linux-386 + GOARCH=386 GOOS=linux go build -o build/linux-386/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=386 GOOS=linux go build -o build/linux-386/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert + +bin-linux-ppc64le: + mkdir -p build/linux-ppc64le + GOARCH=ppc64le GOOS=linux go build -o build/linux-ppc64le/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=ppc64le GOOS=linux go build -o build/linux-ppc64le/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-mips: mkdir -p build/mips @@ -76,6 +85,8 @@ release: all tar -zcv -C build/darwin/ -f nebula-darwin-amd64.tar.gz nebula nebula-cert tar -zcv -C build/windows/ -f nebula-windows-amd64.tar.gz nebula.exe nebula-cert.exe tar -zcv -C build/linux/ -f nebula-linux-amd64.tar.gz nebula nebula-cert + tar -zcv -C build/linux-386/ -f nebula-linux-386.tar.gz nebula nebula-cert + tar -zcv -C build/linux-ppc64le/ -f nebula-linux-ppc64le.tar.gz nebula nebula-cert tar -zcv -C build/mips/ -f nebula-linux-mips.tar.gz nebula nebula-cert tar -zcv -C build/mipsle/ -f nebula-linux-mipsle.tar.gz nebula nebula-cert tar -zcv -C build/mips64/ -f nebula-linux-mips64.tar.gz nebula nebula-cert diff --git a/tun_linux.go b/tun_linux.go index 1099f5e..f62d6a7 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -6,7 +6,6 @@ import ( "net" "os" "strings" - "syscall" "unsafe" "github.com/vishvananda/netlink" @@ -31,7 +30,7 @@ type ifReq struct { } func ioctl(a1, a2, a3 uintptr) error { - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, a1, a2, a3) + _, _, errno := unix.Syscall(unix.SYS_IOCTL, a1, a2, a3) if errno != 0 { return errno } @@ -59,7 +58,7 @@ const ( type ifreqAddr struct { Name [16]byte - Addr syscall.RawSockaddrInet4 + Addr unix.RawSockaddrInet4 pad [8]byte } @@ -84,7 +83,7 @@ func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, var req ifReq req.Flags = uint16(cIFF_TUN | cIFF_NO_PI) copy(req.Name[:], deviceName) - if err = ioctl(uintptr(fd), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil { + if err = ioctl(uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&req))); err != nil { return } name := strings.Trim(string(req.Name[:]), "\x00") @@ -115,7 +114,7 @@ func (c *Tun) WriteRaw(b []byte) error { var nn int for { max := len(b) - n, err := syscall.Write(c.fd, b[nn:max]) + n, err := unix.Write(c.fd, b[nn:max]) if n > 0 { nn += n } @@ -148,10 +147,10 @@ func (c Tun) Activate() error { copy(addr[:], c.Cidr.IP.To4()) copy(mask[:], c.Cidr.Mask) - s, err := syscall.Socket( - syscall.AF_INET, - syscall.SOCK_DGRAM, - syscall.IPPROTO_IP, + s, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM, + unix.IPPROTO_IP, ) if err != nil { return err @@ -160,44 +159,44 @@ func (c Tun) Activate() error { ifra := ifreqAddr{ Name: devName, - Addr: syscall.RawSockaddrInet4{ - Family: syscall.AF_INET, + Addr: unix.RawSockaddrInet4{ + Family: unix.AF_INET, Addr: addr, }, } // Set the device ip address - if err = ioctl(fd, syscall.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil { + if err = ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil { return fmt.Errorf("failed to set tun address: %s", err) } // Set the device network ifra.Addr.Addr = mask - if err = ioctl(fd, syscall.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil { + if err = ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil { return fmt.Errorf("failed to set tun netmask: %s", err) } // Set the device name ifrf := ifReq{Name: devName} - if err = ioctl(fd, syscall.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { + if err = ioctl(fd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { return fmt.Errorf("failed to set tun device name: %s", err) } // Set the MTU on the device ifm := ifreqMTU{Name: devName, MTU: int32(c.MaxMTU)} - if err = ioctl(fd, syscall.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil { + if err = ioctl(fd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil { return fmt.Errorf("failed to set tun mtu: %s", err) } // Set the transmit queue length ifrq := ifreqQLEN{Name: devName, Value: int32(c.TXQueueLen)} - if err = ioctl(fd, syscall.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil { + if err = ioctl(fd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil { return fmt.Errorf("failed to set tun tx queue length: %s", err) } // Bring up the interface - ifrf.Flags = ifrf.Flags | syscall.IFF_UP - if err = ioctl(fd, syscall.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { + ifrf.Flags = ifrf.Flags | unix.IFF_UP + if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { return fmt.Errorf("failed to bring the tun device up: %s", err) } @@ -240,8 +239,8 @@ func (c Tun) Activate() error { } // Run the interface - ifrf.Flags = ifrf.Flags | syscall.IFF_UP | syscall.IFF_RUNNING - if err = ioctl(fd, syscall.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { + ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING + if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil { return fmt.Errorf("failed to run tun device: %s", err) } diff --git a/udp_linux.go b/udp_linux.go index 2a1b0d0..a9ba64c 100644 --- a/udp_linux.go +++ b/udp_linux.go @@ -55,58 +55,58 @@ var x int func NewListener(ip string, port int, multi bool) (*udpConn, error) { syscall.ForkLock.RLock() - fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP) if err == nil { - syscall.CloseOnExec(fd) + unix.CloseOnExec(fd) } syscall.ForkLock.RUnlock() if err != nil { - syscall.Close(fd) + unix.Close(fd) return nil, fmt.Errorf("unable to open socket: %s", err) } var lip [4]byte copy(lip[:], net.ParseIP(ip).To4()) - if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { + if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { return nil, fmt.Errorf("unable to set SO_REUSEPORT: %s", err) } - if err = syscall.Bind(fd, &syscall.SockaddrInet4{Port: port}); err != nil { + if err = unix.Bind(fd, &unix.SockaddrInet4{Port: port}); err != nil { return nil, fmt.Errorf("unable to bind to socket: %s", err) } //TODO: this may be useful for forcing threads into specific cores - //syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_INCOMING_CPU, x) - //v, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_INCOMING_CPU) + //unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU, x) + //v, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_INCOMING_CPU) //l.Println(v, err) return &udpConn{sysFd: fd}, err } func (u *udpConn) SetRecvBuffer(n int) error { - return syscall.SetsockoptInt(u.sysFd, syscall.SOL_SOCKET, syscall.SO_RCVBUFFORCE, n) + return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, n) } func (u *udpConn) SetSendBuffer(n int) error { - return syscall.SetsockoptInt(u.sysFd, syscall.SOL_SOCKET, syscall.SO_SNDBUFFORCE, n) + return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, n) } func (u *udpConn) GetRecvBuffer() (int, error) { - return syscall.GetsockoptInt(int(u.sysFd), syscall.SOL_SOCKET, syscall.SO_RCVBUF) + return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_RCVBUF) } func (u *udpConn) GetSendBuffer() (int, error) { - return syscall.GetsockoptInt(int(u.sysFd), syscall.SOL_SOCKET, syscall.SO_SNDBUF) + return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_SNDBUF) } func (u *udpConn) LocalAddr() (*udpAddr, error) { var rsa rawSockaddrAny - var rLen = syscall.SizeofSockaddrAny + var rLen = unix.SizeofSockaddrAny - _, _, err := syscall.Syscall( - syscall.SYS_GETSOCKNAME, + _, _, err := unix.Syscall( + unix.SYS_GETSOCKNAME, uintptr(u.sysFd), uintptr(unsafe.Pointer(&rsa)), uintptr(unsafe.Pointer(&rLen)), @@ -117,7 +117,7 @@ func (u *udpConn) LocalAddr() (*udpAddr, error) { } addr := &udpAddr{} - if rsa.Addr.Family == syscall.AF_INET { + if rsa.Addr.Family == unix.AF_INET { addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1]) addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5]) } else { @@ -157,11 +157,11 @@ func (u *udpConn) ListenOut(f *Interface) { func (u *udpConn) Read(addr *udpAddr, b []byte) ([]byte, error) { var rsa rawSockaddrAny - var rLen = syscall.SizeofSockaddrAny + var rLen = unix.SizeofSockaddrAny for { - n, _, err := syscall.Syscall6( - syscall.SYS_RECVFROM, + n, _, err := unix.Syscall6( + unix.SYS_RECVFROM, uintptr(u.sysFd), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), @@ -174,7 +174,7 @@ func (u *udpConn) Read(addr *udpAddr, b []byte) ([]byte, error) { return nil, &net.OpError{Op: "read", Err: err} } - if rsa.Addr.Family == syscall.AF_INET { + if rsa.Addr.Family == unix.AF_INET { addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1]) addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5]) } else { @@ -188,8 +188,8 @@ func (u *udpConn) Read(addr *udpAddr, b []byte) ([]byte, error) { func (u *udpConn) ReadMulti(msgs []rawMessage) (int, error) { for { - n, _, err := syscall.Syscall6( - syscall.SYS_RECVMMSG, + n, _, err := unix.Syscall6( + unix.SYS_RECVMMSG, uintptr(u.sysFd), uintptr(unsafe.Pointer(&msgs[0])), uintptr(len(msgs)), @@ -207,10 +207,10 @@ func (u *udpConn) ReadMulti(msgs []rawMessage) (int, error) { } func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error { - var rsa syscall.RawSockaddrInet4 + var rsa unix.RawSockaddrInet4 //TODO: sometimes addr is nil! - rsa.Family = syscall.AF_INET + rsa.Family = unix.AF_INET p := (*[2]byte)(unsafe.Pointer(&rsa.Port)) p[0] = byte(addr.Port >> 8) p[1] = byte(addr.Port) @@ -221,14 +221,14 @@ func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error { rsa.Addr[3] = byte(addr.IP & 0x000000ff) for { - _, _, err := syscall.Syscall6( - syscall.SYS_SENDTO, + _, _, err := unix.Syscall6( + unix.SYS_SENDTO, uintptr(u.sysFd), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(0), uintptr(unsafe.Pointer(&rsa)), - uintptr(syscall.SizeofSockaddrInet4), + uintptr(unix.SizeofSockaddrInet4), ) if err != 0 {