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>
26 #include <linux/if_tun.h>
30 #define TAP_PREFIX "/dev/"
39 #define MODULENAME "tuntap"
41 static struct swmodule swmi
;
42 static struct mod_support modfun
;
43 static unsigned int tap_type
;
47 struct init_tap
*next
;
50 struct init_tap
*hinit_tap
=NULL
;
52 static int send_tap(int fd
, int ctl_fd
, void *packet
, int len
, void *unused
, int port
)
56 n
= len
- write(ctl_fd
, packet
, len
);
60 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"send_tap port %d: %s",port
,strerror(errno
));
70 static void closeport(int fd
, int portno
)
76 static void handle_input(unsigned char type
,int fd
,int revents
,int *arg
)
78 struct bipacket packet
;
79 int len
=read(fd
, &(packet
.p
), sizeof(struct packet
));
82 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"Reading tap data: %s",strerror(errno
));
85 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"EOF tap data port: %s",strerror(errno
));
87 } else if (len
>= ETH_HEADER_SIZE
)
88 handle_in_packet(*arg
, &(packet
.p
), len
);
92 static void cleanup(unsigned char type
,int fd
,int arg
)
98 static struct option long_options
[] = {
101 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
103 static void usage(void)
106 "(opts from tuntap module)\n"
107 " -t, --tap TAP Enable routing through TAP tap interface\n"
109 " TAP can be an absolute file name or a relative\n"
110 " one (and will be prefixed with %s). The TAP\n"
111 " device must already exist.\n", TAP_PREFIX
116 static struct init_tap
*add_init_tap(struct init_tap
*p
,char *arg
)
119 p
=malloc(sizeof(struct init_tap
));
121 printlog(LOG_WARNING
,"Malloc Tap init:%s\n",strerror(errno
));
123 p
->tap_dev
=strdup(optarg
);
127 p
->next
=add_init_tap(p
->next
,arg
);
131 static struct init_tap
*free_init_tap(struct init_tap
*p
)
134 free_init_tap(p
->next
);
140 static int parseopt(int c
, char *optarg
)
145 hinit_tap
=add_init_tap(hinit_tap
,optarg
);
154 int open_tap(char *dev
)
159 if((fd
= open("/dev/net/tun", O_RDWR
)) < 0){
160 printlog(LOG_ERR
,"Failed to open /dev/net/tun %s",strerror(errno
));
163 memset(&ifr
, 0, sizeof(ifr
));
164 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
165 strncpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
) - 1);
166 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
167 if(ioctl(fd
, TUNSETIFF
, (void *) &ifr
) < 0){
168 printlog(LOG_ERR
,"TUNSETIFF failed %s",strerror(errno
));
177 int open_tap(char *dev
)
180 int prefixlen
= strlen(TAP_PREFIX
);
183 fd
=open(dev
, O_RDWR
);
186 path
= malloc(strlen(dev
) + prefixlen
+ 1);
189 snprintf(path
, strlen(dev
) + prefixlen
+ 1, "%s%s", TAP_PREFIX
, dev
);
190 fd
=open(path
, O_RDWR
);
199 printlog(LOG_ERR
,"Failed to open tap device %s: %s", (*dev
== '/') ? dev
: path
, strerror(errno
));
206 static int newport(int fd
, int portno
)
211 static int newtap(char *dev
)
214 tap_fd
= open_tap(dev
);
216 int portno
=setup_ep(0,tap_fd
,NULL
,&modfun
);
218 setup_description(portno
,tap_fd
,dev
);
219 add_fd(tap_fd
,tap_type
,portno
);
227 static void init(void)
229 if(hinit_tap
!= NULL
) {
231 tap_type
=add_type(&swmi
,1);
232 for(p
=hinit_tap
;p
!= NULL
;p
=p
->next
) {
233 if (newtap(p
->tap_dev
) < 0)
234 printlog(LOG_ERR
,"ERROR OPENING tap interface: %s",p
->tap_dev
);
236 hinit_tap
=free_init_tap(hinit_tap
);
240 static void delep (int fd
, void* data
, void *descr
)
242 if (descr
) free(descr
);
245 void start_tuntap(void)
247 modfun
.modname
=swmi
.swmname
=MODULENAME
;
248 swmi
.swmnopts
=Nlong_options
;
249 swmi
.swmopts
=long_options
;
251 swmi
.parseopt
=parseopt
;
253 swmi
.handle_input
=handle_input
;
254 swmi
.cleanup
=cleanup
;
255 modfun
.sender
=send_tap
;
256 modfun
.newport
=newport
;
258 modfun
.delport
=closeport
;