From 92261b770fdf745b6437a4f24482d19a480a00eb Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 27 Apr 2018 02:23:48 +0200 Subject: [PATCH] Fix error handling and cleanup of netlink listener --- tun_linux.go | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tun_linux.go b/tun_linux.go index 1abc86f..0672b5e 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -36,31 +36,15 @@ type NativeTun struct { closingWriter *os.File } -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 } func (tun *NativeTun) RoutineHackListener() { + // TODO: This function never actually exits in response to anything, + // a go routine that goes forever. We'll want to fix that if this is + // to ever be used as any sort of library. + /* This is needed for the detection to work across network namespaces * If you are reading this and know a better method, please get in touch. */ @@ -78,12 +62,35 @@ func (tun *NativeTun) RoutineHackListener() { } } +func toRTMGRP(sc uint) uint { + return 1 << (sc - 1) +} + func (tun *NativeTun) RoutineNetlinkListener() { - sock, err := tun.bindRTMGRP() + + 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 { - tun.errors <- errors.New("Failed to create netlink event listener") + tun.errors <- errors.New("Failed to create netlink event listener socket") return } + defer unix.Close(sock) + saddr := &unix.SockaddrNetlink{ + Family: unix.AF_NETLINK, + Pid: uint32(os.Getpid()), + Groups: uint32(groups), + } + err = unix.Bind(sock, saddr) + if err != nil { + tun.errors <- errors.New("Failed to bind netlink event listener socket") + return + } + + // TODO: This function never actually exits in response to anything, + // a go routine that goes forever. We'll want to fix that if this is + // to ever be used as any sort of library. for msg := make([]byte, 1<<16); ; {