1 /* Copyright 2003 Renzo Davoli
2 * Licensed under the GPL
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
19 #define SWITCH_MAGIC 0xfeedface
23 enum request_type
{ REQ_NEW_CONTROL
};
28 enum request_type type
;
29 struct sockaddr_un sock
;
33 static int send_fd(char *name
, int fddata
, struct sockaddr_un
*datasock
, int intno
, int group
)
36 struct request_v3 req
;
39 struct sockaddr_un sock
;
41 if((fdctl
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0){
46 sock
.sun_family
= AF_UNIX
;
47 snprintf(sock
.sun_path
, sizeof(sock
.sun_path
), "%s", name
);
48 if(connect(fdctl
, (struct sockaddr
*) &sock
, sizeof(sock
))){
53 req
.magic
=SWITCH_MAGIC
;
55 req
.type
=REQ_NEW_CONTROL
+((group
> 0)?((geteuid()<<8) + group
) << 8:0);
57 req
.sock
.sun_family
=AF_UNIX
;
58 memset(req
.sock
.sun_path
, 0, sizeof(req
.sock
.sun_path
));
59 sprintf(&req
.sock
.sun_path
[1], "%5d-%2d", pid
, intno
);
61 if(bind(fddata
, (struct sockaddr
*) &req
.sock
, sizeof(req
.sock
)) < 0){
66 if (send(fdctl
,&req
,sizeof(req
),0) < 0) {
71 if (recv(fdctl
,datasock
,sizeof(struct sockaddr_un
),0)<0) {
79 unsigned char bufin
[BUFSIZE
];
81 //struct pollfd pollv[]={{STDIN_FILENO,POLLIN|POLLHUP,0},{0,POLLIN|POLLHUP,0}};
89 static int countnics(const char *s
)
101 if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0)
102 fprintf(stderr
,"Usage: %s [-h]\n"
103 "\t %s [-vdesock sock1 [,sock2...]] qemu_options\n"
104 "\t (%s executes a qemu machine named %s)\n", vdeqname
,vdeqname
,vdeqname
,filename
);
106 fprintf(stderr
,"Usage: %s [-h]\n"
107 "\t %s qemu_executable [-vdesock sock1 [,sock2...]] qemu_options\n", vdeqname
, vdeqname
);
113 fprintf(stderr
,"qemu exited: %s quits\n", vdeqname
);
117 int main(int argc
, char **argv
)
120 char *argsock
,**sockname
;
121 struct sockaddr_un
*dataout
,datain
;
135 vdeqname
=basename(argv
[0]);
136 if (strcmp(vdeqname
,"vdeq") != 0 && strncmp(vdeqname
,"vde",3)==0) {
146 if ((argc
> args
&& (
147 strcmp(argv
[args
],"-h")==0 ||
148 strcmp(argv
[args
],"-help")==0 ||
149 strcmp(argv
[args
],"--help")==0
151 strcmp(filename
,"-h")==0 ||
152 strcmp(filename
,"-help")==0 ||
153 strcmp(filename
,"--help")==0
156 } else if (argc
> args
+1 && strcmp(argv
[args
],"-vdesock")==0) {
157 argsock
=argv
[args
+1];
160 argsock
=strdup(VDESTDSOCK
);
162 nb_nics
=countnics(argsock
);
163 if ((sp
= (pair
*) malloc(nb_nics
* 2 * sizeof (int)))<0) {
164 perror("malloc nics");
167 if ((numfd
= (char *) malloc(nb_nics
* NUMW
* sizeof (char)))<0) {
168 perror("malloc numfd");
172 for (i
=0; i
<nb_nics
; i
++) {
174 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, sp
[i
]) < 0){
175 perror("socketpair");
178 snprintf(curfd
,NUMW
,"%d%c",sp
[i
][0],(i
<nb_nics
-1)?',':0);
182 if ((sockname
= (char **) malloc(sizeof(char *) * nb_nics
))<0) {
183 perror("malloc sockname");
188 register char *s
=argsock
;
193 while (*s
!= ',' && *s
!= '\0')
198 } while (oldch
!= 0);
201 /* printf("-- %s --\n",numfd);
202 printf("as %s\n",argsock);
203 for (i=0; i<nb_nics; i++)
204 printf("%d -> %s\n",i,sockname[i]); */
206 if ((newargv
=(char **) malloc ((newargc
+1)* sizeof(char *))) <0) {
212 newargv
[1]="-tun-fd";
215 for (i
=3;args
<argc
;i
++,args
++) newargv
[i
]=argv
[args
];
219 if ((fddata
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
220 perror("malloc fddata");
223 if ((connected_fd
= (int *) malloc(sizeof(int) * nb_nics
))<0) {
224 perror("malloc connected_fd");
227 if ((dataout
= (struct sockaddr_un
*) malloc(sizeof(struct sockaddr_un
) * nb_nics
))<0) {
228 perror("malloc dataout");
232 if ((pollv
= (struct pollfd
*) malloc(sizeof(struct pollfd
) * 2 * nb_nics
))<0) {
233 perror("malloc fddata");
236 for (i
=0; i
<nb_nics
; i
++) {
237 if((fddata
[i
] = socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0){
241 connected_fd
[i
]=send_fd(sockname
[i
], fddata
[i
], &(dataout
[i
]), i
, group
);
242 pollv
[2*i
+1].fd
=fddata
[i
];
243 pollv
[2*i
].fd
=sp
[i
][1];
244 pollv
[2*i
].events
= pollv
[2*i
+1].events
=POLLIN
|POLLHUP
;
249 signal(SIGCHLD
, leave
);
250 for (i
=0; i
<nb_nics
; i
++)
253 result
=poll(pollv
,2*nb_nics
,-1);
254 for (i
=0; i
<nb_nics
; i
++) {
255 if (pollv
[2*i
].revents
& POLLHUP
|| pollv
[2*i
+1].revents
& POLLHUP
)
257 if (pollv
[2*i
].revents
& POLLIN
) {
258 nx
=read(sp
[i
][1],bufin
,sizeof(bufin
));
259 //fprintf(stderr,"RX from qemu %d\n",nx);
260 //send(connected_fd,bufin,nx,0);
261 sendto(fddata
[i
],bufin
,nx
,0,(struct sockaddr
*) &(dataout
[i
]), sizeof(struct sockaddr_un
));
263 if (pollv
[2*i
+1].revents
& POLLIN
) {
264 datainsize
=sizeof(datain
);
265 nx
=recvfrom(fddata
[i
],bufin
,BUFSIZE
,0,(struct sockaddr
*) &datain
, &datainsize
);
266 //fprintf(stderr,"TX to qemu %d\n",nx);
267 write(sp
[i
][1],bufin
,nx
);
272 for (i
=0; i
<nb_nics
; i
++) {
275 close(connected_fd
[i
]);
277 execvp(filename
,newargv
);