From ee6e6a63cbf6aae23d317d1331ff0fd582b83138 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 13 Jan 2013 13:57:32 +0100 Subject: [PATCH] set configured addresses to tun device. --- src/main.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/vpn.c | 3 ++ 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/main.c b/src/main.c index 24ea2e0e..2ab1b3fb 100644 --- a/src/main.c +++ b/src/main.c @@ -193,10 +193,103 @@ static void handle_alarm(int signo) need_to_expire_cookies = 1; } -static int open_tun(void) +static int set_network_info(const struct vpn_st* vinfo) { -int tunfd; struct ifreq ifr; +int fd, ret; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return -1; + + /* set netmask */ + if (vinfo->ipv4_netmask && vinfo->ipv4) { + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_addr.sa_family = AF_INET; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); + + ret = inet_pton(AF_INET, vinfo->ipv4_netmask, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr); + if (ret != 1) { + syslog(LOG_ERR, "%s: Error reading mask: %s\n", + vinfo->name, vinfo->ipv4_netmask); + goto fail; + } + + ret = ioctl(fd, SIOCSIFNETMASK, &ifr); + if (ret != 0) { + syslog(LOG_ERR, "%s: Error setting mask: %s\n", + vinfo->name, vinfo->ipv4_netmask); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_addr.sa_family = AF_INET; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); + + ret = inet_pton(AF_INET, vinfo->ipv4, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr); + if (ret != 1) { + syslog(LOG_ERR, "%s: Error reading IP: %s\n", + vinfo->name, vinfo->ipv4_netmask); + goto fail; + + } + + ret = ioctl(fd, SIOCSIFADDR, &ifr); + if (ret != 0) { + syslog(LOG_ERR, "%s: Error setting IP: %s\n", + vinfo->name, vinfo->ipv4); + } + } + + if (vinfo->ipv6_netmask && vinfo->ipv6) { + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_addr.sa_family = AF_INET6; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); + + ret = inet_pton(AF_INET6, vinfo->ipv6_netmask, &((struct sockaddr_in6 *)&ifr.ifr_addr)->sin6_addr); + if (ret != 1) { + syslog(LOG_ERR, "%s: Error reading mask: %s\n", + vinfo->name, vinfo->ipv6_netmask); + goto fail; + + } + + ret = ioctl(fd, SIOCSIFNETMASK, &ifr); + if (ret != 0) { + syslog(LOG_ERR, "%s: Error setting mask: %s\n", + vinfo->name, vinfo->ipv6_netmask); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_addr.sa_family = AF_INET6; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); + + ret = inet_pton(AF_INET6, vinfo->ipv6, &((struct sockaddr_in6 *)&ifr.ifr_addr)->sin6_addr); + if (ret != 1) { + syslog(LOG_ERR, "%s: Error reading IP: %s\n", + vinfo->name, vinfo->ipv6_netmask); + goto fail; + + } + + ret = ioctl(fd, SIOCSIFADDR, &ifr); + if (ret != 0) { + syslog(LOG_ERR, "%s: Error setting IP: %s\n", + vinfo->name, vinfo->ipv6); + } + } + + + ret = 0; +fail: + close(fd); + return ret; +} + +static int open_tun(struct cfg_st *config) +{ +int tunfd, ret; +struct ifreq ifr; +unsigned int i; tunfd = open("/dev/net/tun", O_RDWR); if (tunfd < 0) { @@ -206,13 +299,22 @@ struct ifreq ifr; return -1; } - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "vpns%d", 0); - if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { - int e = errno; - syslog(LOG_ERR, "TUNSETIFF: %s\n", strerror(e)); - exit(1); + for (i=0;inetworks_size;i++) { + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), config->networks[i].name, 0); + if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { + int e = errno; + syslog(LOG_ERR, "TUNSETIFF: %s\n", strerror(e)); + exit(1); + } + + /* set IP/mask */ + ret = set_network_info(&config->networks[i]); + if (ret < 0) { + exit(1); + } + } return tunfd; @@ -280,7 +382,7 @@ int main(void) exit(1); } - tunfd = open_tun(); + tunfd = open_tun(&config); if (tunfd < 0) { exit(1); } diff --git a/src/vpn.c b/src/vpn.c index b525edb9..26a7e0c4 100644 --- a/src/vpn.c +++ b/src/vpn.c @@ -318,6 +318,7 @@ unsigned int i; int ret; /* get netmask */ + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = family; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); @@ -350,6 +351,7 @@ int ret; } /* get IP (and make it network) */ + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = family; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); @@ -429,6 +431,7 @@ const char* p; goto fail; } + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); ret = ioctl(fd, SIOCGIFMTU, (caddr_t)&ifr);