1 /* Copyright 2003 Renzo Davoli
2 * Licensed under the GPL
3 * Modified by Ludovico Gardenghi 2005
16 #include <sys/ioctl.h>
17 #include <sys/socket.h>
21 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <libvdeplug/libvdeplug.h>
37 # if defined HAVE_SYSLIMITS_H
38 # include <syslimits.h>
39 # elif defined HAVE_SYS_SYSLIMITS_H
40 # include <sys/syslimits.h>
42 # error "No syslimits.h found"
46 #define SWITCH_MAGIC 0xfeedface
52 static char *pidfile
= NULL
;
53 static char pidfile_path
[_POSIX_PATH_MAX
];
58 void printlog(int priority
, const char *format
, ...)
62 va_start (arg
, format
);
65 vsyslog(priority
,format
,arg
);
67 fprintf(stderr
,"%s: ",prog
);
68 vfprintf(stderr
,format
,arg
);
75 static void save_pidfile()
78 strncat(pidfile_path
, pidfile
, PATH_MAX
- strlen(pidfile_path
));
80 strcpy(pidfile_path
, pidfile
);
82 int fd
= open(pidfile_path
,
83 O_WRONLY
| O_CREAT
| O_EXCL
,
84 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
88 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
92 if((f
= fdopen(fd
, "w")) == NULL
) {
93 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
97 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
98 printlog(LOG_ERR
, "Error in writing pidfile");
105 static void cleanup(void)
107 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
108 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
113 static void sig_handler(int sig
)
116 signal(sig
, SIG_DFL
);
120 static void setsighandlers()
122 /* setting signal handlers.
123 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
124 * ignores all the others signals which could cause termination. */
125 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
126 { SIGHUP
, "SIGHUP", 0 },
127 { SIGINT
, "SIGINT", 0 },
128 { SIGPIPE
, "SIGPIPE", 1 },
129 { SIGALRM
, "SIGALRM", 1 },
130 { SIGTERM
, "SIGTERM", 0 },
131 { SIGUSR1
, "SIGUSR1", 1 },
132 { SIGUSR2
, "SIGUSR2", 1 },
133 { SIGPROF
, "SIGPROF", 1 },
134 { SIGVTALRM
, "SIGVTALRM", 1 },
136 { SIGPOLL
, "SIGPOLL", 1 },
138 { SIGSTKFLT
, "SIGSTKFLT", 1 },
140 { SIGIO
, "SIGIO", 1 },
141 { SIGPWR
, "SIGPWR", 1 },
143 { SIGUNUSED
, "SIGUNUSED", 1 },
147 { SIGXCPU
, "SIGXCPU", 1 },
148 { SIGXFSZ
, "SIGXFSZ", 1 },
154 for(i
= 0; signals
[i
].sig
!= 0; i
++)
155 if(signal(signals
[i
].sig
,
156 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
157 perror("Setting handler");
160 unsigned char bufin
[BUFSIZE
];
162 int slirp_can_output(void)
169 #define convery2ascii(x) ((x)>=' ' && (x) <= '~')?(x):'.'
170 void dumppkt(const uint8_t *pkt
, int pkt_len
)
173 printf("Packet dump len=%d\n",pkt_len
);
176 for (i
=0;i
<((pkt_len
-1)/16)+1;i
++) {
178 if (i
*16+j
> pkt_len
)
181 printf("%02x ",pkt
[i
*16+j
]);
184 if (i
*16+j
> pkt_len
)
187 printf("%c",convery2ascii(pkt
[i
*16+j
]));
193 void slirp_output(const uint8_t *pkt
, int pkt_len
)
196 //fprintf(stderr,"RX from slirp %d\n",pkt_len);
197 //dumppkt(pkt,pkt_len);
198 vde_send(conn
,pkt
,pkt_len
,0);
213 struct redirtcp
*next
;
216 static struct redirtcp
*parse_redir_tcp(struct redirtcp
*head
, char *buff
)
221 char *ipaddrstr
=NULL
;
223 struct redirtcp
*new;
225 if ((ipaddrstr
= strchr(buff
, ':'))) {
227 if (*ipaddrstr
== 0) {
228 fprintf(stderr
,"redir TCP syntax error\n");
232 if ((portstr
= strchr(ipaddrstr
, ':'))) {
235 fprintf(stderr
,"redir TCP syntax error\n");
240 sscanf(buff
,"%d",&lport
);
241 sscanf(portstr
,"%d",&port
);
243 inaddr
= inet_addr(ipaddrstr
);
246 fprintf(stderr
,"TCP redirection error: an IP address must be specified\r\n");
250 if ((new=malloc(sizeof(struct redirtcp
)))==NULL
)
261 static struct redirx
*parse_redir_x(struct redirx
*head
, char *buff
)
264 u_int32_t inaddr
= 0;
269 if ((ptr
= strchr(buff
, ':'))) {
272 fprintf(stderr
,"X-redirection syntax error\n");
277 inaddr
= inet_addr(buff
);
278 if (inaddr
== 0xffffffff) {
279 fprintf(stderr
,"Error: X-redirection bad address\r\n");
284 if (strchr(ptr
, '.')) {
285 if (sscanf(ptr
, "%d.%d", &display
, &screen
) != 2)
288 if (sscanf(ptr
, "%d", &display
) != 1)
294 fprintf(stderr
,"Error: X-redirection an IP address must be specified\r\n");
298 if ((new=malloc(sizeof(struct redirx
)))==NULL
)
302 new->display
=display
;
304 new->start_port
=start_port
;
310 static void do_redir_tcp(struct redirtcp
*head
)
313 do_redir_tcp(head
->next
);
314 redir_tcp(head
->inaddr
,head
->port
,head
->lport
);
319 static void do_redir_x(struct redirx
*head
)
322 do_redir_x(head
->next
);
323 redir_x(head
->inaddr
,head
->start_port
,head
->display
,head
->screen
);
328 void usage(char *name
) {
331 " %s [-socket vdesock] [-dhcp] [-daemon] [-network netaddr] \n"
332 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n"
333 " %s [-s vdesock] [-D] [-d] [-n netaddr]\n"
334 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n" ,name
,name
);
338 struct option slirpvdeopts
[] = {
339 {"socket",1,NULL
,'s'},
341 {"vdesock",1,NULL
,'s'},
343 {"pidfile", 1, 0, 'p'},
345 {"daemon",0,NULL
,'d'},
346 {"network",0,NULL
,'n'},
352 int main(int argc
, char **argv
)
362 struct redirtcp
*rtcp
=NULL
;
363 struct redirx
*rx
=NULL
;
364 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
366 prog
=basename(argv
[0]);
368 while ((opt
=GETOPT_LONG(argc
,argv
,"s:n:p:g:m:L:X:dD",slirpvdeopts
,&longindx
)) > 0) {
370 case 's' : sockname
=optarg
;
372 case 'D' : dhcpmgmt
= 1;
374 case 'd' : daemonize
= 1;
376 case 'n' : netw
=optarg
;
378 case 'm' : sscanf(optarg
,"%o",&(open_args
.mode
));
380 case 'g' : open_args
.group
=strdup(optarg
);
382 case 'p': pidfile
=strdup(optarg
);
384 case 'P' : open_args
.port
=atoi(optarg
);
386 case 'L': rtcp
=parse_redir_tcp(rtcp
,optarg
);
388 case 'X': rx
=parse_redir_x(rx
,optarg
);
390 default : usage(prog
);
396 openlog(basename(prog
), LOG_PID
, 0);
398 syslog(LOG_INFO
,"slirpvde started");
400 if(getcwd(pidfile_path
, PATH_MAX
-1) == NULL
) {
401 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
404 strcat(pidfile_path
, "/");
405 if (daemonize
&& daemon(0, 0)) {
406 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
410 if(pidfile
) save_pidfile();
412 conn
=vde_open(sockname
,"slirpvde:",&open_args
);
425 slirp_select_fill(&nfds
,&rs
,&ws
,&xs
);
426 datafd
=vde_datafd(conn
);
427 ctlfd
=vde_ctlfd(conn
);
430 if (datafd
>nfds
) nfds
=datafd
;
431 if (ctlfd
>nfds
) nfds
=ctlfd
;
432 result
=select(nfds
+1,&rs
,&ws
,&xs
,NULL
);
433 //printf("SELECT %d %d\n",nfds,result);
434 if (FD_ISSET(datafd
,&rs
)) {
435 nx
=vde_recv(conn
,bufin
,BUFSIZE
,0);
436 //fprintf(stderr,"TX to slirp %d\n",nx);
438 slirp_input(bufin
,nx
);
439 //fprintf(stderr,"TX to slirp %d exit\n",nx);
442 //fprintf(stderr,"slirp poll\n");
443 slirp_select_poll(&rs
,&ws
,&xs
);
444 //fprintf(stderr,"slirp poll exit\n");
446 if (FD_ISSET(ctlfd
,&rs
)) {
447 if(read(ctlfd
,bufin
,BUFSIZE
)==0)