summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2008-12-27 15:20:28 +0000
committerChristian Pointner <equinox@anytun.org>2008-12-27 15:20:28 +0000
commit3f9fa03e027ef6db9ae7f8f5815a16e6ad6dd66c (patch)
treee98d80378768c33531b1eab71c14a185b940e0b9
parentadded empty tun.c and h (diff)
added first version of tun device (needs furhter testing)
-rw-r--r--src/linux/tun.c156
-rw-r--r--src/tun.h32
-rw-r--r--src/tun_helper.h90
-rw-r--r--src/uanytun.c19
4 files changed, 294 insertions, 3 deletions
diff --git a/src/linux/tun.c b/src/linux/tun.c
index 971f344..005f125 100644
--- a/src/linux/tun.c
+++ b/src/linux/tun.c
@@ -33,3 +33,159 @@
*/
#include "tun.h"
+
+#include "tun_helper.h"
+
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <net/if.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
+#include <linux/if_tun.h>
+#define DEFAULT_DEVICE "/dev/net/tun"
+
+#include "log.h"
+
+void tun_init(tun_device_t** dev, const char* dev_name, const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp)
+{
+ if(!dev) return;
+
+ *dev = malloc(sizeof(tun_device_t));
+ if(!*dev) return;
+
+ tun_conf(*dev, dev_name, dev_type, ifcfg_lp, ifcfg_rnmp, 1400);
+
+ (*dev)->fd_ = open(DEFAULT_DEVICE, O_RDWR);
+ if((*dev)->fd_ < 0) {
+ log_printf(ERR, "can't open device file (%s): %m", DEFAULT_DEVICE);
+ free(*dev);
+ *dev = NULL;
+ return;
+ }
+
+ 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(ERR, "unable to recognize type of device (tun or tap)");
+ free(*dev);
+ *dev = NULL;
+ return;
+ }
+
+ if(dev_name)
+ strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
+
+ 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(ERR, "tun/tap device ioctl failed: %m");
+ free(*dev);
+ *dev = NULL;
+ return;
+ }
+
+ if(ifcfg_lp && ifcfg_rnmp)
+ tun_do_ifconfig(*dev);
+}
+
+void tun_init_post(tun_device_t* dev)
+{
+// nothing yet
+}
+
+void tun_close(tun_device_t** dev)
+{
+ if(!dev || !(*dev))
+ return;
+
+ if((*dev)->fd_ > 0)
+ close((*dev)->fd_);
+
+ free(*dev);
+ *dev = NULL;
+}
+
+int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+ if(!dev || dev->fd_ < 0)
+ return -1;
+
+ if(dev->with_pi_)
+ {
+ struct iovec iov[2];
+ struct tun_pi tpi;
+
+ iov[0].iov_base = &tpi;
+ iov[0].iov_len = sizeof(tpi);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+ return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(tpi)));
+ }
+ else
+ return(read(dev->fd_, buf, len));
+}
+
+int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
+{
+ if(!dev || dev->fd_ < 0)
+ return -1;
+
+ if(dev->with_pi_)
+ {
+ 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;
+ iov[1].iov_len = len;
+ return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(tpi)));
+ }
+ else
+ return(write(dev->fd_, buf, len));
+}
+
+void tun_do_ifconfig(tun_device_t* dev)
+{
+ if(!dev)
+ return;
+
+ char* command = NULL;
+ if(dev->type_ == TYPE_TUN)
+ asprintf(&command, "/sbin/ifconfig %s %s pointopoint %s mtu %d" , dev->actual_name_, dev->local_, dev->remote_netmask_, dev->mtu_);
+ else
+ asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d" , dev->actual_name_, dev->local_, dev->remote_netmask_, dev->mtu_);
+
+ if(!command) {
+ log_printf(ERR, "Execution of ifconfig failed");
+ return;
+ }
+
+ int result = system(command);
+ if(result == -1)
+ log_printf(ERR, "Execution of ifconfig failed");
+ else
+ log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));
+}
diff --git a/src/tun.h b/src/tun.h
index 24bde6a..5b42f61 100644
--- a/src/tun.h
+++ b/src/tun.h
@@ -35,6 +35,38 @@
#ifndef _TUN_H_
#define _TUN_H_
+#include <stdlib.h>
+typedef unsigned char u_int8_t;
+typedef unsigned short int u_int16_t;
+typedef unsigned int u_int32_t;
+
+
+enum device_type_enum { TYPE_UNDEF, TYPE_TUN, TYPE_TAP };
+typedef enum device_type_enum device_type_t;
+
+struct tun_device_struct {
+ int fd_;
+ unsigned int with_pi_;
+ char* actual_name_;
+ device_type_t type_;
+ u_int16_t mtu_;
+ char* local_;
+ char* remote_netmask_;
+};
+typedef struct tun_device_struct tun_device_t;
+
+void tun_init(tun_device_t** dev, const char* dev_name, const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp);
+void tun_init_post(tun_device_t* dev);
+void tun_do_ifconfig(tun_device_t* dev);
+void tun_close(tun_device_t** dev);
+
+int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len);
+int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len);
+
+// in tun_helper.h
+void tun_conf(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp, u_int16_t mtu);
+int tun_fix_return(int ret, size_t pi_length);
+const char* tun_get_type_string(tun_device_t* dev);
#endif
diff --git a/src/tun_helper.h b/src/tun_helper.h
new file mode 100644
index 0000000..c403f28
--- /dev/null
+++ b/src/tun_helper.h
@@ -0,0 +1,90 @@
+/*
+ * ľAnytun
+ *
+ * ľAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ * featured implementation ľAnytun has no support for multiple connections
+ * or synchronisation. It is a small single threaded implementation intended
+ * to act as a client on small platforms.
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * 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
+ * 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>
+ *
+ * This file is part of ľAnytun.
+ *
+ * ľAnytun 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.
+ *
+ * ľAnytun is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ľAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TUN_HELPER_H_
+#define _TUN_HELPER_H_
+
+#include <string.h>
+
+void tun_conf(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp, u_int16_t mtu)
+{
+ if(!dev) return;
+
+ dev->mtu_ = mtu;
+ dev->type_ = TYPE_UNDEF;
+ if(dev_type) {
+ if(!strncmp(dev_type, "tun", 3))
+ dev->type_ = TYPE_TUN;
+ else if (!strncmp(dev_type, "tap", 3))
+ dev->type_ = TYPE_TAP;
+ }
+ else if(dev_name) {
+ if(!strncmp(dev_name, "tun", 3))
+ dev->type_ = TYPE_TUN;
+ else if(!strncmp(dev_name, "tap", 3))
+ dev->type_ = TYPE_TAP;
+ }
+
+ if(ifcfg_lp)
+ dev->local_ = strdup(ifcfg_lp);
+ if(ifcfg_rnmp)
+ dev->remote_netmask_ = strdup(ifcfg_rnmp);
+}
+
+
+int tun_fix_return(int ret, size_t pi_length)
+{
+ if(ret < 0)
+ return ret;
+
+ return ((size_t)ret > pi_length ? (ret - pi_length) : 0);
+}
+
+const char* tun_get_type_string(tun_device_t* dev)
+{
+ if(!dev || dev->fd_ < 0)
+ return "";
+
+ switch(dev->type_)
+ {
+ case TYPE_UNDEF: return "undef"; break;
+ case TYPE_TUN: return "tun"; break;
+ case TYPE_TAP: return "tap"; break;
+ }
+ return "";
+}
+
+
+
+#endif
diff --git a/src/uanytun.c b/src/uanytun.c
index 162ad5d..82085b4 100644
--- a/src/uanytun.c
+++ b/src/uanytun.c
@@ -47,11 +47,24 @@ int main(int argc, char* argv[])
signal_init();
// chrootAndDrop("/var/run/", "nobody");
- daemonize();
- log_printf(INFO, "running in background now");
+// daemonize();
+// log_printf(INFO, "running in background now");
+
+ tun_device_t* dev;
+ tun_init(&dev, "tun0", "tun", "192.168.23.1", "192.168.23.2");
+ if(!dev) {
+ log_printf(ERR, "error on tun_init");
+ exit -1;
+ }
+
log_printf(INFO, "entering main loop");
- while(1) sleep(1);
+ u_int8_t buf[1600];
+ int len = 0;
+ while(1) {
+ len = tun_read(dev, buf, 1600);
+ printf("read %d bytes from device\n", len);
+ }
}