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>
31 #define SWITCH_MAGIC 0xfeedface
36 static char *pidfile
= NULL
;
37 static char pidfile_path
[_POSIX_PATH_MAX
];
41 void printlog(int priority
, const char *format
, ...)
45 va_start (arg
, format
);
48 vsyslog(priority
,format
,arg
);
50 fprintf(stderr
,"%s: ",prog
);
51 vfprintf(stderr
,format
,arg
);
57 enum request_type
{ REQ_NEW_CONTROL
};
64 enum request_type type
;
65 struct sockaddr_un sock
;
66 char description
[MAXDESCR
];
69 static struct sockaddr_un inpath
;
71 static int send_fd(char *name
, int fddata
, struct sockaddr_un
*datasock
, int port
, char *g
, int m
)
74 struct request_v3 req
;
78 struct passwd
*callerpwd
;
80 struct sockaddr_un sock
;
82 callerpwd
=getpwuid(getuid());
83 if((fdctl
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0){
92 if(name
[strlen(name
)-1] == ']' && (split
=rindex(name
,'[')) != NULL
) {
96 if (*name
==0) name
=VDESTDSOCK
;
100 sock
.sun_family
= AF_UNIX
;
101 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s/ctl", name
);
102 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
103 if (name
== VDESTDSOCK
) {
105 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s/ctl", name
);
106 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
107 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s", name
);
108 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
116 req
.magic
=SWITCH_MAGIC
;
118 req
.type
=REQ_NEW_CONTROL
+(port
<< 8);
119 req
.sock
.sun_family
=AF_UNIX
;
121 /* First choice, return socket from the switch close to the control dir*/
122 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
123 sprintf(req
.sock
.sun_path
, "%s.%05d-%02d", name
, pid
, 0);
124 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0){
125 /* if it is not possible -> /tmp */
126 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
127 sprintf(req
.sock
.sun_path
, "/tmp/vde.%05d-%02d", pid
, 0);
128 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0) {
134 snprintf(req
.description
,MAXDESCR
,"slirpvde user=%s PID=%d SOCK=%s",
135 callerpwd
->pw_name
,pid
,req
.sock
.sun_path
);
136 memcpy(&inpath
,&req
.sock
,sizeof(req
.sock
));
138 if (send(fdctl
,&req
,sizeof(req
)-MAXDESCR
+strlen(req
.description
),0) < 0) {
143 if (recv(fdctl
,datasock
,sizeof(struct sockaddr_un
),0)<0) {
149 if ((gs
=getgrnam(g
)) == NULL
)
153 chown(inpath
.sun_path
,-1,gid
);
156 chmod(inpath
.sun_path
,m
);
161 static void save_pidfile()
163 if(pidfile
[0] != '/')
164 strncat(pidfile_path
, pidfile
, PATH_MAX
- strlen(pidfile_path
));
166 strcpy(pidfile_path
, pidfile
);
168 int fd
= open(pidfile_path
,
169 O_WRONLY
| O_CREAT
| O_EXCL
,
170 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
174 printlog(LOG_ERR
, "Error in pidfile creation: %s", strerror(errno
));
178 if((f
= fdopen(fd
, "w")) == NULL
) {
179 printlog(LOG_ERR
, "Error in FILE* construction: %s", strerror(errno
));
183 if(fprintf(f
, "%ld\n", (long int)getpid()) <= 0) {
184 printlog(LOG_ERR
, "Error in writing pidfile");
191 static void cleanup(void)
193 if((pidfile
!= NULL
) && unlink(pidfile_path
) < 0) {
194 printlog(LOG_WARNING
,"Couldn't remove pidfile '%s': %s", pidfile
, strerror(errno
));
196 unlink(inpath
.sun_path
);
199 static void sig_handler(int sig
)
202 signal(sig
, SIG_DFL
);
206 static void setsighandlers()
208 /* setting signal handlers.
209 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
210 * ignores all the others signals which could cause termination. */
211 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
212 { SIGHUP
, "SIGHUP", 0 },
213 { SIGINT
, "SIGINT", 0 },
214 { SIGPIPE
, "SIGPIPE", 1 },
215 { SIGALRM
, "SIGALRM", 1 },
216 { SIGTERM
, "SIGTERM", 0 },
217 { SIGUSR1
, "SIGUSR1", 1 },
218 { SIGUSR2
, "SIGUSR2", 1 },
219 { SIGPROF
, "SIGPROF", 1 },
220 { SIGVTALRM
, "SIGVTALRM", 1 },
222 { SIGPOLL
, "SIGPOLL", 1 },
223 { SIGSTKFLT
, "SIGSTKFLT", 1 },
224 { SIGIO
, "SIGIO", 1 },
225 { SIGPWR
, "SIGPWR", 1 },
226 { SIGUNUSED
, "SIGUNUSED", 1 },
229 { SIGXCPU
, "SIGXCPU", 1 },
230 { SIGXFSZ
, "SIGXFSZ", 1 },
236 for(i
= 0; signals
[i
].sig
!= 0; i
++)
237 if(signal(signals
[i
].sig
,
238 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
239 perror("Setting handler");
242 unsigned char bufin
[BUFSIZE
];
244 int slirp_can_output(void)
250 static struct sockaddr_un dataout
;
253 #define convery2ascii(x) ((x)>=' ' && (x) <= '~')?(x):'.'
254 void dumppkt(const uint8_t *pkt
, int pkt_len
)
257 printf("Packet dump len=%d\n",pkt_len
);
260 for (i
=0;i
<((pkt_len
-1)/16)+1;i
++) {
262 if (i
*16+j
> pkt_len
)
265 printf("%02x ",pkt
[i
*16+j
]);
268 if (i
*16+j
> pkt_len
)
271 printf("%c",convery2ascii(pkt
[i
*16+j
]));
277 void slirp_output(const uint8_t *pkt
, int pkt_len
)
280 //fprintf(stderr,"RX from slirp %d\n",pkt_len);
281 //dumppkt(pkt,pkt_len);
282 sendto(fddata
,pkt
,pkt_len
,0,(struct sockaddr
*) &dataout
, sizeof(struct sockaddr_un
));
285 void usage(char *name
) {
286 fprintf(stderr
,"Usage: %s [-socket vdesock] [-dhcp] [-daemon] [-network netaddr] \n\t%s [-s vdesock] [-D] [-d] [-n netaddr]\n",name
,name
);
290 struct option slirpvdeopts
[] = {
291 {"socket",1,NULL
,'s'},
293 {"vdesock",1,NULL
,'s'},
295 {"pidfile", 1, 0, 'p'},
297 {"daemon",0,NULL
,'d'},
298 {"network",0,NULL
,'n'},
304 int main(int argc
, char **argv
)
319 prog
=basename(argv
[0]);
321 while ((opt
=GETOPT_LONG(argc
,argv
,"s:n:p:g:m:dD",slirpvdeopts
,&longindx
)) > 0) {
323 case 's' : sockname
=optarg
;
325 case 'D' : dhcpmgmt
= 1;
327 case 'd' : daemonize
= 1;
329 case 'n' : netw
=optarg
;
331 case 'm' : sscanf(optarg
,"%o",&mode
);
333 case 'g' : group
=strdup(optarg
);
335 case 'p': pidfile
=strdup(optarg
);
337 case 'P' : port
=atoi(optarg
);
339 default : usage(prog
);
345 openlog(basename(prog
), LOG_PID
, 0);
347 syslog(LOG_INFO
,"slirpvde started");
349 if(getcwd(pidfile_path
, PATH_MAX
-1) == NULL
) {
350 printlog(LOG_ERR
, "getcwd: %s", strerror(errno
));
353 strcat(pidfile_path
, "/");
354 if (daemonize
&& daemon(0, 1)) {
355 printlog(LOG_ERR
,"daemon: %s",strerror(errno
));
359 if((fddata
= socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0){
363 connected_fd
=send_fd(sockname
, fddata
, &dataout
, port
, group
, mode
);
371 slirp_select_fill(&nfds
,&rs
,&ws
,&xs
);
373 FD_SET(connected_fd
,&rs
);
374 if (fddata
>nfds
) nfds
=fddata
;
375 if (connected_fd
>nfds
) nfds
=connected_fd
;
376 result
=select(nfds
+1,&rs
,&ws
,&xs
,NULL
);
377 //printf("SELECT %d %d\n",nfds,result);
378 if (FD_ISSET(fddata
,&rs
)) {
379 nx
=recv(fddata
,bufin
,BUFSIZE
,0);
380 //fprintf(stderr,"TX to slirp %d\n",nx);
382 slirp_input(bufin
,nx
);
383 //fprintf(stderr,"TX to slirp %d exit\n",nx);
386 //fprintf(stderr,"slirp poll\n");
387 slirp_select_poll(&rs
,&ws
,&xs
);
388 //fprintf(stderr,"slirp poll exit\n");
390 if (FD_ISSET(connected_fd
,&rs
)) {
391 if(read(connected_fd
,bufin
,BUFSIZE
)==0)