c2187a60fd07fac5df8592e9887df6a8ee64a0d9
[debian/uanytun.git] / src / linux / tun.c
1 /*
2  *  uAnytun
3  *
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.
16  *  
17  *
18  *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
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.
25  *
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.
30  *
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/>.
33  */
34
35 #include <stdio.h>
36
37 #include "datatypes.h"
38
39 #include "tun.h"
40
41 #include "tun_helper.h"
42
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <sys/wait.h>
46 #include <fcntl.h>
47 #include <sys/ioctl.h>
48 #include <arpa/inet.h>
49 #include <errno.h>
50 #include <net/if.h>
51 #include <linux/ip.h>
52 #include <linux/if_ether.h>
53 #include <linux/if_tun.h>
54 #define DEFAULT_DEVICE "/dev/net/tun"
55
56 #include "log.h"
57
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){
59   if(!dev) 
60     return -1;
61  
62   tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400);
63   dev->actual_name_ = NULL;
64
65         dev->fd_ = open(DEFAULT_DEVICE, O_RDWR);
66         if(dev->fd_ < 0) {
67     log_printf(ERROR, "can't open device file (%s): %s", DEFAULT_DEVICE, strerror(errno));
68     tun_close(dev);
69     return -1;
70   }
71
72         struct ifreq ifr;
73         memset(&ifr, 0, sizeof(ifr));
74
75   if(dev->type_ == TYPE_TUN) {
76     ifr.ifr_flags = IFF_TUN;
77     dev->with_pi_ = 1;
78   } 
79   else if(dev->type_ == TYPE_TAP) {
80     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
81     dev->with_pi_ = 0;
82   } 
83   else {
84     log_printf(ERROR, "unable to recognize type of device (tun or tap)");
85     tun_close(dev);
86     return -1;
87   }
88
89         if(dev_name)
90                 strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
91
92         if(!ioctl(dev->fd_, TUNSETIFF, &ifr)) {
93                 dev->actual_name_ = strdup(ifr.ifr_name);
94         } else if(!ioctl(dev->fd_, (('T' << 8) | 202), &ifr)) {
95                 dev->actual_name_ = strdup(ifr.ifr_name);
96         } else {
97     log_printf(ERROR, "tun/tap device ioctl failed: %s", strerror(errno));
98     tun_close(dev);
99     return -1;
100   }
101
102   if(!dev->actual_name_) {
103     log_printf(ERROR, "can't open device file: memory error");
104     tun_close(dev);
105     return -2;
106   }
107
108   if(ifcfg_addr)
109     tun_do_ifconfig(dev);
110
111   return 0;
112 }
113
114 int tun_init_post(tun_device_t* dev)
115 {
116 // nothing yet
117 }
118
119 void tun_close(tun_device_t* dev)
120 {
121   if(!dev)
122     return;
123
124   if(dev->fd_ > 0)
125     close(dev->fd_);
126
127   if(dev->actual_name_)
128     free(dev->actual_name_);
129
130   if(dev->net_addr_)
131     free(dev->net_addr_);
132
133   if(dev->net_mask_)
134     free(dev->net_mask_);
135 }
136
137 int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
138 {
139   if(!dev || dev->fd_ < 0)
140     return -1;
141
142   if(dev->with_pi_)
143   {
144     struct iovec iov[2];
145     struct tun_pi tpi;
146     
147     iov[0].iov_base = &tpi;
148     iov[0].iov_len = sizeof(tpi);
149     iov[1].iov_base = buf;
150     iov[1].iov_len = len;
151     return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(tpi)));
152   }
153   else
154     return(read(dev->fd_, buf, len));
155 }
156
157 int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len)
158 {
159   if(!dev || dev->fd_ < 0)
160     return -1;
161
162   if(!buf)
163     return 0;
164
165   if(dev->with_pi_)
166   {
167     struct iovec iov[2];
168     struct tun_pi tpi;
169     struct iphdr *hdr = (struct iphdr *)buf;
170     
171     tpi.flags = 0;
172     if(hdr->version == 4)
173       tpi.proto = htons(ETH_P_IP);
174     else
175       tpi.proto = htons(ETH_P_IPV6);
176     
177     iov[0].iov_base = &tpi;
178     iov[0].iov_len = sizeof(tpi);
179     iov[1].iov_base = buf;
180     iov[1].iov_len = len;
181     return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(tpi)));
182   }
183   else
184     return(write(dev->fd_, buf, len));
185 }
186
187 void tun_do_ifconfig(tun_device_t* dev)
188 {
189   if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_)
190     return;
191
192   char* command = NULL;
193   asprintf(&command, "/sbin/ifconfig %s %s netmask %s mtu %d", dev->actual_name_, dev->net_addr_, dev->net_mask_, dev->mtu_);
194   if(!command) {
195     log_printf(ERROR, "Execution of ifconfig failed");
196     return;
197   }
198
199   int result = system(command);
200   if(result == -1)
201     log_printf(ERROR, "Execution of ifconfig failed");
202   else
203     log_printf(NOTICE, "ifconfig returned %d", WEXITSTATUS(result));
204
205   free(command);
206 }