|
|
@ -21,6 +21,8 @@ |
|
|
|
#ifdef __linux__ |
|
|
|
|
|
|
|
#include <net/if_arp.h> |
|
|
|
#include <linux/netlink.h> |
|
|
|
#include <linux/rtnetlink.h> |
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
@ -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); |
|
|
|