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
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
24 #define SWITCH_MAGIC 0xfeedface
29 enum request_type
{ REQ_NEW_CONTROL
};
34 enum request_type type
;
35 struct sockaddr_un sock
;
36 char description
[MAXDESCR
];
39 static struct passwd
*callerpwd
;
44 static int send_fd(char *name
, int fddata
, struct sockaddr_un
*datasock
, int intno
, int port
)
47 struct request_v3 req
;
49 struct sockaddr_un sock
;
51 if((fdctl
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0){
60 if(name
[strlen(name
)-1] == ']' && (split
=rindex(name
,'[')) != NULL
) {
64 if (*name
==0) name
=VDESTDSOCK
;
68 sock
.sun_family
= AF_UNIX
;
69 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s/ctl", name
);
70 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
71 if (name
== VDESTDSOCK
) {
73 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s/ctl", name
);
74 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
75 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s", name
);
76 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
84 req
.magic
=SWITCH_MAGIC
;
86 req
.type
=REQ_NEW_CONTROL
+(port
<< 8);
87 req
.sock
.sun_family
=AF_UNIX
;
89 /* First choice, return socket from the switch close to the control dir*/
90 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
91 sprintf(req
.sock
.sun_path
, "%s.%05d-%02d", name
, pid
, intno
);
92 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0){
93 /* if it is not possible -> /tmp */
94 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
95 sprintf(req
.sock
.sun_path
, "/tmp/vde.%05d-%02d", pid
, intno
);
96 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0) {
102 snprintf(req
.description
,MAXDESCR
,"vdeqemu user=%s PID=%d SOCK=%s INT=%d",
103 callerpwd
->pw_name
,pid
,req
.sock
.sun_path
,intno
);
105 inpath
[intno
]=strdup(req
.sock
.sun_path
);
107 if (send(fdctl
,&req
,sizeof(req
),0) < 0) {
112 if (recv(fdctl
,datasock
,sizeof(struct sockaddr_un
),0)<0) {
120 unsigned char bufin
[BUFSIZE
];
122 struct pollfd
*pollv
;
128 static int countnics(const char *s
)
138 static int countnewnics(int argc
,char *argv
[])
141 register int netflag
=0;
143 if (strcmp(argv
[0],"-net")==0)
146 if (netflag
&& (strncmp(argv
[0],"vde",3)==0))
156 static void usage(void)
158 if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0)
159 fprintf(stderr
,"Usage: %s [-h]\n"
160 "\t %s ...qemu options... -net vde[,vlan=n][,sock=sock] ... \n"
162 "\t %s [-sock sock1 [,sock2...]] qemu_options\n"
163 "\t (%s executes a qemu machine named %s)\n", vdeqname
,vdeqname
,vdeqname
,vdeqname
,filename
);
165 fprintf(stderr
,"Usage: %s [-h]\n"
166 "\t %s qemu_executable ...qemu options... -net vde[,vlan=n][,sock=sock] ... \n"
168 "\t %s qemu_executable [-sock sock1 [,sock2...]] qemu_options\n", vdeqname
,vdeqname
, vdeqname
);
172 static void cleanup()
175 for (i
=0; i
<nb_nics
; i
++) {
176 if (inpath
[i
] != NULL
)
181 static void leave(void)
183 fprintf(stderr
,"qemu exited: %s quits\n", vdeqname
);
188 static int checkver(char *prog
)
199 if ((f
=fork()) > 0) {
202 len
=read(fd
[0],buf
,256);
205 for(i
=0;i
<len
&& version
==0;i
++) {
206 if(strncmp(buf
+i
,"version ",8)==0) {
208 sscanf(buf
+i
+8,"%d.%d.%d",&v1
,&v2
,&v3
);
209 version
=(v1
<< 16) + (v2
<< 8) + v3
;
213 waitpid(f
,&status
,0);
221 if (execvp(prog
,newargv
) < 0) {
228 static char *parsevdearg(char *arg
,char **sock
,int *pport
, int fd
)
233 while (*arg
==',') arg
++;
234 if (strncmp(arg
,"vlan=",5)==0) {
236 while (*arg
!= 0 && *arg
!= ',')
239 while (*arg
==',') arg
++;
240 if (strncmp(arg
,"sock=",5)==0) {
245 while (*arg
!= 0 && *arg
!= '\"')
249 while (*arg
!= 0 && *arg
!= ',')
256 while (*arg
==',') arg
++;
257 if (strncmp(arg
,"port=",5)==0) {
259 while (*arg
!= 0 && *arg
!= ',')
262 while (*arg
==',') arg
++;
264 snprintf(newarg
,128,"tap,vlan=%d,fd=%d%s%s",vlan
,fd
,(*arg
== 0)?"":",",arg
);
265 return strdup(newarg
);
268 int main(int argc
, char **argv
)
271 char *argsock
,**sockname
;
273 struct sockaddr_un
*dataout
,datain
;
274 socklen_t datainsize
;
288 vdeqname
=basename(argv
[0]);
289 callerpwd
=getpwuid(getuid());
290 /* OLD SYNTAX MGMT */
291 if (strncmp(vdeqname
,"vdeo",4) == 0) {
293 if (strcmp(vdeqname
,"vdeoq") != 0) {
298 else if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0) {
308 if ((ver
=checkver(filename
)) < 0x800)
311 nb_nics
=countnewnics(argc
-args
,argv
+args
);
315 if ((argc
> args
&& (
316 strcmp(argv
[args
],"-h")==0 ||
317 strcmp(argv
[args
],"-help")==0 ||
318 strcmp(argv
[args
],"--help")==0
320 strcmp(filename
,"-h")==0 ||
321 strcmp(filename
,"-help")==0 ||
322 strcmp(filename
,"--help")==0
325 } else if (argc
> args
+1 && (
326 (strcmp(argv
[args
],"-vdesock")==0) ||
327 (strcmp(argv
[args
],"-sock")==0) ||
328 (strcmp(argv
[args
],"-unix")==0) ||
329 (strcmp(argv
[args
],"-s")==0))
331 argsock
=argv
[args
+1];
340 nb_nics
=countnics(argsock
);
341 if (!oldsyntax
&& nb_nics
> 1)
343 "Warning: all the vde connections will be connected to one net interface\n"
344 " to configure several interface use the new syntax -net vde\n");
346 if ((sp
= (pair
*) malloc(nb_nics
* 2 * sizeof (int)))<0) {
347 perror("malloc nics");
350 if ((inpath
=(char **) malloc (nb_nics
* sizeof(char *))) <0) {
351 perror("malloc inpath");
354 memset(inpath
,0,(nb_nics
* sizeof(char *)));
356 for (i
=0; i
<nb_nics
; i
++) {
357 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, sp
[i
]) < 0){
358 perror("socketpair");
363 if ((sockname
= (char **) malloc(sizeof(char *) * nb_nics
))<0) {
364 perror("malloc sockname");
367 if ((ports
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
368 perror("malloc ports");
378 for (i
=0,netflag
=0,vdeint
=0;i
<argc
;i
++) {
379 if (strcmp(argv
[i
],"-net")==0)
382 if (netflag
&& strncmp(argv
[i
],"vde",3) == 0)
384 argv
[i
]=parsevdearg(argv
[i
]+3,&sockname
[vdeint
],&ports
[vdeint
],sp
[vdeint
][0]);
393 sockname
[0]=VDESTDSOCK
;
396 register char *s
=argsock
;
401 while (*s
!= ',' && *s
!= '\0')
406 } while (oldch
!= 0);
409 /* printf("-- %s --\n",numfd);
410 printf("as %s\n",argsock);
411 for (i=0; i<nb_nics; i++)
412 printf("%d -> %s\n",i,sockname[i]); */
413 newargc
=argc
+3+(2*nb_nics
)-args
;
414 if ((newargv
=(char **) malloc ((newargc
+1)* sizeof(char *))) <0) {
421 for (i
=0; i
<nb_nics
; i
++) {
424 sprintf(numfd
,"%d",sp
[i
][0]);
425 newargv
[2*i
+1]="-tun-fd";
426 newargv
[2*i
+2]=strdup(numfd
);
430 sprintf(nnics
,"%d",nb_nics
);
431 newargv
[2*nb_nics
+1]="-nics";
432 newargv
[2*nb_nics
+2]=strdup(nnics
);
435 for (i
=0; i
<nb_nics
; i
++) {
438 sprintf(numfd
,"tap,vlan=0,fd=%d",sp
[i
][0]);
439 newargv
[2*i
+1]="-net";
440 newargv
[2*i
+2]=strdup(numfd
);
442 newargv
[2*nb_nics
+1]="-net";
443 newargv
[2*nb_nics
+2]="nic";
445 for (i
=(2*nb_nics
)+3;args
<argc
;i
++,args
++) newargv
[i
]=argv
[args
];
450 if ((fddata
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
451 perror("malloc fddata");
454 if ((connected_fd
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
455 perror("malloc connected_fd");
458 if ((dataout
= (struct sockaddr_un
*) malloc(sizeof(struct sockaddr_un
) * nb_nics
))<0) {
459 perror("malloc dataout");
463 if ((pollv
= (struct pollfd
*) malloc(sizeof(struct pollfd
) * 2 * nb_nics
))<0) {
464 perror("malloc fddata");
467 for (i
=0; i
<nb_nics
; i
++) {
468 if((fddata
[i
] = socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0){
472 connected_fd
[i
]=send_fd(sockname
[i
], fddata
[i
], &(dataout
[i
]), i
, ports
[i
]);
473 pollv
[2*i
+1].fd
=fddata
[i
];
474 pollv
[2*i
].fd
=sp
[i
][1];
475 pollv
[2*i
].events
= pollv
[2*i
+1].events
=POLLIN
|POLLHUP
;
480 signal(SIGCHLD
, leave
);
481 for (i
=0; i
<nb_nics
; i
++)
484 result
=poll(pollv
,2*nb_nics
,-1);
485 for (i
=0; i
<nb_nics
; i
++) {
486 if (pollv
[2*i
].revents
& POLLHUP
|| pollv
[2*i
+1].revents
& POLLHUP
)
488 if (pollv
[2*i
].revents
& POLLIN
) {
489 nx
=read(sp
[i
][1],bufin
,sizeof(bufin
));
490 //fprintf(stderr,"RX from qemu %d\n",nx);
491 //send(connected_fd,bufin,nx,0);
492 sendto(fddata
[i
],bufin
,nx
,0,(struct sockaddr
*) &(dataout
[i
]), sizeof(struct sockaddr_un
));
494 if (pollv
[2*i
+1].revents
& POLLIN
) {
495 datainsize
=sizeof(datain
);
496 nx
=recvfrom(fddata
[i
],bufin
,BUFSIZE
,0,(struct sockaddr
*) &datain
, &datainsize
);
497 //fprintf(stderr,"TX to qemu %d\n",nx);
498 write(sp
[i
][1],bufin
,nx
);
503 for (i
=0; i
<nb_nics
; i
++) {
506 close(connected_fd
[i
]);
508 execvp(filename
,newargv
);