bugfix (fdctl is not used)
[vde.git] / vde-2 / tuntap.c
blobe64d30bc054fb9621ce7eeb338e2b2f9db8358c1
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 <config.h>
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <syslog.h>
14 #include <stdlib.h>
15 #include <libgen.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/ioctl.h>
19 #include <stdarg.h>
20 #define _GNU_SOURCE
21 #include <getopt.h>
22 #include <vde.h>
24 #include <port.h>
25 #include <switch.h>
26 #include <consmgmt.h>
28 #ifdef HAVE_TUNTAP
30 #ifdef VDE_LINUX
31 #include <net/if.h>
32 #include <linux/if_tun.h>
33 #endif
35 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
36 #define TAP_PREFIX "/dev/"
37 #endif
39 #define MAXCMD 128
40 #define MODULENAME "tuntap"
42 static struct swmodule swmi;
43 static struct mod_support modfun;
44 static unsigned int tap_type;
46 struct init_tap {
47 char *tap_dev;
48 struct init_tap *next;
51 struct init_tap *hinit_tap=NULL;
53 static int send_tap(int fd, int ctl_fd, void *packet, int len, void *unused, int port)
55 int n;
57 n = len - write(ctl_fd, packet, len);
58 if(n){
59 int rv=errno;
60 #ifndef VDE_PQ
61 if(errno != EAGAIN) printlog(LOG_WARNING,"send_tap port %d: %s",port,strerror(errno));
62 #endif
63 if (n > len)
64 return -rv;
65 else
66 return n;
68 return 0;
71 static void closeport(int fd, int portno)
73 if (fd>0)
74 remove_fd(fd);
77 static void handle_input(unsigned char type,int fd,int revents,int *arg)
79 struct bipacket packet;
80 int len=read(fd, &(packet.p), sizeof(struct packet));
82 if(len < 0){
83 if(errno != EAGAIN) printlog(LOG_WARNING,"Reading tap data: %s",strerror(errno));
85 else if(len == 0) {
86 if(errno != EAGAIN) printlog(LOG_WARNING,"EOF tap data port: %s",strerror(errno));
87 /* close tap! */
88 } else if (len >= ETH_HEADER_SIZE)
89 handle_in_packet(*arg, &(packet.p), len);
93 static void cleanup(unsigned char type,int fd,int arg)
95 if (fd >= 0)
96 close(fd);
99 static struct option long_options[] = {
100 {"tap", 1, 0, 't'},
102 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
104 static void usage(void)
106 printf(
107 "(opts from tuntap module)\n"
108 " -t, --tap TAP Enable routing through TAP tap interface\n"
109 #ifdef VDE_DARWIN
110 " TAP can be an absolute file name or a relative\n"
111 " one (and will be prefixed with %s). The TAP\n"
112 " device must already exist.\n", TAP_PREFIX
113 #endif
117 static struct init_tap *add_init_tap(struct init_tap *p,char *arg)
119 if (p == NULL) {
120 p=malloc(sizeof(struct init_tap));
121 if (p==NULL)
122 printlog(LOG_WARNING,"Malloc Tap init:%s\n",strerror(errno));
123 else {
124 p->tap_dev=strdup(optarg);
125 p->next=NULL;
127 } else
128 p->next=add_init_tap(p->next,arg);
129 return(p);
132 static struct init_tap *free_init_tap(struct init_tap *p)
134 if (p != NULL) {
135 free_init_tap(p->next);
136 free(p);
138 return NULL;
141 static int parseopt(int c, char *optarg)
143 int outc=0;
144 switch (c) {
145 case 't':
146 hinit_tap=add_init_tap(hinit_tap,optarg);
147 break;
148 default:
149 outc=c;
151 return outc;
154 #ifdef VDE_LINUX
155 int open_tap(char *dev)
157 struct ifreq ifr;
158 int fd;
160 if((fd = open("/dev/net/tun", O_RDWR)) < 0){
161 printlog(LOG_ERR,"Failed to open /dev/net/tun %s",strerror(errno));
162 return(-1);
164 memset(&ifr, 0, sizeof(ifr));
165 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
166 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
167 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
168 if(ioctl(fd, TUNSETIFF, (void *) &ifr) < 0){
169 printlog(LOG_ERR,"TUNSETIFF failed %s",strerror(errno));
170 close(fd);
171 return(-1);
173 return(fd);
175 #endif
177 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
178 int open_tap(char *dev)
180 int fd;
181 int prefixlen = strlen(TAP_PREFIX);
182 char *path = NULL;
183 if (*dev == '/')
184 fd=open(dev, O_RDWR);
185 else
187 path = malloc(strlen(dev) + prefixlen + 1);
188 if (path != NULL)
190 snprintf(path, strlen(dev) + prefixlen + 1, "%s%s", TAP_PREFIX, dev);
191 fd=open(path, O_RDWR);
192 free(path);
194 else
195 fd = -1;
198 if (fd < 0)
200 printlog(LOG_ERR,"Failed to open tap device %s: %s", (*dev == '/') ? dev : path, strerror(errno));
201 return(-1);
203 return fd;
205 #endif
207 static int newport(int fd, int portno)
209 return fd;
212 static int newtap(char *dev)
214 int tap_fd;
215 tap_fd = open_tap(dev);
216 if (tap_fd>0) {
217 int portno=setup_ep(0,tap_fd,NULL,&modfun);
218 if (portno >= 0) {
219 setup_description(portno,tap_fd,dev);
220 add_fd(tap_fd,tap_type,portno);
221 return portno;
222 } else
223 return -1;
224 } else
225 return -1;
228 static void init(void)
230 if(hinit_tap != NULL) {
231 struct init_tap *p;
232 tap_type=add_type(&swmi,1);
233 for(p=hinit_tap;p != NULL;p=p->next) {
234 if (newtap(p->tap_dev) < 0)
235 printlog(LOG_ERR,"ERROR OPENING tap interface: %s",p->tap_dev);
237 hinit_tap=free_init_tap(hinit_tap);
241 static void delep (int fd, void* data, void *descr)
243 if (descr) free(descr);
246 void start_tuntap(void)
248 modfun.modname=swmi.swmname=MODULENAME;
249 swmi.swmnopts=Nlong_options;
250 swmi.swmopts=long_options;
251 swmi.usage=usage;
252 swmi.parseopt=parseopt;
253 swmi.init=init;
254 swmi.handle_input=handle_input;
255 swmi.cleanup=cleanup;
256 modfun.sender=send_tap;
257 modfun.newport=newport;
258 modfun.delep=delep;
259 modfun.delport=closeport;
260 add_swm(&swmi);
263 #endif