From 3d3e30beb83889fe2508c4da80796abea2500983 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 18 Apr 2021 20:26:32 -0600 Subject: [PATCH] tun: freebsd: remove horrific hack for getting tunnel name As of FreeBSD 12.1, there's TUNGIFNAME. Signed-off-by: Jason A. Donenfeld --- tun/tun_freebsd.go | 97 +++++++--------------------------------------- 1 file changed, 13 insertions(+), 84 deletions(-) diff --git a/tun/tun_freebsd.go b/tun/tun_freebsd.go index 53d1584..e618be3 100644 --- a/tun/tun_freebsd.go +++ b/tun/tun_freebsd.go @@ -6,7 +6,6 @@ package tun import ( - "bytes" "errors" "fmt" "net" @@ -19,12 +18,10 @@ import ( "golang.org/x/sys/unix" ) -// _TUNSIFHEAD, value derived from sys/net/{if_tun,ioccom}.h -// const _TUNSIFHEAD = ((0x80000000) | (((4) & ((1 << 13) - 1) ) << 16) | (uint32(byte('t')) << 8) | (96)) const ( _TUNSIFHEAD = 0x80047460 _TUNSIFMODE = 0x8004745e - _TUNSIFPID = 0x2000745f + _TUNGIFNAME = 0x4020745d ) // TODO: move into x/sys/unix @@ -40,6 +37,12 @@ const _IFSTATMAX = 800 const SIZEOF_UINTPTR = 4 << (^uintptr(0) >> 32 & 1) +// structure for iface requests for just the name +type ifreq_name struct { + Name [unix.IFNAMSIZ]byte + Pad0 [16]byte +} + // structure for iface requests with a pointer type ifreq_ptr struct { Name [unix.IFNAMSIZ]byte @@ -54,12 +57,6 @@ type ifreq_mtu struct { Pad0 [12]byte } -// Structure for interface status request ioctl -type ifstat struct { - IfsName [unix.IFNAMSIZ]byte - Ascii [_IFSTATMAX]byte -} - // Structures for nd6 flag manipulation type in6_ndireq struct { Name [unix.IFNAMSIZ]byte @@ -110,10 +107,10 @@ func (tun *NativeTun) routineRouteListener(tunIfindex int) { continue } - if data[3 /* type */] != unix.RTM_IFINFO { + if data[3 /* type */ ] != unix.RTM_IFINFO { continue } - ifindex := int(*(*uint16)(unsafe.Pointer(&data[12 /* ifindex */]))) + ifindex := int(*(*uint16)(unsafe.Pointer(&data[12 /* ifindex */ ]))) if ifindex != tunIfindex { continue } @@ -143,80 +140,12 @@ func (tun *NativeTun) routineRouteListener(tunIfindex int) { } func tunName(fd uintptr) (string, error) { - // Terrible hack to make up for freebsd not having a TUNGIFNAME - - // First, make sure the tun pid matches this proc's pid - _, _, errno := unix.Syscall( - unix.SYS_IOCTL, - uintptr(fd), - uintptr(_TUNSIFPID), - uintptr(0), - ) - - if errno != 0 { - return "", fmt.Errorf("failed to set tun device PID: %s", errno.Error()) - } - - // Open iface control socket - - confd, err := unix.Socket( - unix.AF_INET, - unix.SOCK_DGRAM, - 0, - ) - - if err != nil { + var ifreq ifreq_name + _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, _TUNGIFNAME, uintptr(unsafe.Pointer(&ifreq))) + if err != 0 { return "", err } - - defer unix.Close(confd) - - procPid := os.Getpid() - - // Try to find interface with matching PID - for i := 1; ; i++ { - iface, _ := net.InterfaceByIndex(i) - if err != nil || iface == nil { - break - } - - // Structs for getting data in and out of SIOCGIFSTATUS ioctl - var ifstatus ifstat - copy(ifstatus.IfsName[:], iface.Name) - - // Make the syscall to get the status string - _, _, errno := unix.Syscall( - unix.SYS_IOCTL, - uintptr(confd), - uintptr(unix.SIOCGIFSTATUS), - uintptr(unsafe.Pointer(&ifstatus)), - ) - - if errno != 0 { - continue - } - - nullStr := ifstatus.Ascii[:] - i := bytes.IndexByte(nullStr, 0) - if i < 1 { - continue - } - statStr := string(nullStr[:i]) - var pidNum int = 0 - - // Finally get the owning PID - // Format string taken from sys/net/if_tun.c - _, err := fmt.Sscanf(statStr, "\tOpened by PID %d\n", &pidNum) - if err != nil { - continue - } - - if pidNum == procPid { - return iface.Name, nil - } - } - - return "", nil + return unix.ByteSliceToString(ifreq.Name[:]), nil } // Destroy a named system interface