xref: /openbmc/qemu/util/qemu-sockets.c (revision 3257fc83)
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  * Contributions after 2012-01-13 are licensed under the terms of the
16  * GNU GPL, version 2 or (at your option) any later version.
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <unistd.h>
24 
25 #include "monitor/monitor.h"
26 #include "qemu/sockets.h"
27 #include "qemu/main-loop.h"
28 
29 #ifndef AI_ADDRCONFIG
30 # define AI_ADDRCONFIG 0
31 #endif
32 
33 static const int on=1, off=0;
34 
35 /* used temporarily until all users are converted to QemuOpts */
36 QemuOptsList socket_optslist = {
37     .name = "socket",
38     .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
39     .desc = {
40         {
41             .name = "path",
42             .type = QEMU_OPT_STRING,
43         },{
44             .name = "host",
45             .type = QEMU_OPT_STRING,
46         },{
47             .name = "port",
48             .type = QEMU_OPT_STRING,
49         },{
50             .name = "to",
51             .type = QEMU_OPT_NUMBER,
52         },{
53             .name = "ipv4",
54             .type = QEMU_OPT_BOOL,
55         },{
56             .name = "ipv6",
57             .type = QEMU_OPT_BOOL,
58         },
59         { /* end if list */ }
60     },
61 };
62 
63 static int inet_getport(struct addrinfo *e)
64 {
65     struct sockaddr_in *i4;
66     struct sockaddr_in6 *i6;
67 
68     switch (e->ai_family) {
69     case PF_INET6:
70         i6 = (void*)e->ai_addr;
71         return ntohs(i6->sin6_port);
72     case PF_INET:
73         i4 = (void*)e->ai_addr;
74         return ntohs(i4->sin_port);
75     default:
76         return 0;
77     }
78 }
79 
80 static void inet_setport(struct addrinfo *e, int port)
81 {
82     struct sockaddr_in *i4;
83     struct sockaddr_in6 *i6;
84 
85     switch (e->ai_family) {
86     case PF_INET6:
87         i6 = (void*)e->ai_addr;
88         i6->sin6_port = htons(port);
89         break;
90     case PF_INET:
91         i4 = (void*)e->ai_addr;
92         i4->sin_port = htons(port);
93         break;
94     }
95 }
96 
97 const char *inet_strfamily(int family)
98 {
99     switch (family) {
100     case PF_INET6: return "ipv6";
101     case PF_INET:  return "ipv4";
102     case PF_UNIX:  return "unix";
103     }
104     return "unknown";
105 }
106 
107 int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
108 {
109     struct addrinfo ai,*res,*e;
110     const char *addr;
111     char port[33];
112     char uaddr[INET6_ADDRSTRLEN+1];
113     char uport[33];
114     int slisten, rc, to, port_min, port_max, p;
115 
116     memset(&ai,0, sizeof(ai));
117     ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
118     ai.ai_family = PF_UNSPEC;
119     ai.ai_socktype = SOCK_STREAM;
120 
121     if ((qemu_opt_get(opts, "host") == NULL) ||
122         (qemu_opt_get(opts, "port") == NULL)) {
123         error_setg(errp, "host and/or port not specified");
124         return -1;
125     }
126     pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
127     addr = qemu_opt_get(opts, "host");
128 
129     to = qemu_opt_get_number(opts, "to", 0);
130     if (qemu_opt_get_bool(opts, "ipv4", 0))
131         ai.ai_family = PF_INET;
132     if (qemu_opt_get_bool(opts, "ipv6", 0))
133         ai.ai_family = PF_INET6;
134 
135     /* lookup */
136     if (port_offset)
137         snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
138     rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
139     if (rc != 0) {
140         error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
141                    gai_strerror(rc));
142         return -1;
143     }
144 
145     /* create socket + bind */
146     for (e = res; e != NULL; e = e->ai_next) {
147         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
148 		        uaddr,INET6_ADDRSTRLEN,uport,32,
149 		        NI_NUMERICHOST | NI_NUMERICSERV);
150         slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
151         if (slisten < 0) {
152             if (!e->ai_next) {
153                 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
154             }
155             continue;
156         }
157 
158         socket_set_fast_reuse(slisten);
159 #ifdef IPV6_V6ONLY
160         if (e->ai_family == PF_INET6) {
161             /* listen on both ipv4 and ipv6 */
162             qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off,
163                             sizeof(off));
164         }
165 #endif
166 
167         port_min = inet_getport(e);
168         port_max = to ? to + port_offset : port_min;
169         for (p = port_min; p <= port_max; p++) {
170             inet_setport(e, p);
171             if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
172                 goto listen;
173             }
174             if (p == port_max) {
175                 if (!e->ai_next) {
176                     error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
177                 }
178             }
179         }
180         closesocket(slisten);
181     }
182     freeaddrinfo(res);
183     return -1;
184 
185 listen:
186     if (listen(slisten,1) != 0) {
187         error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED);
188         closesocket(slisten);
189         freeaddrinfo(res);
190         return -1;
191     }
192     snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
193     qemu_opt_set(opts, "host", uaddr);
194     qemu_opt_set(opts, "port", uport);
195     qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
196     qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
197     freeaddrinfo(res);
198     return slisten;
199 }
200 
201 #ifdef _WIN32
202 #define QEMU_SOCKET_RC_INPROGRESS(rc) \
203     ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY)
204 #else
205 #define QEMU_SOCKET_RC_INPROGRESS(rc) \
206     ((rc) == -EINPROGRESS)
207 #endif
208 
209 /* Struct to store connect state for non blocking connect */
210 typedef struct ConnectState {
211     int fd;
212     struct addrinfo *addr_list;
213     struct addrinfo *current_addr;
214     NonBlockingConnectHandler *callback;
215     void *opaque;
216 } ConnectState;
217 
218 static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
219                              ConnectState *connect_state, Error **errp);
220 
221 static void wait_for_connect(void *opaque)
222 {
223     ConnectState *s = opaque;
224     int val = 0, rc = 0;
225     socklen_t valsize = sizeof(val);
226     bool in_progress;
227 
228     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
229 
230     do {
231         rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
232     } while (rc == -1 && socket_error() == EINTR);
233 
234     /* update rc to contain error */
235     if (!rc && val) {
236         rc = -1;
237     }
238 
239     /* connect error */
240     if (rc < 0) {
241         closesocket(s->fd);
242         s->fd = rc;
243     }
244 
245     /* try to connect to the next address on the list */
246     if (s->current_addr) {
247         while (s->current_addr->ai_next != NULL && s->fd < 0) {
248             s->current_addr = s->current_addr->ai_next;
249             s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL);
250             /* connect in progress */
251             if (in_progress) {
252                 return;
253             }
254         }
255 
256         freeaddrinfo(s->addr_list);
257     }
258 
259     if (s->callback) {
260         s->callback(s->fd, s->opaque);
261     }
262     g_free(s);
263 }
264 
265 static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
266                              ConnectState *connect_state, Error **errp)
267 {
268     int sock, rc;
269 
270     *in_progress = false;
271 
272     sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
273     if (sock < 0) {
274         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
275         return -1;
276     }
277     socket_set_fast_reuse(sock);
278     if (connect_state != NULL) {
279         qemu_set_nonblock(sock);
280     }
281     /* connect to peer */
282     do {
283         rc = 0;
284         if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
285             rc = -socket_error();
286         }
287     } while (rc == -EINTR);
288 
289     if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
290         connect_state->fd = sock;
291         qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect,
292                              connect_state);
293         *in_progress = true;
294     } else if (rc < 0) {
295         error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED);
296         closesocket(sock);
297         return -1;
298     }
299     return sock;
300 }
301 
302 static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp)
303 {
304     struct addrinfo ai, *res;
305     int rc;
306     const char *addr;
307     const char *port;
308 
309     memset(&ai, 0, sizeof(ai));
310 
311     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
312     ai.ai_family = PF_UNSPEC;
313     ai.ai_socktype = SOCK_STREAM;
314 
315     addr = qemu_opt_get(opts, "host");
316     port = qemu_opt_get(opts, "port");
317     if (addr == NULL || port == NULL) {
318         error_setg(errp, "host and/or port not specified");
319         return NULL;
320     }
321 
322     if (qemu_opt_get_bool(opts, "ipv4", 0)) {
323         ai.ai_family = PF_INET;
324     }
325     if (qemu_opt_get_bool(opts, "ipv6", 0)) {
326         ai.ai_family = PF_INET6;
327     }
328 
329     /* lookup */
330     rc = getaddrinfo(addr, port, &ai, &res);
331     if (rc != 0) {
332         error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
333                    gai_strerror(rc));
334         return NULL;
335     }
336     return res;
337 }
338 
339 /**
340  * Create a socket and connect it to an address.
341  *
342  * @opts: QEMU options, recognized parameters strings "host" and "port",
343  *        bools "ipv4" and "ipv6".
344  * @errp: set on error
345  * @callback: callback function for non-blocking connect
346  * @opaque: opaque for callback function
347  *
348  * Returns: -1 on error, file descriptor on success.
349  *
350  * If @callback is non-null, the connect is non-blocking.  If this
351  * function succeeds, callback will be called when the connection
352  * completes, with the file descriptor on success, or -1 on error.
353  */
354 int inet_connect_opts(QemuOpts *opts, Error **errp,
355                       NonBlockingConnectHandler *callback, void *opaque)
356 {
357     Error *local_err = NULL;
358     struct addrinfo *res, *e;
359     int sock = -1;
360     bool in_progress;
361     ConnectState *connect_state = NULL;
362 
363     res = inet_parse_connect_opts(opts, errp);
364     if (!res) {
365         return -1;
366     }
367 
368     if (callback != NULL) {
369         connect_state = g_malloc0(sizeof(*connect_state));
370         connect_state->addr_list = res;
371         connect_state->callback = callback;
372         connect_state->opaque = opaque;
373     }
374 
375     for (e = res; e != NULL; e = e->ai_next) {
376         error_free(local_err);
377         local_err = NULL;
378         if (connect_state != NULL) {
379             connect_state->current_addr = e;
380         }
381         sock = inet_connect_addr(e, &in_progress, connect_state, &local_err);
382         if (sock >= 0) {
383             break;
384         }
385     }
386 
387     if (sock < 0) {
388         error_propagate(errp, local_err);
389     } else if (in_progress) {
390         /* wait_for_connect() will do the rest */
391         return sock;
392     } else {
393         if (callback) {
394             callback(sock, opaque);
395         }
396     }
397     g_free(connect_state);
398     freeaddrinfo(res);
399     return sock;
400 }
401 
402 int inet_dgram_opts(QemuOpts *opts, Error **errp)
403 {
404     struct addrinfo ai, *peer = NULL, *local = NULL;
405     const char *addr;
406     const char *port;
407     int sock = -1, rc;
408 
409     /* lookup peer addr */
410     memset(&ai,0, sizeof(ai));
411     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
412     ai.ai_family = PF_UNSPEC;
413     ai.ai_socktype = SOCK_DGRAM;
414 
415     addr = qemu_opt_get(opts, "host");
416     port = qemu_opt_get(opts, "port");
417     if (addr == NULL || strlen(addr) == 0) {
418         addr = "localhost";
419     }
420     if (port == NULL || strlen(port) == 0) {
421         error_setg(errp, "remote port not specified");
422         return -1;
423     }
424 
425     if (qemu_opt_get_bool(opts, "ipv4", 0))
426         ai.ai_family = PF_INET;
427     if (qemu_opt_get_bool(opts, "ipv6", 0))
428         ai.ai_family = PF_INET6;
429 
430     if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
431         error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
432                    gai_strerror(rc));
433 	return -1;
434     }
435 
436     /* lookup local addr */
437     memset(&ai,0, sizeof(ai));
438     ai.ai_flags = AI_PASSIVE;
439     ai.ai_family = peer->ai_family;
440     ai.ai_socktype = SOCK_DGRAM;
441 
442     addr = qemu_opt_get(opts, "localaddr");
443     port = qemu_opt_get(opts, "localport");
444     if (addr == NULL || strlen(addr) == 0) {
445         addr = NULL;
446     }
447     if (!port || strlen(port) == 0)
448         port = "0";
449 
450     if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
451         error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
452                    gai_strerror(rc));
453         goto err;
454     }
455 
456     /* create socket */
457     sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
458     if (sock < 0) {
459         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
460         goto err;
461     }
462     socket_set_fast_reuse(sock);
463 
464     /* bind socket */
465     if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
466         error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
467         goto err;
468     }
469 
470     /* connect to peer */
471     if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
472         error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED);
473         goto err;
474     }
475 
476     freeaddrinfo(local);
477     freeaddrinfo(peer);
478     return sock;
479 
480 err:
481     if (-1 != sock)
482         closesocket(sock);
483     if (local)
484         freeaddrinfo(local);
485     if (peer)
486         freeaddrinfo(peer);
487     return -1;
488 }
489 
490 /* compatibility wrapper */
491 InetSocketAddress *inet_parse(const char *str, Error **errp)
492 {
493     InetSocketAddress *addr;
494     const char *optstr, *h;
495     char host[64];
496     char port[33];
497     int to;
498     int pos;
499 
500     addr = g_new0(InetSocketAddress, 1);
501 
502     /* parse address */
503     if (str[0] == ':') {
504         /* no host given */
505         host[0] = '\0';
506         if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) {
507             error_setg(errp, "error parsing port in address '%s'", str);
508             goto fail;
509         }
510     } else if (str[0] == '[') {
511         /* IPv6 addr */
512         if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) {
513             error_setg(errp, "error parsing IPv6 address '%s'", str);
514             goto fail;
515         }
516         addr->ipv6 = addr->has_ipv6 = true;
517     } else {
518         /* hostname or IPv4 addr */
519         if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
520             error_setg(errp, "error parsing address '%s'", str);
521             goto fail;
522         }
523         if (host[strspn(host, "0123456789.")] == '\0') {
524             addr->ipv4 = addr->has_ipv4 = true;
525         }
526     }
527 
528     addr->host = g_strdup(host);
529     addr->port = g_strdup(port);
530 
531     /* parse options */
532     optstr = str + pos;
533     h = strstr(optstr, ",to=");
534     if (h) {
535         h += 4;
536         if (sscanf(h, "%d%n", &to, &pos) != 1 ||
537             (h[pos] != '\0' && h[pos] != ',')) {
538             error_setg(errp, "error parsing to= argument");
539             goto fail;
540         }
541         addr->has_to = true;
542         addr->to = to;
543     }
544     if (strstr(optstr, ",ipv4")) {
545         addr->ipv4 = addr->has_ipv4 = true;
546     }
547     if (strstr(optstr, ",ipv6")) {
548         addr->ipv6 = addr->has_ipv6 = true;
549     }
550     return addr;
551 
552 fail:
553     qapi_free_InetSocketAddress(addr);
554     return NULL;
555 }
556 
557 static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
558 {
559     bool ipv4 = addr->ipv4 || !addr->has_ipv4;
560     bool ipv6 = addr->ipv6 || !addr->has_ipv6;
561 
562     if (!ipv4 || !ipv6) {
563         qemu_opt_set_bool(opts, "ipv4", ipv4);
564         qemu_opt_set_bool(opts, "ipv6", ipv6);
565     }
566     if (addr->has_to) {
567         char to[20];
568         snprintf(to, sizeof(to), "%d", addr->to);
569         qemu_opt_set(opts, "to", to);
570     }
571     qemu_opt_set(opts, "host", addr->host);
572     qemu_opt_set(opts, "port", addr->port);
573 }
574 
575 int inet_listen(const char *str, char *ostr, int olen,
576                 int socktype, int port_offset, Error **errp)
577 {
578     QemuOpts *opts;
579     char *optstr;
580     int sock = -1;
581     InetSocketAddress *addr;
582 
583     addr = inet_parse(str, errp);
584     if (addr != NULL) {
585         opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
586         inet_addr_to_opts(opts, addr);
587         qapi_free_InetSocketAddress(addr);
588         sock = inet_listen_opts(opts, port_offset, errp);
589         if (sock != -1 && ostr) {
590             optstr = strchr(str, ',');
591             if (qemu_opt_get_bool(opts, "ipv6", 0)) {
592                 snprintf(ostr, olen, "[%s]:%s%s",
593                          qemu_opt_get(opts, "host"),
594                          qemu_opt_get(opts, "port"),
595                          optstr ? optstr : "");
596             } else {
597                 snprintf(ostr, olen, "%s:%s%s",
598                          qemu_opt_get(opts, "host"),
599                          qemu_opt_get(opts, "port"),
600                          optstr ? optstr : "");
601             }
602         }
603         qemu_opts_del(opts);
604     }
605     return sock;
606 }
607 
608 /**
609  * Create a blocking socket and connect it to an address.
610  *
611  * @str: address string
612  * @errp: set in case of an error
613  *
614  * Returns -1 in case of error, file descriptor on success
615  **/
616 int inet_connect(const char *str, Error **errp)
617 {
618     QemuOpts *opts;
619     int sock = -1;
620     InetSocketAddress *addr;
621 
622     addr = inet_parse(str, errp);
623     if (addr != NULL) {
624         opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
625         inet_addr_to_opts(opts, addr);
626         qapi_free_InetSocketAddress(addr);
627         sock = inet_connect_opts(opts, errp, NULL, NULL);
628         qemu_opts_del(opts);
629     }
630     return sock;
631 }
632 
633 /**
634  * Create a non-blocking socket and connect it to an address.
635  * Calls the callback function with fd in case of success or -1 in case of
636  * error.
637  *
638  * @str: address string
639  * @callback: callback function that is called when connect completes,
640  *            cannot be NULL.
641  * @opaque: opaque for callback function
642  * @errp: set in case of an error
643  *
644  * Returns: -1 on immediate error, file descriptor on success.
645  **/
646 int inet_nonblocking_connect(const char *str,
647                              NonBlockingConnectHandler *callback,
648                              void *opaque, Error **errp)
649 {
650     QemuOpts *opts;
651     int sock = -1;
652     InetSocketAddress *addr;
653 
654     g_assert(callback != NULL);
655 
656     addr = inet_parse(str, errp);
657     if (addr != NULL) {
658         opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
659         inet_addr_to_opts(opts, addr);
660         qapi_free_InetSocketAddress(addr);
661         sock = inet_connect_opts(opts, errp, callback, opaque);
662         qemu_opts_del(opts);
663     }
664     return sock;
665 }
666 
667 #ifndef _WIN32
668 
669 int unix_listen_opts(QemuOpts *opts, Error **errp)
670 {
671     struct sockaddr_un un;
672     const char *path = qemu_opt_get(opts, "path");
673     int sock, fd;
674 
675     sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
676     if (sock < 0) {
677         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
678         return -1;
679     }
680 
681     memset(&un, 0, sizeof(un));
682     un.sun_family = AF_UNIX;
683     if (path && strlen(path)) {
684         snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
685     } else {
686         char *tmpdir = getenv("TMPDIR");
687         snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
688                  tmpdir ? tmpdir : "/tmp");
689         /*
690          * This dummy fd usage silences the mktemp() unsecure warning.
691          * Using mkstemp() doesn't make things more secure here
692          * though.  bind() complains about existing files, so we have
693          * to unlink first and thus re-open the race window.  The
694          * worst case possible is bind() failing, i.e. a DoS attack.
695          */
696         fd = mkstemp(un.sun_path); close(fd);
697         qemu_opt_set(opts, "path", un.sun_path);
698     }
699 
700     unlink(un.sun_path);
701     if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
702         error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
703         goto err;
704     }
705     if (listen(sock, 1) < 0) {
706         error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED);
707         goto err;
708     }
709 
710     return sock;
711 
712 err:
713     closesocket(sock);
714     return -1;
715 }
716 
717 int unix_connect_opts(QemuOpts *opts, Error **errp,
718                       NonBlockingConnectHandler *callback, void *opaque)
719 {
720     struct sockaddr_un un;
721     const char *path = qemu_opt_get(opts, "path");
722     ConnectState *connect_state = NULL;
723     int sock, rc;
724 
725     if (NULL == path) {
726         error_setg(errp, "unix connect: no path specified");
727         return -1;
728     }
729 
730     sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
731     if (sock < 0) {
732         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
733         return -1;
734     }
735     if (callback != NULL) {
736         connect_state = g_malloc0(sizeof(*connect_state));
737         connect_state->callback = callback;
738         connect_state->opaque = opaque;
739         qemu_set_nonblock(sock);
740     }
741 
742     memset(&un, 0, sizeof(un));
743     un.sun_family = AF_UNIX;
744     snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
745 
746     /* connect to peer */
747     do {
748         rc = 0;
749         if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
750             rc = -socket_error();
751         }
752     } while (rc == -EINTR);
753 
754     if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
755         connect_state->fd = sock;
756         qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect,
757                              connect_state);
758         return sock;
759     } else if (rc >= 0) {
760         /* non blocking socket immediate success, call callback */
761         if (callback != NULL) {
762             callback(sock, opaque);
763         }
764     }
765 
766     if (rc < 0) {
767         error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED);
768         close(sock);
769         sock = -1;
770     }
771 
772     g_free(connect_state);
773     return sock;
774 }
775 
776 #else
777 
778 int unix_listen_opts(QemuOpts *opts, Error **errp)
779 {
780     error_setg(errp, "unix sockets are not available on windows");
781     errno = ENOTSUP;
782     return -1;
783 }
784 
785 int unix_connect_opts(QemuOpts *opts, Error **errp,
786                       NonBlockingConnectHandler *callback, void *opaque)
787 {
788     error_setg(errp, "unix sockets are not available on windows");
789     errno = ENOTSUP;
790     return -1;
791 }
792 #endif
793 
794 /* compatibility wrapper */
795 int unix_listen(const char *str, char *ostr, int olen, Error **errp)
796 {
797     QemuOpts *opts;
798     char *path, *optstr;
799     int sock, len;
800 
801     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
802 
803     optstr = strchr(str, ',');
804     if (optstr) {
805         len = optstr - str;
806         if (len) {
807             path = g_malloc(len+1);
808             snprintf(path, len+1, "%.*s", len, str);
809             qemu_opt_set(opts, "path", path);
810             g_free(path);
811         }
812     } else {
813         qemu_opt_set(opts, "path", str);
814     }
815 
816     sock = unix_listen_opts(opts, errp);
817 
818     if (sock != -1 && ostr)
819         snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
820     qemu_opts_del(opts);
821     return sock;
822 }
823 
824 int unix_connect(const char *path, Error **errp)
825 {
826     QemuOpts *opts;
827     int sock;
828 
829     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
830     qemu_opt_set(opts, "path", path);
831     sock = unix_connect_opts(opts, errp, NULL, NULL);
832     qemu_opts_del(opts);
833     return sock;
834 }
835 
836 
837 int unix_nonblocking_connect(const char *path,
838                              NonBlockingConnectHandler *callback,
839                              void *opaque, Error **errp)
840 {
841     QemuOpts *opts;
842     int sock = -1;
843 
844     g_assert(callback != NULL);
845 
846     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
847     qemu_opt_set(opts, "path", path);
848     sock = unix_connect_opts(opts, errp, callback, opaque);
849     qemu_opts_del(opts);
850     return sock;
851 }
852 
853 SocketAddress *socket_parse(const char *str, Error **errp)
854 {
855     SocketAddress *addr;
856 
857     addr = g_new0(SocketAddress, 1);
858     if (strstart(str, "unix:", NULL)) {
859         if (str[5] == '\0') {
860             error_setg(errp, "invalid Unix socket address");
861             goto fail;
862         } else {
863             addr->kind = SOCKET_ADDRESS_KIND_UNIX;
864             addr->q_unix = g_new(UnixSocketAddress, 1);
865             addr->q_unix->path = g_strdup(str + 5);
866         }
867     } else if (strstart(str, "fd:", NULL)) {
868         if (str[3] == '\0') {
869             error_setg(errp, "invalid file descriptor address");
870             goto fail;
871         } else {
872             addr->kind = SOCKET_ADDRESS_KIND_FD;
873             addr->fd = g_new(String, 1);
874             addr->fd->str = g_strdup(str + 3);
875         }
876     } else {
877         addr->kind = SOCKET_ADDRESS_KIND_INET;
878         addr->inet = inet_parse(str, errp);
879         if (addr->inet == NULL) {
880             goto fail;
881         }
882     }
883     return addr;
884 
885 fail:
886     qapi_free_SocketAddress(addr);
887     return NULL;
888 }
889 
890 int socket_connect(SocketAddress *addr, Error **errp,
891                    NonBlockingConnectHandler *callback, void *opaque)
892 {
893     QemuOpts *opts;
894     int fd;
895 
896     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
897     switch (addr->kind) {
898     case SOCKET_ADDRESS_KIND_INET:
899         inet_addr_to_opts(opts, addr->inet);
900         fd = inet_connect_opts(opts, errp, callback, opaque);
901         break;
902 
903     case SOCKET_ADDRESS_KIND_UNIX:
904         qemu_opt_set(opts, "path", addr->q_unix->path);
905         fd = unix_connect_opts(opts, errp, callback, opaque);
906         break;
907 
908     case SOCKET_ADDRESS_KIND_FD:
909         fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
910         if (fd >= 0 && callback) {
911             qemu_set_nonblock(fd);
912             callback(fd, opaque);
913         }
914         break;
915 
916     default:
917         abort();
918     }
919     qemu_opts_del(opts);
920     return fd;
921 }
922 
923 int socket_listen(SocketAddress *addr, Error **errp)
924 {
925     QemuOpts *opts;
926     int fd;
927 
928     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
929     switch (addr->kind) {
930     case SOCKET_ADDRESS_KIND_INET:
931         inet_addr_to_opts(opts, addr->inet);
932         fd = inet_listen_opts(opts, 0, errp);
933         break;
934 
935     case SOCKET_ADDRESS_KIND_UNIX:
936         qemu_opt_set(opts, "path", addr->q_unix->path);
937         fd = unix_listen_opts(opts, errp);
938         break;
939 
940     case SOCKET_ADDRESS_KIND_FD:
941         fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
942         break;
943 
944     default:
945         abort();
946     }
947     qemu_opts_del(opts);
948     return fd;
949 }
950 
951 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
952 {
953     QemuOpts *opts;
954     int fd;
955 
956     opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
957     switch (remote->kind) {
958     case SOCKET_ADDRESS_KIND_INET:
959         qemu_opt_set(opts, "host", remote->inet->host);
960         qemu_opt_set(opts, "port", remote->inet->port);
961         if (local) {
962             qemu_opt_set(opts, "localaddr", local->inet->host);
963             qemu_opt_set(opts, "localport", local->inet->port);
964         }
965         fd = inet_dgram_opts(opts, errp);
966         break;
967 
968     default:
969         error_setg(errp, "socket type unsupported for datagram");
970         fd = -1;
971     }
972     qemu_opts_del(opts);
973     return fd;
974 }
975