From fa37039c3bbadf902cef87ae92c9c624f0991942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=BC=C3=9F?= Date: Tue, 13 Feb 2018 16:43:07 +0100 Subject: [PATCH] Reimplemented bind_rtmgrp in pure Go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Getting rid of the Cgo dependency for listing on netlink. Ported original patch from "syscall" to "golang.org/x/sys/unix". Signed-off-by: Dominik Süß Co-Authored-By: Mathias Hall-Andersen --- tun_linux.go | 70 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/tun_linux.go b/tun_linux.go index daa2462..b35e08d 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -16,38 +16,9 @@ import ( "unsafe" ) -// #include -// #include -// #include -// #include -// #include -// #include -// -// /* Creates a netlink socket -// * listening to the RTMGRP_LINK multicast group -// */ -// -// int bind_rtmgrp() { -// int nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); -// if (nl_sock < 0) -// return -1; -// -// struct sockaddr_nl addr; -// memset ((void *) &addr, 0, sizeof (addr)); -// addr.nl_family = AF_NETLINK; -// addr.nl_pid = getpid (); -// addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; -// -// if (bind(nl_sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) -// return -1; -// -// return nl_sock; -// } -import "C" - const ( - CloneDevicePath = "/dev/net/tun" - IFReqSize = unix.IFNAMSIZ + 64 + cloneDevicePath = "/dev/net/tun" + ifReqSize = unix.IFNAMSIZ + 64 ) type NativeTun struct { @@ -58,6 +29,26 @@ type NativeTun struct { events chan TUNEvent // device related events } +func toRTMGRP(sc uint) uint { + return 1 << (sc - 1) +} + +func (tun *NativeTun) bindRTMGRP() (int, error) { + groups := toRTMGRP(unix.RTNLGRP_LINK) + groups |= toRTMGRP(unix.RTNLGRP_IPV4_IFADDR) + groups |= toRTMGRP(unix.RTNLGRP_IPV6_IFADDR) + sock, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_ROUTE) + if err != nil { + return 0, err + } + saddr := &unix.SockaddrNetlink{ + Family: unix.AF_NETLINK, + Pid: uint32(os.Getpid()), + Groups: uint32(groups), + } + return sock, unix.Bind(sock, saddr) +} + func (tun *NativeTun) File() *os.File { return tun.fd } @@ -81,9 +72,8 @@ func (tun *NativeTun) RoutineHackListener() { } func (tun *NativeTun) RoutineNetlinkListener() { - - sock := int(C.bind_rtmgrp()) - if sock < 0 { + sock, err := tun.bindRTMGRP() + if err != nil { tun.errors <- errors.New("Failed to create netlink event listener") return } @@ -159,7 +149,7 @@ func getIFIndex(name string) (int32, error) { defer unix.Close(fd) - var ifr [IFReqSize]byte + var ifr [ifReqSize]byte copy(ifr[:], name) _, _, errno := unix.Syscall( unix.SYS_IOCTL, @@ -194,7 +184,7 @@ func (tun *NativeTun) setMTU(n int) error { // do ioctl call - var ifr [IFReqSize]byte + var ifr [ifReqSize]byte copy(ifr[:], tun.name) binary.LittleEndian.PutUint32(ifr[16:20], uint32(n)) _, _, errno := unix.Syscall( @@ -229,7 +219,7 @@ func (tun *NativeTun) MTU() (int, error) { // do ioctl call - var ifr [IFReqSize]byte + var ifr [ifReqSize]byte copy(ifr[:], tun.name) _, _, errno := unix.Syscall( unix.SYS_IOCTL, @@ -324,15 +314,15 @@ func CreateTUN(name string) (TUNDevice, error) { // open clone device - fd, err := os.OpenFile(CloneDevicePath, os.O_RDWR, 0) + fd, err := os.OpenFile(cloneDevicePath, os.O_RDWR, 0) if err != nil { return nil, err } // create new device - var ifr [IFReqSize]byte - var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI + var ifr [ifReqSize]byte + var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI (disabled for TUN status hack) nameBytes := []byte(name) if len(nameBytes) >= unix.IFNAMSIZ { return nil, errors.New("Interface name too long")