From 6868ed9ccd918ef642df5d8f6a50eb7f53b1ae86 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Sun, 22 Sep 2019 19:45:51 +0200 Subject: [PATCH] Ensure that the TAP interface is up and running --- edge.c | 2 +- tuntap_linux.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/edge.c b/edge.c index 6d786ef..ac0b0b9 100644 --- a/edge.c +++ b/edge.c @@ -707,7 +707,7 @@ int main(int argc, char* argv[]) { #ifndef WIN32 if((ec.userid != 0) || (ec.groupid != 0)) { - traceEvent(TRACE_NORMAL, "Interface up. Dropping privileges to uid=%d, gid=%d", + traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d", (signed int)ec.userid, (signed int)ec.groupid); /* Finished with the need for root privileges. Drop to unprivileged user. */ diff --git a/tuntap_linux.c b/tuntap_linux.c index 66ea454..740c289 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -21,6 +21,8 @@ #ifdef __linux__ #include +#include +#include /* *************************************************** */ @@ -138,6 +140,12 @@ int tuntap_open(tuntap_dev *device, int ioctl_fd; struct ifreq ifr; int rc; + int nl_fd; + char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */ + struct iovec iov; + struct sockaddr_nl sa; + int up_and_running = 0; + struct msghdr msg; device->fd = open(tuntap_device, O_RDWR); if(device->fd < 0) { @@ -160,12 +168,38 @@ int tuntap_open(tuntap_dev *device, /* Store the device name for later reuse */ strncpy(device->dev_name, ifr.ifr_name, MIN(IFNAMSIZ, N2N_IFNAMSIZ) ); + if((nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { + traceEvent(TRACE_ERROR, "netlink socket creation failed [%d]: %s", errno, strerror(errno)); + return -1; + } + + iov.iov_base = nl_buf; + iov.iov_len = sizeof(nl_buf); + + memset(&sa, 0, sizeof(sa)); + sa.nl_family = PF_NETLINK; + sa.nl_groups = RTMGRP_LINK; + sa.nl_pid = getpid(); + + msg.msg_name = &sa; + msg.msg_namelen = sizeof(sa); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + /* Subscribe to interface events */ + if(bind(nl_fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { + traceEvent(TRACE_ERROR, "netlink socket bind failed [%d]: %s", errno, strerror(errno)); + return -1; + } + if((ioctl_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { traceEvent(TRACE_ERROR, "socket creation failed [%d]: %s", errno, strerror(errno)); + close(nl_fd); return -1; } if(setup_ifname(ioctl_fd, device->dev_name, device_ip, device_mask, device_mac, mtu) < 0) { + close(nl_fd); close(ioctl_fd); close(device->fd); return -1; @@ -173,6 +207,37 @@ int tuntap_open(tuntap_dev *device, close(ioctl_fd); + /* Wait for the up and running notification */ + traceEvent(TRACE_INFO, "Waiting for TAP interface to be up and running..."); + + while(!up_and_running) { + ssize_t len = recvmsg(nl_fd, &msg, 0); + struct nlmsghdr *nh; + + for(nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { + if(nh->nlmsg_type == NLMSG_ERROR) { + traceEvent(TRACE_DEBUG, "nh->nlmsg_type == NLMSG_ERROR"); + break; + } + + if(nh->nlmsg_type == NLMSG_DONE) + break; + + if(nh->nlmsg_type == NETLINK_GENERIC) { + struct ifinfomsg *ifi = NLMSG_DATA(nh); + + /* NOTE: skipping interface name check, assuming it's our TAP */ + if((ifi->ifi_flags & IFF_UP) && (ifi->ifi_flags & IFF_RUNNING)) { + up_and_running = 1; + traceEvent(TRACE_INFO, "Interface is up and running"); + break; + } + } + } + } + + close(nl_fd); + device->ip_addr = inet_addr(device_ip); device->device_mask = inet_addr(device_mask); read_mac(dev, device->mac_addr);