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 <libvdeplug/libvdeplug.h>
34 #include <syslimits.h>
37 #define SWITCH_MAGIC 0xfeedface
43 static char *pidfile
= NULL
;
44 static char pidfile_path
[_POSIX_PATH_MAX
];
49 void printlog(int priority
, const char *format
, ...)
53 va_start (arg
, format
);
56 vsyslog(priority
,format
,arg
);
58 fprintf(stderr
,"%s: ",prog
);
59 vfprintf(stderr
,format
,arg
);
66 static void save_pidfile()
69 strncat(pidfile_path
, pidfile
, PATH_MAX
- strlen(pidfile_path
));
71 strcpy(pidfile_path
, pidfile
);
73 int fd
= open(pidfile_path
,
74 O_WRONLY
| O_CREAT
| O_EXCL
,
75 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
79 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
83 if((f
= fdopen(fd
, "w")) == NULL
) {
84 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
88 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
89 printlog(LOG_ERR
, "Error in writing pidfile");
96 static void cleanup(void)
98 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
99 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
104 static void sig_handler(int sig
)
107 signal(sig
, SIG_DFL
);
111 static void setsighandlers()
113 /* setting signal handlers.
114 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
115 * ignores all the others signals which could cause termination. */
116 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
117 { SIGHUP
, "SIGHUP", 0 },
118 { SIGINT
, "SIGINT", 0 },
119 { SIGPIPE
, "SIGPIPE", 1 },
120 { SIGALRM
, "SIGALRM", 1 },
121 { SIGTERM
, "SIGTERM", 0 },
122 { SIGUSR1
, "SIGUSR1", 1 },
123 { SIGUSR2
, "SIGUSR2", 1 },
124 { SIGPROF
, "SIGPROF", 1 },
125 { SIGVTALRM
, "SIGVTALRM", 1 },
127 { SIGPOLL
, "SIGPOLL", 1 },
128 { SIGSTKFLT
, "SIGSTKFLT", 1 },
129 { SIGIO
, "SIGIO", 1 },
130 { SIGPWR
, "SIGPWR", 1 },
131 { SIGUNUSED
, "SIGUNUSED", 1 },
134 { SIGXCPU
, "SIGXCPU", 1 },
135 { SIGXFSZ
, "SIGXFSZ", 1 },
141 for(i
= 0; signals
[i
].sig
!= 0; i
++)
142 if(signal(signals
[i
].sig
,
143 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
144 perror("Setting handler");
147 unsigned char bufin
[BUFSIZE
];
149 int slirp_can_output(void)
156 #define convery2ascii(x) ((x)>=' ' && (x) <= '~')?(x):'.'
157 void dumppkt(const uint8_t *pkt
, int pkt_len
)
160 printf("Packet dump len=%d\n",pkt_len
);
163 for (i
=0;i
<((pkt_len
-1)/16)+1;i
++) {
165 if (i
*16+j
> pkt_len
)
168 printf("%02x ",pkt
[i
*16+j
]);
171 if (i
*16+j
> pkt_len
)
174 printf("%c",convery2ascii(pkt
[i
*16+j
]));
180 void slirp_output(const uint8_t *pkt
, int pkt_len
)
183 //fprintf(stderr,"RX from slirp %d\n",pkt_len);
184 //dumppkt(pkt,pkt_len);
185 vde_send(conn
,pkt
,pkt_len
,0);
200 struct redirtcp
*next
;
203 static struct redirtcp
*parse_redir_tcp(struct redirtcp
*head
, char *buff
)
208 char *ipaddrstr
=NULL
;
210 struct redirtcp
*new;
212 if ((ipaddrstr
= strchr(buff
, ':'))) {
214 if (*ipaddrstr
== 0) {
215 fprintf(stderr
,"redir TCP syntax error\n");
219 if ((portstr
= strchr(ipaddrstr
, ':'))) {
222 fprintf(stderr
,"redir TCP syntax error\n");
227 sscanf(buff
,"%d",&lport
);
228 sscanf(portstr
,"%d",&port
);
230 inaddr
= inet_addr(ipaddrstr
);
233 fprintf(stderr
,"TCP redirection error: an IP address must be specified\r\n");
237 if ((new=malloc(sizeof(struct redirtcp
)))==NULL
)
248 static struct redirx
*parse_redir_x(struct redirx
*head
, char *buff
)
251 u_int32_t inaddr
= 0;
256 if ((ptr
= strchr(buff
, ':'))) {
259 fprintf(stderr
,"X-redirection syntax error\n");
264 inaddr
= inet_addr(buff
);
265 if (inaddr
== 0xffffffff) {
266 fprintf(stderr
,"Error: X-redirection bad address\r\n");
271 if (strchr(ptr
, '.')) {
272 if (sscanf(ptr
, "%d.%d", &display
, &screen
) != 2)
275 if (sscanf(ptr
, "%d", &display
) != 1)
281 fprintf(stderr
,"Error: X-redirection an IP address must be specified\r\n");
285 if ((new=malloc(sizeof(struct redirx
)))==NULL
)
289 new->display
=display
;
291 new->start_port
=start_port
;
297 static void do_redir_tcp(struct redirtcp
*head
)
300 do_redir_tcp(head
->next
);
301 redir_tcp(head
->inaddr
,head
->port
,head
->lport
);
306 static void do_redir_x(struct redirx
*head
)
309 do_redir_x(head
->next
);
310 redir_x(head
->inaddr
,head
->start_port
,head
->display
,head
->screen
);
315 void usage(char *name
) {
318 " %s [-socket vdesock] [-dhcp] [-daemon] [-network netaddr] \n"
319 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n"
320 " %s [-s vdesock] [-D] [-d] [-n netaddr]\n"
321 "\t [-L host_port:guest_addr:guest_port] [-X guest_addr[:display[.screen]]] \n" ,name
,name
);
325 struct option slirpvdeopts
[] = {
326 {"socket",1,NULL
,'s'},
328 {"vdesock",1,NULL
,'s'},
330 {"pidfile", 1, 0, 'p'},
332 {"daemon",0,NULL
,'d'},
333 {"network",0,NULL
,'n'},
339 int main(int argc
, char **argv
)
349 struct redirtcp
*rtcp
=NULL
;
350 struct redirx
*rx
=NULL
;
351 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
353 prog
=basename(argv
[0]);
355 while ((opt
=GETOPT_LONG(argc
,argv
,"s:n:p:g:m:L:X:dD",slirpvdeopts
,&longindx
)) > 0) {
357 case 's' : sockname
=optarg
;
359 case 'D' : dhcpmgmt
= 1;
361 case 'd' : daemonize
= 1;
363 case 'n' : netw
=optarg
;
365 case 'm' : sscanf(optarg
,"%o",&(open_args
.mode
));
367 case 'g' : open_args
.group
=strdup(optarg
);
369 case 'p': pidfile
=strdup(optarg
);
371 case 'P' : open_args
.port
=atoi(optarg
);
373 case 'L': rtcp
=parse_redir_tcp(rtcp
,optarg
);
375 case 'X': rx
=parse_redir_x(rx
,optarg
);
377 default : usage(prog
);
383 openlog(basename(prog
), LOG_PID
, 0);
385 syslog(LOG_INFO
,"slirpvde started");
387 if(getcwd(pidfile_path
, PATH_MAX
-1) == NULL
) {
388 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
391 strcat(pidfile_path
, "/");
392 if (daemonize
&& daemon(0, 1)) {
393 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
397 conn
=vde_open(sockname
,"slirpvde:",&open_args
);
410 slirp_select_fill(&nfds
,&rs
,&ws
,&xs
);
411 datafd
=vde_datafd(conn
);
412 ctlfd
=vde_ctlfd(conn
);
415 if (datafd
>nfds
) nfds
=datafd
;
416 if (ctlfd
>nfds
) nfds
=ctlfd
;
417 result
=select(nfds
+1,&rs
,&ws
,&xs
,NULL
);
418 //printf("SELECT %d %d\n",nfds,result);
419 if (FD_ISSET(datafd
,&rs
)) {
420 nx
=vde_recv(conn
,bufin
,BUFSIZE
,0);
421 //fprintf(stderr,"TX to slirp %d\n",nx);
423 slirp_input(bufin
,nx
);
424 //fprintf(stderr,"TX to slirp %d exit\n",nx);
427 //fprintf(stderr,"slirp poll\n");
428 slirp_select_poll(&rs
,&ws
,&xs
);
429 //fprintf(stderr,"slirp poll exit\n");
431 if (FD_ISSET(ctlfd
,&rs
)) {
432 if(read(ctlfd
,bufin
,BUFSIZE
)==0)