1 /* Copyright 2006 Renzo Davoli
2 * from vde_plug Davoli Gardenghi
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
21 #include <libvdeplug/libvdeplug.h>
30 #include <linux/if_tun.h>
34 #define TAP_PREFIX "/dev/"
41 static char *pidfile
= NULL
;
42 static char pidfile_path
[PATH_MAX
];
44 void printlog(int priority
, const char *format
, ...)
48 va_start (arg
, format
);
51 vsyslog(priority
,format
,arg
);
53 fprintf(stderr
,"%s: ",prog
);
54 vfprintf(stderr
,format
,arg
);
60 static void cleanup(void)
62 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
63 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
69 static void sig_handler(int sig
)
76 static void setsighandlers()
78 /* setting signal handlers.
79 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
80 * ignores all the others signals which could cause termination. */
81 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
82 { SIGHUP
, "SIGHUP", 0 },
83 { SIGINT
, "SIGINT", 0 },
84 { SIGPIPE
, "SIGPIPE", 1 },
85 { SIGALRM
, "SIGALRM", 1 },
86 { SIGTERM
, "SIGTERM", 0 },
87 { SIGUSR1
, "SIGUSR1", 1 },
88 { SIGUSR2
, "SIGUSR2", 1 },
89 { SIGPROF
, "SIGPROF", 1 },
90 { SIGVTALRM
, "SIGVTALRM", 1 },
92 { SIGPOLL
, "SIGPOLL", 1 },
93 { SIGSTKFLT
, "SIGSTKFLT", 1 },
94 { SIGIO
, "SIGIO", 1 },
95 { SIGPWR
, "SIGPWR", 1 },
96 { SIGUNUSED
, "SIGUNUSED", 1 },
99 { SIGXCPU
, "SIGXCPU", 1 },
100 { SIGXFSZ
, "SIGXFSZ", 1 },
106 for(i
= 0; signals
[i
].sig
!= 0; i
++)
107 if(signal(signals
[i
].sig
,
108 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
109 perror("Setting handler");
112 struct pollfd pollv
[]={{0,POLLIN
|POLLHUP
},{0,POLLIN
|POLLHUP
},{0,POLLIN
|POLLHUP
}};
114 static void usage(void) {
115 fprintf (stderr
,"Usage: %s [-p portnum] [-g group] [-m mod] [-s sock] -daemon tap_name\n\n",prog
);
120 int open_tap(char *dev
)
125 if((fd
= open("/dev/net/tun", O_RDWR
)) < 0){
126 printlog(LOG_ERR
,"Failed to open /dev/net/tun %s",strerror(errno
));
129 memset(&ifr
, 0, sizeof(ifr
));
130 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
131 strncpy(ifr
.ifr_name
, dev
, sizeof(ifr
.ifr_name
) - 1);
132 /*printf("dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, dev);*/
133 if(ioctl(fd
, TUNSETIFF
, (void *) &ifr
) < 0){
134 printlog(LOG_ERR
,"TUNSETIFF failed %s",strerror(errno
));
143 int open_tap(char *dev
)
146 int prefixlen
= strlen(TAP_PREFIX
);
149 fd
=open(dev
, O_RDWR
);
152 path
= malloc(strlen(dev
) + prefixlen
+ 1);
155 snprintf(path
, strlen(dev
) + prefixlen
+ 1, "%s%s", TAP_PREFIX
, dev
);
156 fd
=open(path
, O_RDWR
);
165 printlog(LOG_ERR
,"Failed to open tap device %s: %s", (*dev
== '/') ? dev
: path
, strerror(errno
));
172 unsigned char bufin
[BUFSIZE
];
174 static void save_pidfile()
176 if(pidfile
[0] != '/')
177 strncat(pidfile_path
, pidfile
, PATH_MAX
- strlen(pidfile_path
));
179 strcpy(pidfile_path
, pidfile
);
181 int fd
= open(pidfile_path
,
182 O_WRONLY
| O_CREAT
| O_EXCL
,
183 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
187 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
191 if((f
= fdopen(fd
, "w")) == NULL
) {
192 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
196 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
197 printlog(LOG_ERR
, "Error in writing pidfile");
204 int main(int argc
, char **argv
)
206 static char *sockname
=NULL
;
207 static char *tapname
=NULL
;
212 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
216 int option_index
= 0;
218 static struct option long_options
[] = {
225 {"pidfile", 1, 0, 'P'},
228 c
= GETOPT_LONG (argc
, argv
, "hdPp:s:m:g:",
229 long_options
, &option_index
);
235 open_args
.port
=atoi(optarg
);
236 if (open_args
.port
<= 0 || open_args
.port
> 255 )
237 usage(); //implies exit
241 usage(); //implies exit
245 sockname
=strdup(optarg
);
249 sscanf(optarg
,"%o",&(open_args
.mode
));
253 open_args
.group
=strdup(optarg
);
261 pidfile
=strdup(optarg
);
265 usage(); //implies exit
270 openlog(basename(prog
), LOG_PID
, 0);
272 syslog(LOG_INFO
,"VDE_PLUG2TAP started");
274 /* saves current path in pidfile_path, because otherwise with daemonize() we
276 if(getcwd(pidfile_path
, PATH_MAX
-1) == NULL
) {
277 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
280 strcat(pidfile_path
, "/");
281 if (daemonize
&& daemon(0, 1)) {
282 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
286 /* once here, we're sure we're the true process which will continue as a
287 * server: save PID file if needed */
288 if(pidfile
) save_pidfile();
291 tapname
=argv
[optind
];
295 tapfd
=open_tap(tapname
);
298 conn
=vde_open(sockname
,"vde_plug:",&open_args
);
303 pollv
[1].fd
=vde_datafd(conn
);
304 pollv
[2].fd
=vde_ctlfd(conn
);
307 result
=poll(pollv
,3,-1);
308 if ((pollv
[0].revents
| pollv
[1].revents
| pollv
[2].revents
) & POLLHUP
||
309 pollv
[2].revents
& POLLIN
)
311 if (pollv
[0].revents
& POLLIN
) {
312 nx
=read(tapfd
,bufin
,sizeof(bufin
));
313 /* if POLLIN but not data it means that the stream has been
314 * closed at the other end */
315 //fprintf(stderr,"%s: RECV %d %x %x \n",prog,nx,bufin[0],bufin[1]);
318 vde_send(conn
,bufin
,nx
,0);
320 if (pollv
[1].revents
& POLLIN
) {
321 nx
=vde_recv(conn
,bufin
,sizeof(bufin
),0);
324 write(tapfd
,bufin
,nx
);
325 //fprintf(stderr,"%s: SENT %d %x %x \n",prog,nx,bufin[0],bufin[1]);