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)
16 #include <sys/types.h>
18 #include <sys/ioctl.h>
32 #include <linux/if_tun.h>
35 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
36 #define TAP_PREFIX "/dev/"
40 #define MODULENAME "tuntap"
42 static struct swmodule swmi
;
43 static struct mod_support modfun
;
44 static unsigned int tap_type
;
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
)
57 n
= len
- write(ctl_fd
, packet
, len
);
61 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"send_tap port %d: %s",port
,strerror(errno
));
71 static void closeport(int fd
, int portno
)
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
));
83 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"Reading tap data: %s",strerror(errno
));
86 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"EOF tap data port: %s",strerror(errno
));
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
)
99 static struct option long_options
[] = {
102 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
104 static void usage(void)
107 "(opts from tuntap module)\n"
108 " -t, --tap TAP Enable routing through TAP tap interface\n"
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
117 static struct init_tap
*add_init_tap(struct init_tap
*p
,char *arg
)
120 p
=malloc(sizeof(struct init_tap
));
122 printlog(LOG_WARNING
,"Malloc Tap init:%s\n",strerror(errno
));
124 p
->tap_dev
=strdup(optarg
);
128 p
->next
=add_init_tap(p
->next
,arg
);
132 static struct init_tap
*free_init_tap(struct init_tap
*p
)
135 free_init_tap(p
->next
);
141 static int parseopt(int c
, char *optarg
)
146 hinit_tap
=add_init_tap(hinit_tap
,optarg
);
155 int open_tap(char *dev
)
160 if((fd
= open("/dev/net/tun", O_RDWR
)) < 0){
161 printlog(LOG_ERR
,"Failed to open /dev/net/tun %s",strerror(errno
));
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
));
177 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
178 int open_tap(char *dev
)
181 int prefixlen
= strlen(TAP_PREFIX
);
184 fd
=open(dev
, O_RDWR
);
187 path
= malloc(strlen(dev
) + prefixlen
+ 1);
190 snprintf(path
, strlen(dev
) + prefixlen
+ 1, "%s%s", TAP_PREFIX
, dev
);
191 fd
=open(path
, O_RDWR
);
200 printlog(LOG_ERR
,"Failed to open tap device %s: %s", (*dev
== '/') ? dev
: path
, strerror(errno
));
207 static int newport(int fd
, int portno
)
212 static int newtap(char *dev
)
215 tap_fd
= open_tap(dev
);
217 int portno
=setup_ep(0,tap_fd
,NULL
,&modfun
);
219 setup_description(portno
,tap_fd
,dev
);
220 add_fd(tap_fd
,tap_type
,portno
);
228 static void init(void)
230 if(hinit_tap
!= NULL
) {
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
;
252 swmi
.parseopt
=parseopt
;
254 swmi
.handle_input
=handle_input
;
255 swmi
.cleanup
=cleanup
;
256 modfun
.sender
=send_tap
;
257 modfun
.newport
=newport
;
259 modfun
.delport
=closeport
;