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.
This commit is contained in:
Noel Cower 2019-12-11 17:51:55 -08:00 committed by Nathan Brown
parent a086d60edc
commit cbf8319eb2
3 changed files with 57 additions and 47 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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 {