1 /* Copyright 2003 Renzo Davoli
2 * Licensed under the GPL
13 #include <sys/ioctl.h>
14 #include <sys/socket.h>
23 #define SWITCH_MAGIC 0xfeedface
29 enum request_type
{ REQ_NEW_CONTROL
};
36 enum request_type type
;
37 struct sockaddr_un sock
;
38 char description
[MAXDESCR
];
41 static struct sockaddr_un inpath
;
43 static int send_fd(char *name
, int fddata
, struct sockaddr_un
*datasock
, int port
, char *g
, int m
)
46 struct request_v3 req
;
50 struct passwd
*callerpwd
;
52 struct sockaddr_un sock
;
54 callerpwd
=getpwuid(getuid());
55 if((fdctl
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0){
59 sock
.sun_family
= AF_UNIX
;
60 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s/ctl", name
);
61 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
62 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s", name
); /* FALLBACK TO VDE v1 */
63 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
69 req
.magic
=SWITCH_MAGIC
;
71 req
.type
=REQ_NEW_CONTROL
+((port
> 0)?port
<< 8:0);
73 req
.sock
.sun_family
=AF_UNIX
;
74 snprintf(req
.sock
.sun_path
, sizeof(req
.sock
.sun_path
), "%s_%05d", name
, pid
);
75 memcpy(&inpath
,&req
.sock
,sizeof(req
.sock
));
77 snprintf(req
.description
,MAXDESCR
,"slirpvde user=%s PID=%d SOCK=%s",
78 callerpwd
->pw_name
,pid
,req
.sock
.sun_path
);
81 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0){
86 if (send(fdctl
,&req
,sizeof(req
)-MAXDESCR
+strlen(req
.description
),0) < 0) {
91 if (recv(fdctl
,datasock
,sizeof(struct sockaddr_un
),0)<0) {
97 if ((gs
=getgrnam(g
)) == NULL
)
101 chown(inpath
.sun_path
,-1,gid
);
104 chmod(inpath
.sun_path
,m
);
109 static void cleanup(void)
111 unlink(inpath
.sun_path
);
114 static void sig_handler(int sig
)
117 signal(sig
, SIG_DFL
);
121 static void setsighandlers()
123 /* setting signal handlers.
124 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
125 * ignores all the others signals which could cause termination. */
126 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
127 { SIGHUP
, "SIGHUP", 0 },
128 { SIGINT
, "SIGINT", 0 },
129 { SIGPIPE
, "SIGPIPE", 1 },
130 { SIGALRM
, "SIGALRM", 1 },
131 { SIGTERM
, "SIGTERM", 0 },
132 { SIGUSR1
, "SIGUSR1", 1 },
133 { SIGUSR2
, "SIGUSR2", 1 },
134 { SIGPOLL
, "SIGPOLL", 1 },
135 { SIGPROF
, "SIGPROF", 1 },
136 { SIGVTALRM
, "SIGVTALRM", 1 },
137 { SIGSTKFLT
, "SIGSTKFLT", 1 },
138 { SIGIO
, "SIGIO", 1 },
139 { SIGPWR
, "SIGPWR", 1 },
140 { SIGUNUSED
, "SIGUNUSED", 1 },
145 for(i
= 0; signals
[i
].sig
!= 0; i
++)
146 if(signal(signals
[i
].sig
,
147 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
148 perror("Setting handler");
151 unsigned char bufin
[BUFSIZE
];
156 int slirp_can_output(void)
162 static struct sockaddr_un dataout
;
165 #define convery2ascii(x) ((x)>=' ' && (x) <= '~')?(x):'.'
166 void dumppkt(const uint8_t *pkt
, int pkt_len
)
169 printf("Packet dump len=%d\n",pkt_len
);
172 for (i
=0;i
<((pkt_len
-1)/16)+1;i
++) {
174 if (i
*16+j
> pkt_len
)
177 printf("%02x ",pkt
[i
*16+j
]);
180 if (i
*16+j
> pkt_len
)
183 printf("%c",convery2ascii(pkt
[i
*16+j
]));
189 void slirp_output(const uint8_t *pkt
, int pkt_len
)
192 //fprintf(stderr,"RX from slirp %d\n",pkt_len);
193 //dumppkt(pkt,pkt_len);
194 sendto(fddata
,pkt
,pkt_len
,0,(struct sockaddr
*) &dataout
, sizeof(struct sockaddr_un
));
197 void usage(char *name
) {
198 fprintf(stderr
,"Usage: %s [-socket vdesock] [-dhcp] [-network netaddr] \n\t%s [-s vdesock] [-d] [-n netaddr]\n",name
,name
);
202 struct option slirpvdeopts
[] = {
203 {"socket",1,NULL
,'s'},
205 {"vdesock",1,NULL
,'s'},
208 {"network",0,NULL
,'n'},
214 int main(int argc
, char **argv
)
217 struct sockaddr_un datain
;
230 filename
=basename(argv
[0]);
231 sockname
="/tmp/vde.ctl";
233 while ((opt
=getopt_long_only(argc
,argv
,"s:n:p:g:m:d",slirpvdeopts
,&longindx
)) > 0) {
235 case 's' : sockname
=optarg
;
237 case 'd' : dhcpmgmt
= 1;
239 case 'n' : netw
=optarg
;
241 case 'm' : sscanf(optarg
,"%o",&mode
);
243 case 'g' : group
=strdup(optarg
);
245 case 'p' : port
=atoi(optarg
);
247 default : usage(filename
);
253 if((fddata
= socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0){
257 connected_fd
=send_fd(sockname
, fddata
, &dataout
, port
, group
, mode
);
265 slirp_select_fill(&nfds
,&rs
,&ws
,&xs
);
267 FD_SET(connected_fd
,&rs
);
268 if (fddata
>nfds
) nfds
=fddata
;
269 if (connected_fd
>nfds
) nfds
=connected_fd
;
270 result
=select(nfds
+1,&rs
,&ws
,&xs
,NULL
);
271 //printf("SELECT %d %d\n",nfds,result);
272 if (FD_ISSET(connected_fd
,&rs
)) {
273 if(read(connected_fd
,bufin
,BUFSIZE
)==0)
276 if (FD_ISSET(fddata
,&rs
)) {
277 nx
=recvfrom(fddata
,bufin
,BUFSIZE
,0,(struct sockaddr
*) &datain
, &datainsize
);
278 //fprintf(stderr,"TX to slirp %d\n",nx);
280 slirp_input(bufin
,nx
);
281 //fprintf(stderr,"TX to slirp %d exit\n",nx);
284 //fprintf(stderr,"slirp poll\n");
285 slirp_select_poll(&rs
,&ws
,&xs
);
286 //fprintf(stderr,"slirp poll exit\n");