1 /* Copyright 2006 Renzo Davoli
2 * from vde_plug Davoli Gardenghi
3 * Modified 2010 Renzo Davoli, vdestream added
4 * Licensed under the GPLv2
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
27 #include <vdecommon.h>
28 #include <libvdeplug.h>
32 #if defined VDE_LINUX || defined VDE_BIONIC
34 #include <linux/if_tun.h>
38 #include <sys/socket.h>
40 #include <net/if_tun.h>
43 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
44 # define TAP_PREFIX "/dev/"
45 # if defined HAVE_SYSLIMITS_H
46 # include <syslimits.h>
47 # elif defined HAVE_SYS_SYSLIMITS_H
48 # include <sys/syslimits.h>
50 # error "No syslimits.h found"
59 static char *pidfile
= NULL
;
60 static char pidfile_path
[PATH_MAX
];
62 void printlog(int priority
, const char *format
, ...)
66 va_start (arg
, format
);
69 vsyslog(priority
,format
,arg
);
71 fprintf(stderr
,"%s: ",prog
);
72 vfprintf(stderr
,format
,arg
);
78 static void cleanup(void)
80 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
81 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
84 if (vdestream
!= NULL
)
85 vdestream_close(vdestream
);
90 static void sig_handler(int sig
)
100 static void setsighandlers()
102 /* setting signal handlers.
103 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
104 * ignores all the others signals which could cause termination. */
105 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
106 { SIGHUP
, "SIGHUP", 0 },
107 { SIGINT
, "SIGINT", 0 },
108 { SIGPIPE
, "SIGPIPE", 1 },
109 { SIGALRM
, "SIGALRM", 1 },
110 { SIGTERM
, "SIGTERM", 0 },
111 { SIGUSR1
, "SIGUSR1", 1 },
112 { SIGUSR2
, "SIGUSR2", 1 },
113 { SIGPROF
, "SIGPROF", 1 },
114 { SIGVTALRM
, "SIGVTALRM", 1 },
115 #if defined VDE_LINUX || defined VDE_BIONIC
116 { SIGPOLL
, "SIGPOLL", 1 },
118 { SIGSTKFLT
, "SIGSTKFLT", 1 },
120 { SIGIO
, "SIGIO", 1 },
121 { SIGPWR
, "SIGPWR", 1 },
123 { SIGUNUSED
, "SIGUNUSED", 1 },
127 { SIGXCPU
, "SIGXCPU", 1 },
128 { SIGXFSZ
, "SIGXFSZ", 1 },
134 for(i
= 0; signals
[i
].sig
!= 0; i
++)
135 if(signal(signals
[i
].sig
,
136 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
137 perror("Setting handler");
140 static void usage(void) {
141 fprintf(stderr
, "Usage: %s [OPTION]... tap_name\n\n", prog
);
142 fprintf(stderr
, " -p, --port=portnum Port number in the VDE switch\n"
143 " -g, --group=group Group for the socket\n"
144 " -m, --mode=mode Octal mode for the socket\n"
145 " -s, --sock=socket VDE switch control socket or dir\n"
146 " -d, --daemon Launch in background\n"
147 " -P, --pidfile=pidfile Create pidfile with our PID\n"
148 " -h, --help This help\n");
153 int open_tap(char *dev
)
158 if((fd
= open("/dev/net/tun", O_RDWR
)) < 0){
159 printlog(LOG_ERR
,"Failed to open /dev/net/tun %s",strerror(errno
));
162 memset(&ifr
, 0, sizeof(ifr
));
163 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
164 strncpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
) - 1);
165 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
166 if(ioctl(fd
, TUNSETIFF
, (void *) &ifr
) < 0){
167 printlog(LOG_ERR
,"TUNSETIFF failed %s",strerror(errno
));
176 int open_tap(char *dev
)
181 if((fd
= open("/dev/tun", O_RDWR
)) < 0){
182 printlog(LOG_ERR
,"Failed to open /dev/tun %s",strerror(errno
));
185 memset(&ifr
, 0, sizeof(ifr
));
186 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
187 strncpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
) - 1);
188 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
189 if(ioctl(fd
, TUNSETIFF
, (void *) &ifr
) < 0){
190 printlog(LOG_ERR
,"TUNSETIFF failed %s",strerror(errno
));
198 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
199 int open_tap(char *dev
)
202 int prefixlen
= strlen(TAP_PREFIX
);
205 fd
=open(dev
, O_RDWR
);
208 path
= malloc(strlen(dev
) + prefixlen
+ 1);
211 snprintf(path
, strlen(dev
) + prefixlen
+ 1, "%s%s", TAP_PREFIX
, dev
);
212 fd
=open(path
, O_RDWR
);
221 printlog(LOG_ERR
,"Failed to open tap device %s: %s", (*dev
== '/') ? dev
: path
, strerror(errno
));
228 unsigned char bufin
[BUFSIZE
];
230 static void save_pidfile()
232 if(pidfile
[0] != '/')
233 strncat(pidfile_path
, pidfile
, PATH_MAX
- strlen(pidfile_path
) - 1);
235 strncpy(pidfile_path
, pidfile
, PATH_MAX
- 1);
237 int fd
= open(pidfile_path
,
238 O_WRONLY
| O_CREAT
| O_EXCL
,
239 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
243 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
247 if((f
= fdopen(fd
, "w")) == NULL
) {
248 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
252 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
253 printlog(LOG_ERR
, "Error in writing pidfile");
260 static ssize_t
vde_plug2tap_recv(void *opaque
, void *buf
, size_t count
)
263 return write(*tapfdp
,buf
,count
);
266 int main(int argc
, char **argv
)
268 static char *sockname
=NULL
;
269 static char *tapname
=NULL
;
273 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
275 static struct pollfd pollv
[]={{0,POLLIN
|POLLHUP
},
282 int option_index
= 0;
284 static struct option long_options
[] = {
291 {"pidfile", 1, 0, 'P'},
294 c
= GETOPT_LONG (argc
, argv
, "hdP:p:s:m:g:",
295 long_options
, &option_index
);
301 open_args
.port
=atoi(optarg
);
302 if (open_args
.port
<= 0)
303 usage(); //implies exit
307 usage(); //implies exit
311 sockname
=strdup(optarg
);
315 sscanf(optarg
,"%o",(unsigned int *)&(open_args
.mode
));
319 open_args
.group
=strdup(optarg
);
327 pidfile
=strdup(optarg
);
331 usage(); //implies exit
336 openlog(basename(prog
), LOG_PID
, 0);
338 syslog(LOG_INFO
,"VDE_PLUG2TAP started");
340 /* saves current path in pidfile_path, because otherwise with daemonize() we
342 if(getcwd(pidfile_path
, PATH_MAX
-2) == NULL
) {
343 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
346 strcat(pidfile_path
, "/");
347 if (daemonize
&& daemon(0, 0)) {
348 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
352 /* once here, we're sure we're the true process which will continue as a
353 * server: save PID file if needed */
354 if(pidfile
) save_pidfile();
357 tapname
=argv
[optind
];
359 usage(); // implies exit
364 tapfd
=open_tap(tapname
);
369 if (sockname
==NULL
|| strcmp(sockname
,"-") != 0) {
370 conn
=vde_open(sockname
,"vde_plug2tap:",&open_args
);
372 printlog(LOG_ERR
,"vde_open %s: %s",sockname
?sockname
:"DEF_SWITCH",strerror(errno
));
375 pollv
[1].fd
=vde_datafd(conn
);
376 pollv
[2].fd
=vde_ctlfd(conn
);
379 vdestream
=vdestream_open(&tapfd
,STDOUT_FILENO
,vde_plug2tap_recv
,NULL
);
380 if (vdestream
== NULL
)
382 pollv
[1].fd
=STDIN_FILENO
;
388 if ((pollv
[0].revents
| pollv
[1].revents
| pollv
[2].revents
) & POLLHUP
||
389 (npollv
> 2 && pollv
[2].revents
& POLLIN
))
391 if (pollv
[0].revents
& POLLIN
) {
392 nx
=read(tapfd
,bufin
,sizeof(bufin
));
393 /* if POLLIN but not data it means that the stream has been
394 * closed at the other end */
395 //fprintf(stderr,"%s: RECV %d %x %x \n",prog,nx,bufin[0],bufin[1]);
399 vde_send(conn
,bufin
,nx
,0);
401 vdestream_send(vdestream
, bufin
, nx
);
403 if (pollv
[1].revents
& POLLIN
) {
405 nx
=vde_recv(conn
,bufin
,sizeof(bufin
),0);
408 write(tapfd
,bufin
,nx
);
410 nx
=read(STDIN_FILENO
,bufin
,sizeof(bufin
));
413 vdestream_recv(vdestream
,bufin
,nx
);
415 //fprintf(stderr,"%s: SENT %d %x %x \n",prog,nx,bufin[0],bufin[1]);