Fix monitor command (screendump) (Stefan Weil)
[qemu] / qemu-sockets.c
1 /*
2  *  inet and unix socket functions for qemu
3  *
4  *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; under version 2 of the License.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
20 #include <unistd.h>
21
22 #include "qemu_socket.h"
23 #include "qemu-common.h" /* for qemu_isdigit */
24
25 #ifndef AI_ADDRCONFIG
26 # define AI_ADDRCONFIG 0
27 #endif
28
29 static int sockets_debug = 0;
30 static const int on=1, off=0;
31
32 static int inet_getport(struct addrinfo *e)
33 {
34     struct sockaddr_in *i4;
35     struct sockaddr_in6 *i6;
36
37     switch (e->ai_family) {
38     case PF_INET6:
39         i6 = (void*)e->ai_addr;
40         return ntohs(i6->sin6_port);
41     case PF_INET:
42         i4 = (void*)e->ai_addr;
43         return ntohs(i4->sin_port);
44     default:
45         return 0;
46     }
47 }
48
49 static void inet_setport(struct addrinfo *e, int port)
50 {
51     struct sockaddr_in *i4;
52     struct sockaddr_in6 *i6;
53
54     switch (e->ai_family) {
55     case PF_INET6:
56         i6 = (void*)e->ai_addr;
57         i6->sin6_port = htons(port);
58         break;
59     case PF_INET:
60         i4 = (void*)e->ai_addr;
61         i4->sin_port = htons(port);
62         break;
63     }
64 }
65
66 static const char *inet_strfamily(int family)
67 {
68     switch (family) {
69     case PF_INET6: return "ipv6";
70     case PF_INET:  return "ipv4";
71     case PF_UNIX:  return "unix";
72     }
73     return "????";
74 }
75
76 static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
77 {
78     struct addrinfo *e;
79     char uaddr[INET6_ADDRSTRLEN+1];
80     char uport[33];
81
82     for (e = res; e != NULL; e = e->ai_next) {
83         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
84                     uaddr,INET6_ADDRSTRLEN,uport,32,
85                     NI_NUMERICHOST | NI_NUMERICSERV);
86         fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
87                 tag, inet_strfamily(e->ai_family), uaddr, uport);
88     }
89 }
90
91 int inet_listen(const char *str, char *ostr, int olen,
92                 int socktype, int port_offset)
93 {
94     struct addrinfo ai,*res,*e;
95     char addr[64];
96     char port[33];
97     char uaddr[INET6_ADDRSTRLEN+1];
98     char uport[33];
99     const char *opts, *h;
100     int slisten,rc,pos,to,try_next;
101
102     memset(&ai,0, sizeof(ai));
103     ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
104     ai.ai_family = PF_UNSPEC;
105     ai.ai_socktype = socktype;
106
107     /* parse address */
108     if (str[0] == ':') {
109         /* no host given */
110         addr[0] = '\0';
111         if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
112             fprintf(stderr, "%s: portonly parse error (%s)\n",
113                     __FUNCTION__, str);
114             return -1;
115         }
116     } else if (str[0] == '[') {
117         /* IPv6 addr */
118         if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
119             fprintf(stderr, "%s: ipv6 parse error (%s)\n",
120                     __FUNCTION__, str);
121             return -1;
122         }
123         ai.ai_family = PF_INET6;
124     } else if (qemu_isdigit(str[0])) {
125         /* IPv4 addr */
126         if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
127             fprintf(stderr, "%s: ipv4 parse error (%s)\n",
128                     __FUNCTION__, str);
129             return -1;
130         }
131         ai.ai_family = PF_INET;
132     } else {
133         /* hostname */
134         if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
135             fprintf(stderr, "%s: hostname parse error (%s)\n",
136                     __FUNCTION__, str);
137             return -1;
138         }
139     }
140
141     /* parse options */
142     opts = str + pos;
143     h = strstr(opts, ",to=");
144     to = h ? atoi(h+4) : 0;
145     if (strstr(opts, ",ipv4"))
146         ai.ai_family = PF_INET;
147     if (strstr(opts, ",ipv6"))
148         ai.ai_family = PF_INET6;
149
150     /* lookup */
151     if (port_offset)
152         snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
153     rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
154     if (rc != 0) {
155         fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__,
156                 addr, port, gai_strerror(rc));
157         return -1;
158     }
159     if (sockets_debug)
160         inet_print_addrinfo(__FUNCTION__, res);
161
162     /* create socket + bind */
163     for (e = res; e != NULL; e = e->ai_next) {
164         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
165                     uaddr,INET6_ADDRSTRLEN,uport,32,
166                     NI_NUMERICHOST | NI_NUMERICSERV);
167         slisten = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
168         if (slisten < 0) {
169             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
170                     inet_strfamily(e->ai_family), strerror(errno));
171             continue;
172         }
173
174         setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
175 #ifdef IPV6_V6ONLY
176         if (e->ai_family == PF_INET6) {
177             /* listen on both ipv4 and ipv6 */
178             setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,sizeof(off));
179         }
180 #endif
181
182         for (;;) {
183             if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
184                 if (sockets_debug)
185                     fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
186                             inet_strfamily(e->ai_family), uaddr, inet_getport(e));
187                 goto listen;
188             }
189             try_next = to && (inet_getport(e) <= to + port_offset);
190             if (!try_next || sockets_debug)
191                 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
192                         inet_strfamily(e->ai_family), uaddr, inet_getport(e),
193                         strerror(errno));
194             if (try_next) {
195                 inet_setport(e, inet_getport(e) + 1);
196                 continue;
197             }
198             break;
199         }
200         closesocket(slisten);
201     }
202     fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
203     freeaddrinfo(res);
204     return -1;
205
206 listen:
207     if (listen(slisten,1) != 0) {
208         perror("listen");
209         closesocket(slisten);
210         return -1;
211     }
212     if (ostr) {
213         if (e->ai_family == PF_INET6) {
214             snprintf(ostr, olen, "[%s]:%d%s", uaddr,
215                      inet_getport(e) - port_offset, opts);
216         } else {
217             snprintf(ostr, olen, "%s:%d%s", uaddr,
218                      inet_getport(e) - port_offset, opts);
219         }
220     }
221     freeaddrinfo(res);
222     return slisten;
223 }
224
225 int inet_connect(const char *str, int socktype)
226 {
227     struct addrinfo ai,*res,*e;
228     char addr[64];
229     char port[33];
230     char uaddr[INET6_ADDRSTRLEN+1];
231     char uport[33];
232     int sock,rc;
233
234     memset(&ai,0, sizeof(ai));
235     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
236     ai.ai_family = PF_UNSPEC;
237     ai.ai_socktype = socktype;
238
239     /* parse address */
240     if (str[0] == '[') {
241         /* IPv6 addr */
242         if (2 != sscanf(str,"[%64[^]]]:%32[^,]",addr,port)) {
243             fprintf(stderr, "%s: ipv6 parse error (%s)\n",
244                     __FUNCTION__, str);
245             return -1;
246         }
247         ai.ai_family = PF_INET6;
248     } else if (qemu_isdigit(str[0])) {
249         /* IPv4 addr */
250         if (2 != sscanf(str,"%64[0-9.]:%32[^,]",addr,port)) {
251             fprintf(stderr, "%s: ipv4 parse error (%s)\n",
252                     __FUNCTION__, str);
253             return -1;
254         }
255         ai.ai_family = PF_INET;
256     } else {
257         /* hostname */
258         if (2 != sscanf(str,"%64[^:]:%32[^,]",addr,port)) {
259             fprintf(stderr, "%s: hostname parse error (%s)\n",
260                     __FUNCTION__, str);
261             return -1;
262         }
263     }
264
265     /* parse options */
266     if (strstr(str, ",ipv4"))
267         ai.ai_family = PF_INET;
268     if (strstr(str, ",ipv6"))
269         ai.ai_family = PF_INET6;
270
271     /* lookup */
272     if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
273         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", gai_strerror(rc),
274                 addr, port);
275         return -1;
276     }
277     if (sockets_debug)
278         inet_print_addrinfo(__FUNCTION__, res);
279
280     for (e = res; e != NULL; e = e->ai_next) {
281         if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
282                         uaddr,INET6_ADDRSTRLEN,uport,32,
283                         NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
284             fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
285             continue;
286         }
287         sock = socket(e->ai_family, e->ai_socktype, e->ai_protocol);
288         if (sock < 0) {
289             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
290                     inet_strfamily(e->ai_family), strerror(errno));
291             continue;
292         }
293         setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
294
295         /* connect to peer */
296         if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
297             if (sockets_debug || NULL == e->ai_next)
298                 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
299                         inet_strfamily(e->ai_family),
300                         e->ai_canonname, uaddr, uport, strerror(errno));
301             closesocket(sock);
302             continue;
303         }
304         if (sockets_debug)
305             fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
306                     inet_strfamily(e->ai_family),
307                     e->ai_canonname, uaddr, uport);
308         freeaddrinfo(res);
309         return sock;
310     }
311     freeaddrinfo(res);
312     return -1;
313 }
314
315 #ifndef _WIN32
316
317 int unix_listen(const char *str, char *ostr, int olen)
318 {
319     struct sockaddr_un un;
320     char *path, *opts;
321     int sock, fd, len;
322
323     sock = socket(PF_UNIX, SOCK_STREAM, 0);
324     if (sock < 0) {
325         perror("socket(unix)");
326         return -1;
327     }
328
329     opts = strchr(str, ',');
330     if (opts) {
331         len = opts - str;
332         path = malloc(len+1);
333         snprintf(path, len+1, "%.*s", len, str);
334     } else
335         path = strdup(str);
336
337     memset(&un, 0, sizeof(un));
338     un.sun_family = AF_UNIX;
339     if (path && strlen(path)) {
340         snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
341     } else {
342         char *tmpdir = getenv("TMPDIR");
343         snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
344                  tmpdir ? tmpdir : "/tmp");
345         /*
346          * This dummy fd usage silences the mktemp() unsecure warning.
347          * Using mkstemp() doesn't make things more secure here
348          * though.  bind() complains about existing files, so we have
349          * to unlink first and thus re-open the race window.  The
350          * worst case possible is bind() failing, i.e. a DoS attack.
351          */
352         fd = mkstemp(un.sun_path); close(fd);
353     }
354     snprintf(ostr, olen, "%s%s", un.sun_path, opts ? opts : "");
355
356     unlink(un.sun_path);
357     if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
358         fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
359         goto err;
360     }
361     if (listen(sock, 1) < 0) {
362         fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
363         goto err;
364     }
365
366     if (sockets_debug)
367         fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
368     free(path);
369     return sock;
370
371 err:
372     free(path);
373     closesocket(sock);
374     return -1;
375 }
376
377 int unix_connect(const char *path)
378 {
379     struct sockaddr_un un;
380     int sock;
381
382     sock = socket(PF_UNIX, SOCK_STREAM, 0);
383     if (sock < 0) {
384         perror("socket(unix)");
385         return -1;
386     }
387
388     memset(&un, 0, sizeof(un));
389     un.sun_family = AF_UNIX;
390     snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
391     if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
392         fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
393         return -1;
394     }
395
396     if (sockets_debug)
397         fprintf(stderr, "connect(unix:%s): OK\n", path);
398     return sock;
399 }
400
401 #else
402
403 int unix_listen(const char *path, char *ostr, int olen)
404 {
405     fprintf(stderr, "unix sockets are not available on windows\n");
406     return -1;
407 }
408
409 int unix_connect(const char *path)
410 {
411     fprintf(stderr, "unix sockets are not available on windows\n");
412     return -1;
413 }
414
415 #endif