4 * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5 * featured implementation uAnytun has no support for multiple connections
6 * or synchronisation. It is a small single threaded implementation intended
7 * to act as a client on small platforms.
8 * The secure anycast tunneling protocol (satp) defines a protocol used
9 * for communication between any combination of unicast and anycast
10 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
11 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
12 * ethernet, ip, arp ...). satp directly includes cryptography and
13 * message authentication based on the methodes used by SRTP. It is
14 * intended to deliver a generic, scaleable and secure solution for
15 * tunneling and relaying of packets of any protocol.
18 * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
20 * This file is part of uAnytun.
22 * uAnytun is free software: you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License version 3 as
24 * published by the Free Software Foundation.
26 * uAnytun is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
35 #include "datatypes.h"
39 #include "tun_helper.h"
47 #include <sys/socket.h>
49 #include <net/if_tun.h>
50 #include <sys/ioctl.h>
51 #include <sys/types.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/in.h>
55 #include <netinet/ip.h>
56 #define DEVICE_FILE_MAX 255
58 int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix)
63 tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400);
64 dev->actual_name_ = NULL;
66 char* device_file = NULL;
67 char* actual_name_start = NULL;
70 asprintf(&device_file, "/dev/%s", dev_name);
73 #if defined(__GNUC__) && defined(__OpenBSD__)
74 else if(dev->type_ == TYPE_TUN || dev->type_ == TYPE_TAP) {
75 asprintf(&device_file, "/dev/tun");
76 actual_name_start = "tun";
79 else if(dev->type_ == TYPE_TUN) {
80 asprintf(&device_file, "/dev/tun");
81 actual_name_start = "tun";
83 else if(dev->type_ == TYPE_TAP) {
84 asprintf(&device_file, "/dev/tap");
85 actual_name_start = "tap";
89 log_printf(ERROR, "unable to recognize type of device (tun or tap)");
94 log_printf(ERROR, "can't open device file: memory error");
101 for(; dev_id <= DEVICE_FILE_MAX; ++dev_id) {
102 char* device_file_tmp = NULL;
103 asprintf(&device_file_tmp, "%s%d", device_file, dev_id);
105 if(!device_file_tmp) {
106 log_printf(ERROR, "can't open device file: memory error");
112 dev->fd_ = open(device_file_tmp, O_RDWR);
113 free(device_file_tmp);
119 dev->fd_ = open(device_file, O_RDWR);
124 log_printf(ERROR, "can't open device file dynamically: no unused node left");
126 log_printf(ERROR, "can't open device file (%s): %s", device_file, strerror(errno));
133 asprintf(&(dev->actual_name_), "%s%d", actual_name_start, dev_id);
135 dev->actual_name_ = strdup(dev_name);
137 if(!dev->actual_name_) {
138 log_printf(ERROR, "can't open device file: memory error");
143 int ret = tun_init_post(dev);
150 tun_do_ifconfig(dev);
156 #if defined(__GNUC__) && defined(__OpenBSD__)
158 int tun_init_post(tun_device_t* dev)
164 if(dev->type_ == TYPE_TAP)
169 if(ioctl(dev->fd_, TUNGIFINFO, &ti) < 0) {
170 log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
174 ti.flags |= IFF_MULTICAST;
175 if(dev->type_ == TYPE_TUN)
176 ti.flags &= ~IFF_POINTOPOINT;
178 if(ioctl(dev->fd_, TUNSIFINFO, &ti) < 0) {
179 log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
185 #elif defined(__GNUC__) && defined(__FreeBSD__)
187 int tun_init_post(tun_device_t* dev)
193 if(dev->type_ == TYPE_TAP)
196 if(dev->type_ == TYPE_TUN) {
198 if(ioctl(dev->fd_, TUNSLMODE, &arg) < 0) {
199 log_printf(ERROR, "can't disable link-layer mode for interface: %s", strerror(errno));
204 if(ioctl(dev->fd_, TUNSIFHEAD, &arg) < 0) {
205 log_printf(ERROR, "can't enable multi-af mode for interface: %s", strerror(errno));
210 arg |= IFF_MULTICAST;
211 if(ioctl(dev->fd_, TUNSIFMODE, &arg) < 0) {
212 log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno));
220 #elif defined(__GNUC__) && defined(__NetBSD__)
221 #warning this device has never been tested on NetBSD and might not work
222 int tun_init_post(tun_device_t* dev)
229 int arg = IFF_POINTOPOINT|IFF_MULTICAST;
230 ioctl(dev->fd_, TUNSIFMODE, &arg);
232 ioctl(dev->fd_, TUNSLMODE, &arg);
238 #error This Device works just for OpenBSD, FreeBSD or NetBSD
243 void tun_close(tun_device_t* dev)
251 if(dev->actual_name_)
252 free(dev->actual_name_);
255 free(dev->net_addr_);
258 free(dev->net_mask_);
261 int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
263 if(!dev || dev->fd_ < 0)
271 iov[0].iov_base = &type;
272 iov[0].iov_len = sizeof(type);
273 iov[1].iov_base = buf;
274 iov[1].iov_len = len;
275 return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(type)));
278 return(read(dev->fd_, buf, len));
281 int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
283 if(!dev || dev->fd_ < 0)
293 struct ip *hdr = (struct ip*)buf;
297 type = htonl(AF_INET);
299 type = htonl(AF_INET6);
301 iov[0].iov_base = &type;
302 iov[0].iov_len = sizeof(type);
303 iov[1].iov_base = buf;
304 iov[1].iov_len = len;
305 return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(type)));
308 return(write(dev->fd_, buf, len));
311 void tun_do_ifconfig(tun_device_t* dev)
313 if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_)
317 char* command = NULL;
320 if(dev->type_ == TYPE_TAP) {
321 #if defined(__GNUC__) && defined(__OpenBSD__)
323 #elif defined(__GNUC__) && defined(__FreeBSD__)
325 #elif defined(__GNUC__) && defined(__NetBSD__)
328 #error This Device works just for OpenBSD, FreeBSD or NetBSD
334 asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d%s", dev->actual_name_, dev->net_addr_,
335 dev->net_mask_, dev->mtu_, end);
337 log_printf(ERROR, "Execution of ifconfig failed");
341 int result = system(command);
343 log_printf(ERROR, "Execution of ifconfig failed");
345 log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));