1 /* Copyright 2003-2007 Renzo Davoli
2 * Licensed under the GPL
3 * Modified by Ludovico Gardenghi 2005
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
19 #include <sys/types.h>
27 #include <netinet/in.h>
33 #include <vdecommon.h>
35 #include <libvdeplug.h>
39 #if defined(VDE_DARWIN) || defined(VDE_FREEBSD)
40 # if defined HAVE_SYSLIMITS_H
41 # include <syslimits.h>
42 # elif defined HAVE_SYS_SYSLIMITS_H
43 # include <sys/syslimits.h>
45 # error "No syslimits.h found"
49 #define SWITCH_MAGIC 0xfeedface
55 static char *pidfile
= NULL
;
56 static char pidfile_path
[PATH_MAX
];
61 void printlog(int priority
, const char *format
, ...)
65 va_start (arg
, format
);
68 vsyslog(priority
,format
,arg
);
70 fprintf(stderr
,"%s: ",prog
);
71 vfprintf(stderr
,format
,arg
);
78 static void save_pidfile()
81 strncat(pidfile_path
, pidfile
, sizeof(pidfile_path
) - strlen(pidfile_path
) -1);
84 strncat(pidfile_path
, pidfile
, sizeof(pidfile_path
)-1);
87 int fd
= open(pidfile_path
,
88 O_WRONLY
| O_CREAT
| O_EXCL
,
89 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
93 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
97 if((f
= fdopen(fd
, "w")) == NULL
) {
98 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
102 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
103 printlog(LOG_ERR
, "Error in writing pidfile");
110 static void cleanup(void)
112 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
113 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
118 /* XXX Apparently unused... check if ok to be removed */
120 /*static void sig_handler(int sig)
123 signal(sig, SIG_DFL);
129 /*static void setsighandlers()
131 |+ setting signal handlers.
132 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
133 * ignores all the others signals which could cause termination. +|
134 struct { int sig; const char *name; int ignore; } signals[] = {
135 { SIGHUP, "SIGHUP", 0 },
136 { SIGINT, "SIGINT", 0 },
137 { SIGPIPE, "SIGPIPE", 1 },
138 { SIGALRM, "SIGALRM", 1 },
139 { SIGTERM, "SIGTERM", 0 },
140 { SIGUSR1, "SIGUSR1", 1 },
141 { SIGUSR2, "SIGUSR2", 1 },
142 { SIGPROF, "SIGPROF", 1 },
143 { SIGVTALRM, "SIGVTALRM", 1 },
145 { SIGPOLL, "SIGPOLL", 1 },
147 { SIGSTKFLT, "SIGSTKFLT", 1 },
149 { SIGIO, "SIGIO", 1 },
150 { SIGPWR, "SIGPWR", 1 },
152 { SIGUNUSED, "SIGUNUSED", 1 },
156 { SIGXCPU, "SIGXCPU", 1 },
157 { SIGXFSZ, "SIGXFSZ", 1 },
163 for(i = 0; signals[i].sig != 0; i++)
164 if(signal(signals[i].sig,
165 signals[i].ignore ? SIG_IGN : sig_handler) < 0)
166 perror("Setting handler");
169 unsigned char bufin
[BUFSIZE
];
171 int slirp_can_output(void)
178 #define convery2ascii(x) ((x)>=' ' && (x) <= '~')?(x):'.'
179 void dumppkt(const uint8_t *pkt
, int pkt_len
)
182 printf("Packet dump len=%d\n",pkt_len
);
185 for (i
=0;i
<((pkt_len
-1)/16)+1;i
++) {
187 if (i
*16+j
> pkt_len
)
190 printf("%02x ",pkt
[i
*16+j
]);
193 if (i
*16+j
> pkt_len
)
196 printf("%c",convery2ascii(pkt
[i
*16+j
]));
202 void slirp_output(const uint8_t *pkt
, int pkt_len
)
205 //fprintf(stderr,"RX from slirp %d\n",pkt_len);
206 //dumppkt(pkt,pkt_len);
207 vde_send(conn
,pkt
,pkt_len
,0);
222 struct redirtcp
*next
;
225 static struct redirtcp
*parse_redir_tcp(struct redirtcp
*head
, char *buff
)
230 char *ipaddrstr
=NULL
;
232 struct redirtcp
*new;
234 if ((ipaddrstr
= strchr(buff
, ':'))) {
236 if (*ipaddrstr
== 0) {
237 fprintf(stderr
,"redir TCP syntax error\n");
241 if ((portstr
= strchr(ipaddrstr
, ':'))) {
244 fprintf(stderr
,"redir TCP syntax error\n");
249 sscanf(buff
,"%d",&lport
);
250 sscanf(portstr
,"%d",&port
);
252 inaddr
= inet_addr(ipaddrstr
);
255 fprintf(stderr
,"TCP redirection error: an IP address must be specified\r\n");
259 if ((new=malloc(sizeof(struct redirtcp
)))==NULL
)
270 static struct redirx
*parse_redir_x(struct redirx
*head
, char *buff
)
273 u_int32_t inaddr
= 0;
278 if ((ptr
= strchr(buff
, ':'))) {
281 fprintf(stderr
,"X-redirection syntax error\n");
286 inaddr
= inet_addr(buff
);
287 if (inaddr
== 0xffffffff) {
288 fprintf(stderr
,"Error: X-redirection bad address\r\n");
293 if (strchr(ptr
, '.')) {
294 if (sscanf(ptr
, "%d.%d", &display
, &screen
) != 2)
297 if (sscanf(ptr
, "%d", &display
) != 1)
303 fprintf(stderr
,"Error: X-redirection an IP address must be specified\r\n");
307 if ((new=malloc(sizeof(struct redirx
)))==NULL
)
311 new->display
=display
;
313 new->start_port
=start_port
;
319 static void parse_redir_locx(char *buff
)
323 if ((path
= strchr(buff
, ':'))) {
325 tcp2unix_add(port
,path
);
327 fprintf(stderr
,"Error: tcp2unix redirection sytax error -x port:path e.g. -x 6000:/tmp/.X11-unix/X0\r\n");
330 static void do_redir_tcp(struct redirtcp
*head
)
333 do_redir_tcp(head
->next
);
334 redir_tcp(head
->inaddr
,head
->port
,head
->lport
);
339 static void do_redir_x(struct redirx
*head
)
342 do_redir_x(head
->next
);
343 redir_x(head
->inaddr
,head
->start_port
,head
->display
,head
->screen
);
348 void usage(char *name
) {
351 " %s [-socket vdesock] [-dhcp] [-daemon] [-network netaddr] \n"
352 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n"
353 "\t [-x portno:unix_socket_path]\n"
354 " %s [-s vdesock] [-D] [-d] [-n netaddr]\n"
355 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n"
356 "\t [-x portno:unix_socket_path]\n"
361 struct option slirpvdeopts
[] = {
362 {"socket",1,NULL
,'s'},
364 {"vdesock",1,NULL
,'s'},
366 {"pidfile", 1, 0, 'p'},
368 {"daemon",0,NULL
,'d'},
369 {"network",1,NULL
,'n'},
375 int main(int argc
, char **argv
)
385 struct redirtcp
*rtcp
=NULL
;
386 struct redirx
*rx
=NULL
;
387 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
389 prog
=basename(argv
[0]);
391 while ((opt
=GETOPT_LONG(argc
,argv
,"s:n:p:g:m:L:X:x:dD",slirpvdeopts
,&longindx
)) > 0) {
393 case 's' : sockname
=optarg
;
395 case 'D' : dhcpmgmt
= 1;
397 case 'd' : daemonize
= 1;
399 case 'n' : netw
=optarg
;
401 case 'm' : sscanf(optarg
,"%o",&(open_args
.mode
));
403 case 'g' : open_args
.group
=strdup(optarg
);
405 case 'p': pidfile
=strdup(optarg
);
407 case 'P' : open_args
.port
=atoi(optarg
);
409 case 'L': rtcp
=parse_redir_tcp(rtcp
,optarg
);
411 case 'X': rx
=parse_redir_x(rx
,optarg
);
413 case 'x': parse_redir_locx(optarg
);
415 default : usage(prog
);
421 openlog(basename(prog
), LOG_PID
, 0);
423 syslog(LOG_INFO
,"slirpvde started");
425 if(getcwd(pidfile_path
, PATH_MAX
-1) == NULL
) {
426 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
430 conn
=vde_open(sockname
,"slirpvde:",&open_args
);
433 printlog(LOG_ERR
, "Could not connect to the VDE switch at '%s': %s",
434 sockname
, strerror(errno
));
438 strncat(pidfile_path
, "/", sizeof(pidfile_path
) - strlen(pidfile_path
) -1);
439 if (daemonize
&& daemon(0, 0)) {
440 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
444 if(pidfile
) save_pidfile();
458 slirp_select_fill(&nfds
,&rs
,&ws
,&xs
);
459 datafd
= vde_datafd(conn
);
460 ctlfd
= vde_ctlfd(conn
);
462 if (datafd
< 0 || ctlfd
< 0)
464 printlog(LOG_ERR
, "Wrong file descriptor(s) for the VDE plug: (%d, %d)",
471 if (datafd
>nfds
) nfds
=datafd
;
472 if (ctlfd
>nfds
) nfds
=ctlfd
;
473 result
=select(nfds
+1,&rs
,&ws
,&xs
,NULL
);
474 //printf("SELECT %d %d\n",nfds,result);
475 if (FD_ISSET(datafd
,&rs
)) {
476 nx
=vde_recv(conn
,bufin
,BUFSIZE
,0);
477 //fprintf(stderr,"TX to slirp %d\n",nx);
479 slirp_input(bufin
,nx
);
480 //fprintf(stderr,"TX to slirp %d exit\n",nx);
483 //fprintf(stderr,"slirp poll\n");
484 slirp_select_poll(&rs
,&ws
,&xs
);
485 //fprintf(stderr,"slirp poll exit\n");
487 if (FD_ISSET(ctlfd
,&rs
)) {
488 if(read(ctlfd
,bufin
,BUFSIZE
)==0)