1 /* Copyright 2003 Renzo Davoli
2 * TNX: 2005.11.18 new syntax mgmt patch by Iain McFarlane <imcfarla@tiscali.co.uk>
3 * Licensed under the GPL
14 #include <sys/ioctl.h>
15 #include <sys/socket.h>
22 #define SWITCH_MAGIC 0xfeedface
26 enum request_type
{ REQ_NEW_CONTROL
};
31 enum request_type type
;
32 struct sockaddr_un sock
;
36 static int send_fd(char *name
, int fddata
, struct sockaddr_un
*datasock
, int intno
, int group
)
39 struct request_v3 req
;
42 struct sockaddr_un sock
;
44 if((fdctl
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0){
49 sock
.sun_family
= AF_UNIX
;
50 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s", name
);
51 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
56 req
.magic
=SWITCH_MAGIC
;
58 req
.type
=REQ_NEW_CONTROL
+((group
> 0)?((geteuid()<<8) + group
) << 8:0);
60 req
.sock
.sun_family
=AF_UNIX
;
61 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
62 sprintf(&req
.sock
.sun_path
[1], "%5d-%2d", pid
, intno
);
64 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0){
69 if (send(fdctl
,&req
,sizeof(req
),0) < 0) {
74 if (recv(fdctl
,datasock
,sizeof(struct sockaddr_un
),0)<0) {
82 unsigned char bufin
[BUFSIZE
];
90 static int countnics(const char *s
)
100 static int countnewnics(int argc
,char *argv
[])
103 register int netflag
=0;
105 if (strcmp(argv
[0],"-net")==0)
108 if (netflag
&& (strncmp(argv
[0],"vde",3)==0))
120 if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0)
121 fprintf(stderr
,"Usage: %s [-h]\n"
122 "\t %s ...qemu options... -net vde[,vlan=n][,sock=sock] ... \n"
124 "\t %s [-sock sock1 [,sock2...]] qemu_options\n"
125 "\t (%s executes a qemu machine named %s)\n", vdeqname
, vdeqname
,vdeqname
,vdeqname
,filename
);
127 fprintf(stderr
,"Usage: %s [-h]\n"
128 "\t %s qemu_executable ...qemu options... -net vde[,vlan=n][,sock=sock] ... \n"
130 "\t %s qemu_executable [-sock sock1 [,sock2...]] qemu_options\n", vdeqname
, vdeqname
, vdeqname
);
136 fprintf(stderr
,"qemu exited: %s quits\n", vdeqname
);
141 static char *parsevdearg(char *arg
,char **sock
,int fd
)
146 while (*arg
==',') arg
++;
147 if (strncmp(arg
,"vlan=",5)==0) {
149 while (*arg
!= 0 && *arg
!= ',')
152 while (*arg
==',') arg
++;
153 if (strncmp(arg
,"sock=",5)==0) {
158 while (*arg
!= 0 && *arg
!= '\"')
162 while (*arg
!= 0 && *arg
!= ',')
169 while (*arg
==',') arg
++;
170 snprintf(newarg
,128,"tap,vlan=%d,fd=%d%s%s",vlan
,fd
,(*arg
== 0)?"":",",arg
);
171 return strdup(newarg
);
174 int main(int argc
, char **argv
)
177 char *argsock
,**sockname
;
178 struct sockaddr_un
*dataout
,datain
;
194 vdeqname
=basename(argv
[0]);
195 /* OLD SYNTAX MGMT */
196 if (strncmp(vdeqname
,"vdeo",4) == 0) {
198 if (strcmp(vdeqname
,"vdeoq") != 0) {
204 if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0) {
215 nb_nics
=countnewnics(argc
-args
,argv
+args
);
219 if ((argc
> args
&& (
220 strcmp(argv
[args
],"-h")==0 ||
221 strcmp(argv
[args
],"-help")==0 ||
222 strcmp(argv
[args
],"--help")==0
224 strcmp(filename
,"-h")==0 ||
225 strcmp(filename
,"-help")==0 ||
226 strcmp(filename
,"--help")==0
229 } else if (argc
> args
+1 && !newsyntax
&&
230 ((strcmp(argv
[args
],"-vdesock")==0) ||
231 (strcmp(argv
[args
],"-sock")==0) ||
232 (strcmp(argv
[args
],"--sock")==0) ||
233 (strcmp(argv
[args
],"-unix")==0) ||
234 (strcmp(argv
[args
],"-s")==0))
236 argsock
=argv
[args
+1];
245 nb_nics
=countnics(argsock
);
246 if (!oldsyntax
&& nb_nics
> 1)
248 "Warning: all the vde connections will be connected to one net interface\n"
249 " to configure several interface use the new syntax -net vde\n");
251 if ((sp
= (pair
*) malloc(nb_nics
* 2 * sizeof (int)))<0) {
252 perror("malloc nics");
256 for (i
=0; i
<nb_nics
; i
++) {
257 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, sp
[i
]) < 0){
258 perror("socketpair");
263 if ((sockname
= (char **) malloc(sizeof(char *) * nb_nics
))<0) {
264 perror("malloc sockname");
274 for (i
=0,netflag
=0,vdeint
=0;i
<argc
;i
++) {
275 if (strcmp(argv
[i
],"-net")==0)
278 if (netflag
&& strncmp(argv
[i
],"vde",3) == 0)
280 argv
[i
]=parsevdearg(argv
[i
]+3,&sockname
[vdeint
],sp
[vdeint
][0]);
289 sockname
[0]=VDESTDSOCK
;
292 register char *s
=argsock
;
297 while (*s
!= ',' && *s
!= '\0')
302 } while (oldch
!= 0);
305 /* printf("-- %s --\n",numfd);
306 printf("as %s\n",argsock);
307 for (i=0; i<nb_nics; i++)
308 printf("%d -> %s\n",i,sockname[i]); */
309 newargc
=argc
+1+2+(2*nb_nics
)-args
;
310 if ((newargv
=(char **) malloc ((newargc
+1)* sizeof(char *))) <0) {
317 for (i
=0; i
<nb_nics
; i
++) {
319 sprintf(numfd
,"%d",sp
[i
][0]);
320 newargv
[2*i
+1]="-tun-fd";
321 newargv
[2*i
+2]=strdup(numfd
);
325 sprintf(nnics
,"%d",nb_nics
);
326 newargv
[2*nb_nics
+1]="-nics";
327 newargv
[2*nb_nics
+2]=strdup(nnics
);
330 for (i
=0; i
<nb_nics
; i
++) {
332 sprintf(numfd
,"tap,vlan=0,fd=%d",sp
[i
][0]);
333 newargv
[2*i
+1]="-net";
334 newargv
[2*i
+2]=strdup(numfd
);
336 newargv
[2*nb_nics
+1]="-net";
337 newargv
[2*nb_nics
+2]="nic";
339 for (i
=(2*nb_nics
)+3;args
<argc
;i
++,args
++) newargv
[i
]=argv
[args
];
344 if ((fddata
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
345 perror("malloc fddata");
348 if ((connected_fd
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
349 perror("malloc connected_fd");
352 if ((dataout
= (struct sockaddr_un
*) malloc(sizeof(struct sockaddr_un
) * nb_nics
))<0) {
353 perror("malloc dataout");
357 if ((pollv
= (struct pollfd
*) malloc(sizeof(struct pollfd
) * 2 * nb_nics
))<0) {
358 perror("malloc fddata");
361 for (i
=0; i
<nb_nics
; i
++) {
362 if((fddata
[i
] = socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0){
366 connected_fd
[i
]=send_fd(sockname
[i
], fddata
[i
], &(dataout
[i
]), i
, group
);
367 pollv
[2*i
+1].fd
=fddata
[i
];
368 pollv
[2*i
].fd
=sp
[i
][1];
369 pollv
[2*i
].events
= pollv
[2*i
+1].events
=POLLIN
|POLLHUP
;
374 signal(SIGCHLD
, leave
);
375 for (i
=0; i
<nb_nics
; i
++)
378 result
=poll(pollv
,2*nb_nics
,-1);
379 for (i
=0; i
<nb_nics
; i
++) {
380 if (pollv
[2*i
].revents
& POLLHUP
|| pollv
[2*i
+1].revents
& POLLHUP
)
382 if (pollv
[2*i
].revents
& POLLIN
) {
383 nx
=read(sp
[i
][1],bufin
,sizeof(bufin
));
384 //fprintf(stderr,"RX from qemu %d\n",nx);
385 //send(connected_fd,bufin,nx,0);
386 sendto(fddata
[i
],bufin
,nx
,0,(struct sockaddr
*) &(dataout
[i
]), sizeof(struct sockaddr_un
));
388 if (pollv
[2*i
+1].revents
& POLLIN
) {
389 datainsize
=sizeof(datain
);
390 nx
=recvfrom(fddata
[i
],bufin
,BUFSIZE
,0,(struct sockaddr
*) &datain
, &datainsize
);
391 //fprintf(stderr,"TX to qemu %d\n",nx);
392 write(sp
[i
][1],bufin
,nx
);
397 for (i
=0; i
<nb_nics
; i
++) {
400 close(connected_fd
[i
]);
402 execvp(filename
,newargv
);