Added support for BIONIC libc to allow compilation on android toolchain.
[vde.git] / vde-2 / src / vde_switch / tuntap.c
blob59f35019d10ff07f3110a23189c210cbdef94b29
1 /* Copyright 2005 Renzo Davoli - VDE-2
2 * --pidfile/-p and cleanup management by Mattia Belletti (C) 2004.
3 * Licensed under the GPLv2
4 * Modified by Ludovico Gardenghi 2005 (OSX tuntap support)
5 */
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <syslog.h>
13 #include <stdlib.h>
14 #include <libgen.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/ioctl.h>
18 #include <stdarg.h>
19 #define _GNU_SOURCE
20 #include <getopt.h>
22 #include <config.h>
23 #include <vde.h>
24 #include <vdecommon.h>
26 #include "port.h"
27 #include "switch.h"
28 #include "consmgmt.h"
30 #ifdef HAVE_TUNTAP
32 #if defined(VDE_LINUX) || defined(VDE_BIONIC)
33 #include <net/if.h>
34 #include <linux/if_tun.h>
35 #endif
37 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
38 #define TAP_PREFIX "/dev/"
39 #endif
41 #define MAXCMD 128
42 #define MODULENAME "tuntap"
44 static struct swmodule swmi;
45 static struct mod_support modfun;
46 static unsigned int tap_type;
48 struct init_tap {
49 char *tap_dev;
50 struct init_tap *next;
53 struct init_tap *hinit_tap=NULL;
55 static int send_tap(int fd_ctl, int fd_data, void *packet, int len, int port)
57 int n;
59 n = len - write(fd_ctl, packet, len);
60 if(n > len){
61 int rv=errno;
62 if(rv != EAGAIN && rv != EWOULDBLOCK)
63 printlog(LOG_WARNING,"send_tap port %d: %s",port,strerror(errno));
64 else
65 rv=EWOULDBLOCK;
66 return -rv;
68 return n;
71 static void handle_io(unsigned char type,int fd,int revents,void *private_data)
73 struct endpoint *ep=private_data;
74 #ifdef VDE_PQ2
75 if (revents & POLLOUT)
76 handle_out_packet(ep);
77 #endif
78 if (revents & POLLIN) {
79 struct bipacket packet;
80 int len=read(fd, &(packet.p), sizeof(struct packet));
82 if(len < 0){
83 if(errno != EAGAIN && errno != EWOULDBLOCK)
84 printlog(LOG_WARNING,"Reading tap data: %s",strerror(errno));
86 else if(len == 0) {
87 if(errno != EAGAIN && errno != EWOULDBLOCK)
88 printlog(LOG_WARNING,"EOF tap data port: %s",strerror(errno));
89 /* close tap! */
90 } else if (len >= ETH_HEADER_SIZE)
91 handle_in_packet(ep, &(packet.p), len);
95 static void cleanup(unsigned char type,int fd,void *private_data)
97 if (fd >= 0)
98 close(fd);
101 static struct option long_options[] = {
102 {"tap", 1, 0, 't'},
104 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
106 static void usage(void)
108 printf(
109 "(opts from tuntap module)\n"
110 " -t, --tap TAP Enable routing through TAP tap interface\n"
111 #ifdef VDE_DARWIN
112 " TAP can be an absolute file name or a relative\n"
113 " one (and will be prefixed with %s). The TAP\n"
114 " device must already exist.\n", TAP_PREFIX
115 #endif
119 static struct init_tap *add_init_tap(struct init_tap *p,char *arg)
121 if (p == NULL) {
122 p=malloc(sizeof(struct init_tap));
123 if (p==NULL)
124 printlog(LOG_WARNING,"Malloc Tap init:%s\n",strerror(errno));
125 else {
126 p->tap_dev=strdup(optarg);
127 p->next=NULL;
129 } else
130 p->next=add_init_tap(p->next,arg);
131 return(p);
134 static struct init_tap *free_init_tap(struct init_tap *p)
136 if (p != NULL) {
137 free_init_tap(p->next);
138 free(p);
140 return NULL;
143 static int parseopt(int c, char *optarg)
145 int outc=0;
146 switch (c) {
147 case 't':
148 hinit_tap=add_init_tap(hinit_tap,optarg);
149 break;
150 default:
151 outc=c;
153 return outc;
156 #ifdef VDE_LINUX
157 int open_tap(char *dev)
159 struct ifreq ifr;
160 int fd;
162 if((fd = open("/dev/net/tun", O_RDWR)) < 0){
163 printlog(LOG_ERR,"Failed to open /dev/net/tun %s",strerror(errno));
164 return(-1);
166 memset(&ifr, 0, sizeof(ifr));
167 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
168 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
169 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
170 if(ioctl(fd, TUNSETIFF, (void *) &ifr) < 0){
171 printlog(LOG_ERR,"TUNSETIFF failed %s",strerror(errno));
172 close(fd);
173 return(-1);
175 /* tuntap should be "fast", but if there is a packetq we can manage
176 a tuntap which is "not fast enough" */
177 fcntl(fd, F_SETFL, O_NONBLOCK);
178 return(fd);
180 #endif
182 #ifdef VDE_BIONIC
183 int open_tap(char *dev)
185 struct ifreq ifr;
186 int fd;
188 if((fd = open("/dev/tun", O_RDWR)) < 0){
189 printlog(LOG_ERR,"Failed to open /dev/tun %s",strerror(errno));
190 return(-1);
192 memset(&ifr, 0, sizeof(ifr));
193 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
194 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
195 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
196 if(ioctl(fd, TUNSETIFF, (void *) &ifr) < 0){
197 printlog(LOG_ERR,"TUNSETIFF failed %s",strerror(errno));
198 close(fd);
199 return(-1);
201 return(fd);
203 #endif
205 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
206 int open_tap(char *dev)
208 int fd;
209 int prefixlen = strlen(TAP_PREFIX);
210 char *path = NULL;
211 if (*dev == '/')
212 fd=open(dev, O_RDWR);
213 else
215 path = malloc(strlen(dev) + prefixlen + 1);
216 if (path != NULL)
218 snprintf(path, strlen(dev) + prefixlen + 1, "%s%s", TAP_PREFIX, dev);
219 fd=open(path, O_RDWR);
220 free(path);
222 else
223 fd = -1;
226 if (fd < 0)
228 printlog(LOG_ERR,"Failed to open tap device %s: %s", (*dev == '/') ? dev : path, strerror(errno));
229 return(-1);
231 return fd;
233 #endif
235 static struct endpoint *newtap(char *dev)
237 int tap_fd;
238 tap_fd = open_tap(dev);
239 if (tap_fd>0) {
240 struct endpoint *ep=setup_ep(0,tap_fd,tap_fd,-1,&modfun);
241 if (ep != NULL) {
242 setup_description(ep,dev);
243 add_fd(tap_fd,tap_type,ep);
245 return ep;
246 } else
247 return NULL;
250 static void init(void)
252 if(hinit_tap != NULL) {
253 struct init_tap *p;
254 tap_type=add_type(&swmi,1);
255 for(p=hinit_tap;p != NULL;p=p->next) {
256 if (newtap(p->tap_dev) == NULL)
257 printlog(LOG_ERR,"ERROR OPENING tap interface: %s",p->tap_dev);
259 hinit_tap=free_init_tap(hinit_tap);
263 static void delep (int fd_ctl, int fd_data, void *descr)
265 if (fd_ctl>=0)
266 remove_fd(fd_ctl);
267 if (descr) free(descr);
270 void start_tuntap(void)
272 modfun.modname=swmi.swmname=MODULENAME;
273 swmi.swmnopts=Nlong_options;
274 swmi.swmopts=long_options;
275 swmi.usage=usage;
276 swmi.parseopt=parseopt;
277 swmi.init=init;
278 swmi.handle_io=handle_io;
279 swmi.cleanup=cleanup;
280 modfun.sender=send_tap;
281 modfun.delep=delep;
282 add_swm(&swmi);
285 #endif