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>
25 #include <linux/if_tun.h>
29 #define TAP_PREFIX "/dev/"
38 #define MODULENAME "tuntap"
40 static struct swmodule swmi
;
41 static struct mod_support modfun
;
42 static unsigned int tap_type
;
46 struct init_tap
*next
;
49 struct init_tap
*hinit_tap
=NULL
;
51 static void send_tap(int fd
, int ctl_fd
, void *packet
, int len
, void *unused
, int port
)
55 n
= write(ctl_fd
, packet
, len
);
57 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"send_tap port %d: %s",port
,strerror(errno
));
61 static void closeport(int fd
, int portno
)
67 static void handle_input(unsigned char type
,int fd
,int revents
,int *arg
)
69 struct bipacket packet
;
70 int len
=read(fd
, &(packet
.p
), sizeof(struct packet
));
73 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"Reading tap data: %s",strerror(errno
));
76 if(errno
!= EAGAIN
) printlog(LOG_WARNING
,"EOF tap data port: %s",strerror(errno
));
78 } else if (len
>= ETH_HEADER_SIZE
)
79 handle_in_packet(*arg
, &(packet
.p
), len
);
83 static void cleanup(unsigned char type
,int fd
,int arg
)
89 static struct option long_options
[] = {
92 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
94 static void usage(void)
97 "(opts from tuntap module)\n"
98 " -t, --tap TAP Enable routing through TAP tap interface\n"
100 " TAP can be an absolute file name or a relative\n"
101 " one (and will be prefixed with %s). The TAP\n"
102 " device must already exist.\n", TAP_PREFIX
107 static struct init_tap
*add_init_tap(struct init_tap
*p
,char *arg
)
110 p
=malloc(sizeof(struct init_tap
));
112 printlog(LOG_WARNING
,"Malloc Tap init:%s\n",strerror(errno
));
114 p
->tap_dev
=strdup(optarg
);
118 p
->next
=add_init_tap(p
->next
,arg
);
122 static struct init_tap
*free_init_tap(struct init_tap
*p
)
125 free_init_tap(p
->next
);
131 static int parseopt(int c
, char *optarg
)
136 hinit_tap
=add_init_tap(hinit_tap
,optarg
);
145 int open_tap(char *dev
)
150 if((fd
= open("/dev/net/tun", O_RDWR
)) < 0){
151 printlog(LOG_ERR
,"Failed to open /dev/net/tun %s",strerror(errno
));
154 memset(&ifr
, 0, sizeof(ifr
));
155 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
156 strncpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
) - 1);
157 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
158 if(ioctl(fd
, TUNSETIFF
, (void *) &ifr
) < 0){
159 printlog(LOG_ERR
,"TUNSETIFF failed %s",strerror(errno
));
168 int open_tap(char *dev
)
171 int prefixlen
= strlen(TAP_PREFIX
);
174 fd
=open(dev
, O_RDWR
);
177 path
= malloc(strlen(dev
) + prefixlen
+ 1);
180 snprintf(path
, strlen(dev
) + prefixlen
+ 1, "%s%s", TAP_PREFIX
, dev
);
181 fd
=open(path
, O_RDWR
);
190 printlog(LOG_ERR
,"Failed to open tap device %s: %s", (*dev
== '/') ? dev
: path
, strerror(errno
));
197 static int newport(int fd
, int portno
)
202 static int newtap(char *dev
)
205 tap_fd
= open_tap(dev
);
207 int portno
=setup_ep(0,tap_fd
,NULL
,&modfun
);
209 setup_description(portno
,tap_fd
,dev
);
210 add_fd(tap_fd
,tap_type
,portno
);
218 static void init(void)
220 if(hinit_tap
!= NULL
) {
222 tap_type
=add_type(&swmi
,1);
223 for(p
=hinit_tap
;p
!= NULL
;p
=p
->next
) {
224 if (newtap(p
->tap_dev
) < 0)
225 printlog(LOG_ERR
,"ERROR OPENING tap interface: %s",p
->tap_dev
);
227 hinit_tap
=free_init_tap(hinit_tap
);
231 static void delep (int fd
, void* data
, void *descr
)
233 if (descr
) free(descr
);
236 void start_tuntap(void)
238 modfun
.modname
=swmi
.swmname
=MODULENAME
;
239 swmi
.swmnopts
=Nlong_options
;
240 swmi
.swmopts
=long_options
;
242 swmi
.parseopt
=parseopt
;
244 swmi
.handle_input
=handle_input
;
245 swmi
.cleanup
=cleanup
;
246 modfun
.sender
=send_tap
;
247 modfun
.newport
=newport
;
249 modfun
.delport
=closeport
;