Imported Upstream version 0.3.7
[debian/uanytun.git] / src / linux / tun.c
index c2187a6..11fd209 100644 (file)
  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
  *  ethernet, ip, arp ...). satp directly includes cryptography and
- *  message authentication based on the methodes used by SRTP.  It is
+ *  message authentication based on the methods used by SRTP.  It is
  *  intended to deliver a generic, scaleable and secure solution for
  *  tunneling and relaying of packets of any protocol.
- *  
  *
- *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
  *
  *  This file is part of uAnytun.
  *
  *  uAnytun is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 3 as
- *  published by the Free Software Foundation.
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  any later version.
  *
  *  uAnytun is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  *  You should have received a copy of the GNU General Public License
  *  along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  In addition, as a special exception, the copyright holders give
+ *  permission to link the code of portions of this program with the
+ *  OpenSSL library under certain conditions as described in each
+ *  individual source file, and distribute linked combinations
+ *  including the two.
+ *  You must obey the GNU General Public License in all respects
+ *  for all of the code used other than OpenSSL.  If you modify
+ *  file(s) with this exception, you may extend this exception to your
+ *  version of the file(s), but you are not obligated to do so.  If you
+ *  do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source
+ *  files in the program, then also delete it here.
  */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 
 #include "datatypes.h"
@@ -45,6 +60,7 @@
 #include <sys/wait.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/uio.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #include <net/if.h>
 #define DEFAULT_DEVICE "/dev/net/tun"
 
 #include "log.h"
+#include "sysexec.h"
 
 int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix){
-  if(!dev) 
+  if(!dev)
     return -1;
+
   tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400);
   dev->actual_name_ = NULL;
 
-       dev->fd_ = open(DEFAULT_DEVICE, O_RDWR);
-       if(dev->fd_ < 0) {
+  dev->fd_ = open(DEFAULT_DEVICE, O_RDWR);
+  if(dev->fd_ < 0) {
     log_printf(ERROR, "can't open device file (%s): %s", DEFAULT_DEVICE, strerror(errno));
     tun_close(dev);
     return -1;
   }
 
-       struct ifreq ifr;
-       memset(&ifr, 0, sizeof(ifr));
+  struct ifreq ifr;
+  memset(&ifr, 0, sizeof(ifr));
 
   if(dev->type_ == TYPE_TUN) {
     ifr.ifr_flags = IFF_TUN;
     dev->with_pi_ = 1;
-  } 
+  }
   else if(dev->type_ == TYPE_TAP) {
     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
     dev->with_pi_ = 0;
-  } 
+  }
   else {
     log_printf(ERROR, "unable to recognize type of device (tun or tap)");
     tun_close(dev);
     return -1;
   }
 
-       if(dev_name)
-               strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
+  if(dev_name)
+    strncpy(ifr.ifr_name, dev_name, IFNAMSIZ-1);
 
-       if(!ioctl(dev->fd_, TUNSETIFF, &ifr)) {
-               dev->actual_name_ = strdup(ifr.ifr_name);
-       } else if(!ioctl(dev->fd_, (('T' << 8) | 202), &ifr)) {
-               dev->actual_name_ = strdup(ifr.ifr_name);
-       } else {
+  if(!ioctl(dev->fd_, TUNSETIFF, &ifr)) {
+    dev->actual_name_ = strdup(ifr.ifr_name);
+  } else if(!ioctl(dev->fd_, (('T' << 8) | 202), &ifr)) {
+    dev->actual_name_ = strdup(ifr.ifr_name);
+  } else {
     log_printf(ERROR, "tun/tap device ioctl failed: %s", strerror(errno));
     tun_close(dev);
     return -1;
@@ -114,6 +131,7 @@ int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, cons
 int tun_init_post(tun_device_t* dev)
 {
 // nothing yet
+  return 0;
 }
 
 void tun_close(tun_device_t* dev)
@@ -143,7 +161,7 @@ int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
   {
     struct iovec iov[2];
     struct tun_pi tpi;
-    
+
     iov[0].iov_base = &tpi;
     iov[0].iov_len = sizeof(tpi);
     iov[1].iov_base = buf;
@@ -167,13 +185,13 @@ int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
     struct iovec iov[2];
     struct tun_pi tpi;
     struct iphdr *hdr = (struct iphdr *)buf;
-    
+
     tpi.flags = 0;
     if(hdr->version == 4)
       tpi.proto = htons(ETH_P_IP);
     else
       tpi.proto = htons(ETH_P_IPV6);
-    
+
     iov[0].iov_base = &tpi;
     iov[0].iov_len = sizeof(tpi);
     iov[1].iov_base = buf;
@@ -189,18 +207,16 @@ void tun_do_ifconfig(tun_device_t* dev)
   if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_)
     return;
 
-  char* command = NULL;
-  asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d", dev->actual_name_, dev->net_addr_, dev->net_mask_, dev->mtu_);
-  if(!command) {
+  char* mtu_str = NULL;
+  int len = asprintf(&mtu_str, "%d", dev->mtu_);
+  if(len == -1) {
     log_printf(ERROR, "Execution of ifconfig failed");
     return;
   }
 
-  int result = system(command);
-  if(result == -1)
-    log_printf(ERROR, "Execution of ifconfig failed");
-  else
-    log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));
+  char* const argv[] = { "/sbin/ifconfig", dev->actual_name_, dev->net_addr_, "netmask", dev->net_mask_, "mtu", mtu_str, NULL };
+  char* const evp[] = { NULL };
+  uanytun_exec("/sbin/ifconfig", argv, evp);
 
-  free(command);
+  free(mtu_str);
 }