]> git.proxmox.com Git - mirror_qemu.git/blame - util/qemu-sockets.c
spapr: fix buffer-overflow
[mirror_qemu.git] / util / qemu-sockets.c
CommitLineData
305b0eb2
AL
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.
e6d91ab6
PB
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.
305b0eb2 17 */
aafd7584 18#include "qemu/osdep.h"
d247d25f 19
6a02c806
SH
20#ifdef CONFIG_AF_VSOCK
21#include <linux/vm_sockets.h>
22#endif /* CONFIG_AF_VSOCK */
23
83c9089e 24#include "monitor/monitor.h"
da34e65c 25#include "qapi/error.h"
1de7afc9 26#include "qemu/sockets.h"
1de7afc9 27#include "qemu/main-loop.h"
b3db211f
DB
28#include "qapi/qobject-input-visitor.h"
29#include "qapi/qobject-output-visitor.h"
2a8e21c7 30#include "qapi-visit.h"
f348b6d1 31#include "qemu/cutils.h"
d247d25f
AL
32
33#ifndef AI_ADDRCONFIG
34# define AI_ADDRCONFIG 0
35#endif
340849a9 36
3de3d698
WB
37#ifndef AI_V4MAPPED
38# define AI_V4MAPPED 0
39#endif
d247d25f 40
6979a813
DB
41#ifndef AI_NUMERICSERV
42# define AI_NUMERICSERV 0
43#endif
44
2af2bf67 45
d247d25f
AL
46static int inet_getport(struct addrinfo *e)
47{
48 struct sockaddr_in *i4;
49 struct sockaddr_in6 *i6;
50
51 switch (e->ai_family) {
52 case PF_INET6:
53 i6 = (void*)e->ai_addr;
54 return ntohs(i6->sin6_port);
55 case PF_INET:
56 i4 = (void*)e->ai_addr;
57 return ntohs(i4->sin_port);
58 default:
59 return 0;
60 }
61}
62
63static void inet_setport(struct addrinfo *e, int port)
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 i6->sin6_port = htons(port);
72 break;
73 case PF_INET:
74 i4 = (void*)e->ai_addr;
75 i4->sin_port = htons(port);
76 break;
77 }
78}
79
a589569f
WX
80NetworkAddressFamily inet_netfamily(int family)
81{
82 switch (family) {
83 case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6;
84 case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4;
85 case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX;
6a02c806
SH
86#ifdef CONFIG_AF_VSOCK
87 case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK;
88#endif /* CONFIG_AF_VSOCK */
a589569f
WX
89 }
90 return NETWORK_ADDRESS_FAMILY_UNKNOWN;
91}
92
1856835d
DB
93/*
94 * Matrix we're trying to apply
95 *
96 * ipv4 ipv6 family
97 * - - PF_UNSPEC
98 * - f PF_INET
99 * - t PF_INET6
100 * f - PF_INET6
101 * f f <error>
102 * f t PF_INET6
103 * t - PF_INET
104 * t f PF_INET
105 * t t PF_INET6
106 *
d43eda3d 107 * NB, this matrix is only about getting the necessary results
1856835d
DB
108 * from getaddrinfo(). Some of the cases require further work
109 * after reading results from getaddrinfo in order to fully
110 * apply the logic the end user wants. eg with the last case
111 * ipv4=t + ipv6=t + PF_INET6, getaddrinfo alone can only
112 * guarantee the ipv6=t part of the request - we need more
113 * checks to provide ipv4=t part of the guarantee. This is
114 * outside scope of this method and not currently handled by
115 * callers at all.
116 */
c1b412f1
DB
117int inet_ai_family_from_address(InetSocketAddress *addr,
118 Error **errp)
1856835d
DB
119{
120 if (addr->has_ipv6 && addr->has_ipv4 &&
121 !addr->ipv6 && !addr->ipv4) {
122 error_setg(errp, "Cannot disable IPv4 and IPv6 at same time");
123 return PF_UNSPEC;
124 }
125 if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) {
126 return PF_INET6;
127 }
128 if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) {
129 return PF_INET;
130 }
131 return PF_UNSPEC;
132}
133
134static int inet_listen_saddr(InetSocketAddress *saddr,
135 int port_offset,
136 bool update_addr,
137 Error **errp)
d247d25f
AL
138{
139 struct addrinfo ai,*res,*e;
d247d25f
AL
140 char port[33];
141 char uaddr[INET6_ADDRSTRLEN+1];
142 char uport[33];
1856835d
DB
143 int slisten, rc, port_min, port_max, p;
144 Error *err = NULL;
d247d25f
AL
145
146 memset(&ai,0, sizeof(ai));
3de3d698 147 ai.ai_flags = AI_PASSIVE;
6979a813
DB
148 if (saddr->has_numeric && saddr->numeric) {
149 ai.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
150 }
1856835d 151 ai.ai_family = inet_ai_family_from_address(saddr, &err);
e5bc776f 152 ai.ai_socktype = SOCK_STREAM;
d247d25f 153
1856835d
DB
154 if (err) {
155 error_propagate(errp, err);
156 return -1;
157 }
158
159 if (saddr->host == NULL) {
0983f5e6 160 error_setg(errp, "host not specified");
e5bc776f 161 return -1;
d247d25f 162 }
1856835d
DB
163 if (saddr->port != NULL) {
164 pstrcpy(port, sizeof(port), saddr->port);
0983f5e6
DB
165 } else {
166 port[0] = '\0';
167 }
d247d25f
AL
168
169 /* lookup */
8bc89127
GH
170 if (port_offset) {
171 unsigned long long baseport;
0983f5e6
DB
172 if (strlen(port) == 0) {
173 error_setg(errp, "port not specified");
174 return -1;
175 }
8bc89127
GH
176 if (parse_uint_full(port, &baseport, 10) < 0) {
177 error_setg(errp, "can't convert to a number: %s", port);
178 return -1;
179 }
180 if (baseport > 65535 ||
181 baseport + port_offset > 65535) {
182 error_setg(errp, "port %s out of range", port);
183 return -1;
184 }
185 snprintf(port, sizeof(port), "%d", (int)baseport + port_offset);
186 }
1856835d 187 rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL,
0983f5e6 188 strlen(port) ? port : NULL, &ai, &res);
d247d25f 189 if (rc != 0) {
1856835d
DB
190 error_setg(errp, "address resolution failed for %s:%s: %s",
191 saddr->host, port, gai_strerror(rc));
d247d25f
AL
192 return -1;
193 }
d247d25f
AL
194
195 /* create socket + bind */
196 for (e = res; e != NULL; e = e->ai_next) {
39b6efc8
VS
197 getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
198 uaddr,INET6_ADDRSTRLEN,uport,32,
199 NI_NUMERICHOST | NI_NUMERICSERV);
40ff6d7e 200 slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
39b6efc8 201 if (slisten < 0) {
029409e5 202 if (!e->ai_next) {
235256a2 203 error_setg_errno(errp, errno, "Failed to create socket");
029409e5 204 }
39b6efc8
VS
205 continue;
206 }
d247d25f 207
04fd1c78 208 socket_set_fast_reuse(slisten);
d247d25f
AL
209#ifdef IPV6_V6ONLY
210 if (e->ai_family == PF_INET6) {
211 /* listen on both ipv4 and ipv6 */
f9b5426f 212 const int off = 0;
9957fc7f
SW
213 qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off,
214 sizeof(off));
d247d25f
AL
215 }
216#endif
217
877691f9 218 port_min = inet_getport(e);
1856835d 219 port_max = saddr->has_to ? saddr->to + port_offset : port_min;
877691f9
MA
220 for (p = port_min; p <= port_max; p++) {
221 inet_setport(e, p);
d247d25f 222 if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
d247d25f
AL
223 goto listen;
224 }
877691f9 225 if (p == port_max) {
029409e5 226 if (!e->ai_next) {
235256a2 227 error_setg_errno(errp, errno, "Failed to bind socket");
029409e5 228 }
d247d25f 229 }
d247d25f
AL
230 }
231 closesocket(slisten);
232 }
d247d25f
AL
233 freeaddrinfo(res);
234 return -1;
235
236listen:
237 if (listen(slisten,1) != 0) {
235256a2 238 error_setg_errno(errp, errno, "Failed to listen on socket");
d247d25f 239 closesocket(slisten);
39b6efc8 240 freeaddrinfo(res);
d247d25f
AL
241 return -1;
242 }
1856835d
DB
243 if (update_addr) {
244 g_free(saddr->host);
245 saddr->host = g_strdup(uaddr);
246 g_free(saddr->port);
247 saddr->port = g_strdup_printf("%d",
248 inet_getport(e) - port_offset);
249 saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6;
250 saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6;
251 }
d247d25f
AL
252 freeaddrinfo(res);
253 return slisten;
254}
255
05bc1d8a
MT
256#ifdef _WIN32
257#define QEMU_SOCKET_RC_INPROGRESS(rc) \
258 ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY)
259#else
260#define QEMU_SOCKET_RC_INPROGRESS(rc) \
261 ((rc) == -EINPROGRESS)
262#endif
263
233aa5c2
OW
264/* Struct to store connect state for non blocking connect */
265typedef struct ConnectState {
266 int fd;
267 struct addrinfo *addr_list;
268 struct addrinfo *current_addr;
269 NonBlockingConnectHandler *callback;
270 void *opaque;
271} ConnectState;
272
273static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
11663b55 274 ConnectState *connect_state, Error **errp);
233aa5c2
OW
275
276static void wait_for_connect(void *opaque)
d247d25f 277{
233aa5c2
OW
278 ConnectState *s = opaque;
279 int val = 0, rc = 0;
280 socklen_t valsize = sizeof(val);
281 bool in_progress;
51795029 282 Error *err = NULL;
233aa5c2 283
82e1cc4b 284 qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
233aa5c2
OW
285
286 do {
9957fc7f 287 rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
b16a44e1 288 } while (rc == -1 && errno == EINTR);
233aa5c2
OW
289
290 /* update rc to contain error */
291 if (!rc && val) {
292 rc = -1;
51795029 293 errno = val;
233aa5c2
OW
294 }
295
296 /* connect error */
297 if (rc < 0) {
51795029 298 error_setg_errno(&err, errno, "Error connecting to socket");
233aa5c2
OW
299 closesocket(s->fd);
300 s->fd = rc;
301 }
302
303 /* try to connect to the next address on the list */
1fc05adf
PB
304 if (s->current_addr) {
305 while (s->current_addr->ai_next != NULL && s->fd < 0) {
306 s->current_addr = s->current_addr->ai_next;
11663b55 307 s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL);
51795029
CM
308 if (s->fd < 0) {
309 error_free(err);
310 err = NULL;
311 error_setg_errno(&err, errno, "Unable to start socket connect");
312 }
1fc05adf
PB
313 /* connect in progress */
314 if (in_progress) {
51795029 315 goto out;
1fc05adf 316 }
233aa5c2 317 }
1fc05adf
PB
318
319 freeaddrinfo(s->addr_list);
233aa5c2 320 }
05bc1d8a 321
233aa5c2 322 if (s->callback) {
51795029 323 s->callback(s->fd, err, s->opaque);
05bc1d8a 324 }
233aa5c2 325 g_free(s);
51795029
CM
326out:
327 error_free(err);
233aa5c2
OW
328}
329
330static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
11663b55 331 ConnectState *connect_state, Error **errp)
233aa5c2
OW
332{
333 int sock, rc;
334
335 *in_progress = false;
05bc1d8a
MT
336
337 sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
338 if (sock < 0) {
235256a2 339 error_setg_errno(errp, errno, "Failed to create socket");
05bc1d8a
MT
340 return -1;
341 }
04fd1c78 342 socket_set_fast_reuse(sock);
233aa5c2 343 if (connect_state != NULL) {
f9e8cacc 344 qemu_set_nonblock(sock);
05bc1d8a
MT
345 }
346 /* connect to peer */
347 do {
348 rc = 0;
349 if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
b16a44e1 350 rc = -errno;
05bc1d8a
MT
351 }
352 } while (rc == -EINTR);
353
233aa5c2
OW
354 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
355 connect_state->fd = sock;
82e1cc4b 356 qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
233aa5c2 357 *in_progress = true;
05bc1d8a 358 } else if (rc < 0) {
235256a2 359 error_setg_errno(errp, errno, "Failed to connect socket");
05bc1d8a
MT
360 closesocket(sock);
361 return -1;
362 }
363 return sock;
364}
365
2942e420
DB
366static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
367 Error **errp)
05bc1d8a
MT
368{
369 struct addrinfo ai, *res;
370 int rc;
2942e420 371 Error *err = NULL;
340849a9 372 static int useV4Mapped = 1;
d247d25f 373
05bc1d8a 374 memset(&ai, 0, sizeof(ai));
233aa5c2 375
340849a9
DB
376 ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
377 if (atomic_read(&useV4Mapped)) {
378 ai.ai_flags |= AI_V4MAPPED;
379 }
2942e420 380 ai.ai_family = inet_ai_family_from_address(saddr, &err);
f4c94c7c 381 ai.ai_socktype = SOCK_STREAM;
d247d25f 382
2942e420
DB
383 if (err) {
384 error_propagate(errp, err);
05bc1d8a 385 return NULL;
d247d25f
AL
386 }
387
2942e420
DB
388 if (saddr->host == NULL || saddr->port == NULL) {
389 error_setg(errp, "host and/or port not specified");
390 return NULL;
05bc1d8a 391 }
d247d25f
AL
392
393 /* lookup */
2942e420 394 rc = getaddrinfo(saddr->host, saddr->port, &ai, &res);
340849a9
DB
395
396 /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but
397 * then don't implement it in their getaddrinfo(). Detect
398 * this and retry without the flag since that's preferrable
399 * to a fatal error
400 */
401 if (rc == EAI_BADFLAGS &&
402 (ai.ai_flags & AI_V4MAPPED)) {
403 atomic_set(&useV4Mapped, 0);
404 ai.ai_flags &= ~AI_V4MAPPED;
405 rc = getaddrinfo(saddr->host, saddr->port, &ai, &res);
406 }
05bc1d8a 407 if (rc != 0) {
2942e420
DB
408 error_setg(errp, "address resolution failed for %s:%s: %s",
409 saddr->host, saddr->port, gai_strerror(rc));
05bc1d8a
MT
410 return NULL;
411 }
412 return res;
413}
414
5db5f44c
OW
415/**
416 * Create a socket and connect it to an address.
417 *
2942e420 418 * @saddr: Inet socket address specification
5db5f44c 419 * @errp: set on error
233aa5c2
OW
420 * @callback: callback function for non-blocking connect
421 * @opaque: opaque for callback function
5db5f44c
OW
422 *
423 * Returns: -1 on error, file descriptor on success.
233aa5c2
OW
424 *
425 * If @callback is non-null, the connect is non-blocking. If this
426 * function succeeds, callback will be called when the connection
427 * completes, with the file descriptor on success, or -1 on error.
5db5f44c 428 */
89cadc9d
AA
429int inet_connect_saddr(InetSocketAddress *saddr, Error **errp,
430 NonBlockingConnectHandler *callback, void *opaque)
05bc1d8a 431{
3f9286b7 432 Error *local_err = NULL;
05bc1d8a
MT
433 struct addrinfo *res, *e;
434 int sock = -1;
233aa5c2
OW
435 bool in_progress;
436 ConnectState *connect_state = NULL;
05bc1d8a 437
2942e420 438 res = inet_parse_connect_saddr(saddr, errp);
05bc1d8a
MT
439 if (!res) {
440 return -1;
441 }
442
233aa5c2
OW
443 if (callback != NULL) {
444 connect_state = g_malloc0(sizeof(*connect_state));
445 connect_state->addr_list = res;
446 connect_state->callback = callback;
447 connect_state->opaque = opaque;
d247d25f 448 }
d247d25f
AL
449
450 for (e = res; e != NULL; e = e->ai_next) {
3f9286b7
MA
451 error_free(local_err);
452 local_err = NULL;
233aa5c2
OW
453 if (connect_state != NULL) {
454 connect_state->current_addr = e;
455 }
3f9286b7
MA
456 sock = inet_connect_addr(e, &in_progress, connect_state, &local_err);
457 if (sock >= 0) {
05bc1d8a 458 break;
a6ba35b3 459 }
d247d25f 460 }
3f9286b7
MA
461
462 if (sock < 0) {
463 error_propagate(errp, local_err);
464 } else if (in_progress) {
465 /* wait_for_connect() will do the rest */
466 return sock;
467 } else {
468 if (callback) {
51795029 469 callback(sock, NULL, opaque);
3f9286b7
MA
470 }
471 }
233aa5c2 472 g_free(connect_state);
d247d25f 473 freeaddrinfo(res);
05bc1d8a 474 return sock;
d247d25f
AL
475}
476
8b39910e
DB
477static int inet_dgram_saddr(InetSocketAddress *sraddr,
478 InetSocketAddress *sladdr,
479 Error **errp)
7e1b35b4
GH
480{
481 struct addrinfo ai, *peer = NULL, *local = NULL;
482 const char *addr;
483 const char *port;
7e1b35b4 484 int sock = -1, rc;
8b39910e 485 Error *err = NULL;
7e1b35b4
GH
486
487 /* lookup peer addr */
488 memset(&ai,0, sizeof(ai));
3de3d698 489 ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG;
8b39910e 490 ai.ai_family = inet_ai_family_from_address(sraddr, &err);
7e1b35b4
GH
491 ai.ai_socktype = SOCK_DGRAM;
492
8b39910e
DB
493 if (err) {
494 error_propagate(errp, err);
58c652c0 495 goto err;
8b39910e
DB
496 }
497
498 addr = sraddr->host;
499 port = sraddr->port;
7e1b35b4
GH
500 if (addr == NULL || strlen(addr) == 0) {
501 addr = "localhost";
502 }
503 if (port == NULL || strlen(port) == 0) {
4f085c82 504 error_setg(errp, "remote port not specified");
58c652c0 505 goto err;
7e1b35b4
GH
506 }
507
9cd1883c 508 if ((rc = getaddrinfo(addr, port, &ai, &peer)) != 0) {
4f085c82
PB
509 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
510 gai_strerror(rc));
26015051 511 goto err;
7e1b35b4 512 }
7e1b35b4
GH
513
514 /* lookup local addr */
515 memset(&ai,0, sizeof(ai));
516 ai.ai_flags = AI_PASSIVE;
517 ai.ai_family = peer->ai_family;
518 ai.ai_socktype = SOCK_DGRAM;
519
8b39910e
DB
520 if (sladdr) {
521 addr = sladdr->host;
522 port = sladdr->port;
523 if (addr == NULL || strlen(addr) == 0) {
524 addr = NULL;
525 }
526 if (!port || strlen(port) == 0) {
527 port = "0";
528 }
529 } else {
7e1b35b4 530 addr = NULL;
7e1b35b4 531 port = "0";
8b39910e 532 }
7e1b35b4 533
9cd1883c 534 if ((rc = getaddrinfo(addr, port, &ai, &local)) != 0) {
4f085c82
PB
535 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
536 gai_strerror(rc));
39b38459 537 goto err;
7e1b35b4 538 }
7e1b35b4
GH
539
540 /* create socket */
40ff6d7e 541 sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
7e1b35b4 542 if (sock < 0) {
235256a2 543 error_setg_errno(errp, errno, "Failed to create socket");
7e1b35b4
GH
544 goto err;
545 }
04fd1c78 546 socket_set_fast_reuse(sock);
7e1b35b4
GH
547
548 /* bind socket */
7e1b35b4 549 if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
235256a2 550 error_setg_errno(errp, errno, "Failed to bind socket");
7e1b35b4
GH
551 goto err;
552 }
553
554 /* connect to peer */
7e1b35b4 555 if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
235256a2 556 error_setg_errno(errp, errno, "Failed to connect socket");
7e1b35b4
GH
557 goto err;
558 }
559
560 freeaddrinfo(local);
561 freeaddrinfo(peer);
562 return sock;
563
564err:
26015051 565 if (sock != -1) {
7e1b35b4 566 closesocket(sock);
26015051
C
567 }
568 if (local) {
7e1b35b4 569 freeaddrinfo(local);
26015051
C
570 }
571 if (peer) {
7e1b35b4 572 freeaddrinfo(peer);
26015051
C
573 }
574
7e1b35b4
GH
575 return -1;
576}
577
f4c94c7c 578/* compatibility wrapper */
f17c90be 579InetSocketAddress *inet_parse(const char *str, Error **errp)
f4c94c7c 580{
879e45c7 581 InetSocketAddress *addr;
f4c94c7c 582 const char *optstr, *h;
55a10996 583 char host[65];
f4c94c7c 584 char port[33];
879e45c7 585 int to;
f4c94c7c
GH
586 int pos;
587
879e45c7
PB
588 addr = g_new0(InetSocketAddress, 1);
589
f4c94c7c
GH
590 /* parse address */
591 if (str[0] == ':') {
592 /* no host given */
879e45c7 593 host[0] = '\0';
9cd1883c 594 if (sscanf(str, ":%32[^,]%n", port, &pos) != 1) {
2f002c43 595 error_setg(errp, "error parsing port in address '%s'", str);
879e45c7 596 goto fail;
f4c94c7c
GH
597 }
598 } else if (str[0] == '[') {
599 /* IPv6 addr */
9cd1883c 600 if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos) != 2) {
2f002c43 601 error_setg(errp, "error parsing IPv6 address '%s'", str);
879e45c7 602 goto fail;
f4c94c7c 603 }
879e45c7 604 addr->ipv6 = addr->has_ipv6 = true;
f4c94c7c 605 } else {
391b7b97 606 /* hostname or IPv4 addr */
9cd1883c 607 if (sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos) != 2) {
2f002c43 608 error_setg(errp, "error parsing address '%s'", str);
879e45c7 609 goto fail;
f4c94c7c 610 }
391b7b97
JT
611 if (host[strspn(host, "0123456789.")] == '\0') {
612 addr->ipv4 = addr->has_ipv4 = true;
613 }
f4c94c7c 614 }
879e45c7
PB
615
616 addr->host = g_strdup(host);
617 addr->port = g_strdup(port);
f4c94c7c
GH
618
619 /* parse options */
620 optstr = str + pos;
621 h = strstr(optstr, ",to=");
879e45c7 622 if (h) {
1ccbc285
AP
623 h += 4;
624 if (sscanf(h, "%d%n", &to, &pos) != 1 ||
625 (h[pos] != '\0' && h[pos] != ',')) {
879e45c7
PB
626 error_setg(errp, "error parsing to= argument");
627 goto fail;
628 }
629 addr->has_to = true;
630 addr->to = to;
631 }
632 if (strstr(optstr, ",ipv4")) {
633 addr->ipv4 = addr->has_ipv4 = true;
634 }
635 if (strstr(optstr, ",ipv6")) {
636 addr->ipv6 = addr->has_ipv6 = true;
637 }
638 return addr;
639
640fail:
641 qapi_free_InetSocketAddress(addr);
642 return NULL;
643}
644
e5bc776f 645
5db5f44c
OW
646/**
647 * Create a blocking socket and connect it to an address.
648 *
649 * @str: address string
650 * @errp: set in case of an error
651 *
652 * Returns -1 in case of error, file descriptor on success
653 **/
654int inet_connect(const char *str, Error **errp)
f4c94c7c 655{
f4c94c7c 656 int sock = -1;
879e45c7 657 InetSocketAddress *addr;
f4c94c7c 658
879e45c7
PB
659 addr = inet_parse(str, errp);
660 if (addr != NULL) {
2942e420 661 sock = inet_connect_saddr(addr, errp, NULL, NULL);
879e45c7 662 qapi_free_InetSocketAddress(addr);
5db5f44c 663 }
5db5f44c
OW
664 return sock;
665}
666
6a02c806
SH
667#ifdef CONFIG_AF_VSOCK
668static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr,
669 struct sockaddr_vm *svm,
670 Error **errp)
671{
672 unsigned long long val;
673
674 memset(svm, 0, sizeof(*svm));
675 svm->svm_family = AF_VSOCK;
676
677 if (parse_uint_full(vaddr->cid, &val, 10) < 0 ||
678 val > UINT32_MAX) {
679 error_setg(errp, "Failed to parse cid '%s'", vaddr->cid);
680 return false;
681 }
682 svm->svm_cid = val;
683
684 if (parse_uint_full(vaddr->port, &val, 10) < 0 ||
685 val > UINT32_MAX) {
686 error_setg(errp, "Failed to parse port '%s'", vaddr->port);
687 return false;
688 }
689 svm->svm_port = val;
690
691 return true;
692}
693
694static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress,
695 ConnectState *connect_state, Error **errp)
696{
697 int sock, rc;
698
699 *in_progress = false;
700
701 sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
702 if (sock < 0) {
703 error_setg_errno(errp, errno, "Failed to create socket");
704 return -1;
705 }
706 if (connect_state != NULL) {
707 qemu_set_nonblock(sock);
708 }
709 /* connect to peer */
710 do {
711 rc = 0;
712 if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) {
713 rc = -errno;
714 }
715 } while (rc == -EINTR);
716
717 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
718 connect_state->fd = sock;
719 qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
720 *in_progress = true;
721 } else if (rc < 0) {
722 error_setg_errno(errp, errno, "Failed to connect socket");
723 closesocket(sock);
724 return -1;
725 }
726 return sock;
727}
728
729static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp,
730 NonBlockingConnectHandler *callback,
731 void *opaque)
732{
733 struct sockaddr_vm svm;
734 int sock = -1;
735 bool in_progress;
736 ConnectState *connect_state = NULL;
737
738 if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
739 return -1;
740 }
741
742 if (callback != NULL) {
743 connect_state = g_malloc0(sizeof(*connect_state));
744 connect_state->callback = callback;
745 connect_state->opaque = opaque;
746 }
747
748 sock = vsock_connect_addr(&svm, &in_progress, connect_state, errp);
749 if (sock < 0) {
750 /* do nothing */
751 } else if (in_progress) {
752 /* wait_for_connect() will do the rest */
753 return sock;
754 } else {
755 if (callback) {
756 callback(sock, NULL, opaque);
757 }
758 }
759 g_free(connect_state);
760 return sock;
761}
762
763static int vsock_listen_saddr(VsockSocketAddress *vaddr,
764 Error **errp)
765{
766 struct sockaddr_vm svm;
767 int slisten;
768
769 if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
770 return -1;
771 }
772
773 slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
774 if (slisten < 0) {
775 error_setg_errno(errp, errno, "Failed to create socket");
776 return -1;
777 }
778
779 if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) {
780 error_setg_errno(errp, errno, "Failed to bind socket");
781 closesocket(slisten);
782 return -1;
783 }
784
785 if (listen(slisten, 1) != 0) {
786 error_setg_errno(errp, errno, "Failed to listen on socket");
787 closesocket(slisten);
788 return -1;
789 }
790 return slisten;
791}
792
793static VsockSocketAddress *vsock_parse(const char *str, Error **errp)
794{
795 VsockSocketAddress *addr = NULL;
796 char cid[33];
797 char port[33];
798 int n;
799
800 if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) {
801 error_setg(errp, "error parsing address '%s'", str);
802 return NULL;
803 }
804 if (str[n] != '\0') {
805 error_setg(errp, "trailing characters in address '%s'", str);
806 return NULL;
807 }
808
809 addr = g_new0(VsockSocketAddress, 1);
810 addr->cid = g_strdup(cid);
811 addr->port = g_strdup(port);
812 return addr;
813}
814#else
815static void vsock_unsupported(Error **errp)
816{
817 error_setg(errp, "socket family AF_VSOCK unsupported");
818}
819
820static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp,
821 NonBlockingConnectHandler *callback,
822 void *opaque)
823{
824 vsock_unsupported(errp);
825 return -1;
826}
827
828static int vsock_listen_saddr(VsockSocketAddress *vaddr,
829 Error **errp)
830{
831 vsock_unsupported(errp);
832 return -1;
833}
834
835static VsockSocketAddress *vsock_parse(const char *str, Error **errp)
836{
837 vsock_unsupported(errp);
838 return NULL;
839}
840#endif /* CONFIG_AF_VSOCK */
841
d247d25f
AL
842#ifndef _WIN32
843
1856835d
DB
844static int unix_listen_saddr(UnixSocketAddress *saddr,
845 bool update_addr,
846 Error **errp)
d247d25f
AL
847{
848 struct sockaddr_un un;
62b6adfb 849 int sock, fd;
d247d25f 850
40ff6d7e 851 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
d247d25f 852 if (sock < 0) {
b658c53d 853 error_setg_errno(errp, errno, "Failed to create Unix socket");
39b6efc8 854 return -1;
d247d25f
AL
855 }
856
d247d25f
AL
857 memset(&un, 0, sizeof(un));
858 un.sun_family = AF_UNIX;
1856835d
DB
859 if (saddr->path && strlen(saddr->path)) {
860 snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path);
d247d25f 861 } else {
b658c53d
PB
862 const char *tmpdir = getenv("TMPDIR");
863 tmpdir = tmpdir ? tmpdir : "/tmp";
864 if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
865 tmpdir) >= sizeof(un.sun_path)) {
866 error_setg_errno(errp, errno,
867 "TMPDIR environment variable (%s) too large", tmpdir);
868 goto err;
869 }
870
d247d25f
AL
871 /*
872 * This dummy fd usage silences the mktemp() unsecure warning.
873 * Using mkstemp() doesn't make things more secure here
874 * though. bind() complains about existing files, so we have
875 * to unlink first and thus re-open the race window. The
876 * worst case possible is bind() failing, i.e. a DoS attack.
877 */
b658c53d
PB
878 fd = mkstemp(un.sun_path);
879 if (fd < 0) {
880 error_setg_errno(errp, errno,
881 "Failed to make a temporary socket name in %s", tmpdir);
882 goto err;
883 }
884 close(fd);
1856835d
DB
885 if (update_addr) {
886 g_free(saddr->path);
887 saddr->path = g_strdup(un.sun_path);
888 }
d247d25f 889 }
d247d25f 890
a2f31f18 891 if (unlink(un.sun_path) < 0 && errno != ENOENT) {
0ef705a2
CR
892 error_setg_errno(errp, errno,
893 "Failed to unlink socket %s", un.sun_path);
894 goto err;
895 }
d247d25f 896 if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
b658c53d 897 error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path);
d247d25f
AL
898 goto err;
899 }
900 if (listen(sock, 1) < 0) {
235256a2 901 error_setg_errno(errp, errno, "Failed to listen on socket");
d247d25f
AL
902 goto err;
903 }
904
d247d25f
AL
905 return sock;
906
907err:
d247d25f
AL
908 closesocket(sock);
909 return -1;
910}
911
2942e420
DB
912static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp,
913 NonBlockingConnectHandler *callback, void *opaque)
d247d25f
AL
914{
915 struct sockaddr_un un;
1fc05adf
PB
916 ConnectState *connect_state = NULL;
917 int sock, rc;
d247d25f 918
2942e420 919 if (saddr->path == NULL) {
312fd5f2 920 error_setg(errp, "unix connect: no path specified");
2af2bf67
GH
921 return -1;
922 }
923
40ff6d7e 924 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
d247d25f 925 if (sock < 0) {
235256a2 926 error_setg_errno(errp, errno, "Failed to create socket");
39b6efc8 927 return -1;
d247d25f 928 }
1fc05adf
PB
929 if (callback != NULL) {
930 connect_state = g_malloc0(sizeof(*connect_state));
931 connect_state->callback = callback;
932 connect_state->opaque = opaque;
f9e8cacc 933 qemu_set_nonblock(sock);
1fc05adf 934 }
d247d25f
AL
935
936 memset(&un, 0, sizeof(un));
937 un.sun_family = AF_UNIX;
2942e420 938 snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path);
1fc05adf
PB
939
940 /* connect to peer */
941 do {
942 rc = 0;
943 if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
b16a44e1 944 rc = -errno;
1fc05adf
PB
945 }
946 } while (rc == -EINTR);
947
948 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
949 connect_state->fd = sock;
82e1cc4b 950 qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
1fc05adf
PB
951 return sock;
952 } else if (rc >= 0) {
953 /* non blocking socket immediate success, call callback */
954 if (callback != NULL) {
51795029 955 callback(sock, NULL, opaque);
1fc05adf
PB
956 }
957 }
958
959 if (rc < 0) {
235256a2 960 error_setg_errno(errp, -rc, "Failed to connect socket");
9d947472 961 close(sock);
1fc05adf 962 sock = -1;
d247d25f
AL
963 }
964
1fc05adf 965 g_free(connect_state);
d247d25f
AL
966 return sock;
967}
968
0c814709
PB
969#else
970
1856835d
DB
971static int unix_listen_saddr(UnixSocketAddress *saddr,
972 bool update_addr,
973 Error **errp)
0c814709 974{
58899664 975 error_setg(errp, "unix sockets are not available on windows");
0c814709
PB
976 errno = ENOTSUP;
977 return -1;
978}
979
2942e420
DB
980static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp,
981 NonBlockingConnectHandler *callback, void *opaque)
0c814709 982{
58899664 983 error_setg(errp, "unix sockets are not available on windows");
0c814709
PB
984 errno = ENOTSUP;
985 return -1;
986}
987#endif
988
2af2bf67 989/* compatibility wrapper */
7fc4e63e 990int unix_listen(const char *str, char *ostr, int olen, Error **errp)
62b6adfb 991{
62b6adfb
GH
992 char *path, *optstr;
993 int sock, len;
1856835d 994 UnixSocketAddress *saddr;
62b6adfb 995
1856835d 996 saddr = g_new0(UnixSocketAddress, 1);
62b6adfb
GH
997
998 optstr = strchr(str, ',');
999 if (optstr) {
1000 len = optstr - str;
1001 if (len) {
7267c094 1002 path = g_malloc(len+1);
62b6adfb 1003 snprintf(path, len+1, "%.*s", len, str);
1856835d 1004 saddr->path = path;
62b6adfb
GH
1005 }
1006 } else {
1856835d 1007 saddr->path = g_strdup(str);
62b6adfb
GH
1008 }
1009
1856835d 1010 sock = unix_listen_saddr(saddr, true, errp);
62b6adfb 1011
26015051 1012 if (sock != -1 && ostr) {
1856835d 1013 snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : "");
26015051
C
1014 }
1015
1856835d 1016 qapi_free_UnixSocketAddress(saddr);
62b6adfb
GH
1017 return sock;
1018}
1019
7fc4e63e 1020int unix_connect(const char *path, Error **errp)
2af2bf67 1021{
2942e420 1022 UnixSocketAddress *saddr;
2af2bf67
GH
1023 int sock;
1024
2942e420
DB
1025 saddr = g_new0(UnixSocketAddress, 1);
1026 saddr->path = g_strdup(path);
1027 sock = unix_connect_saddr(saddr, errp, NULL, NULL);
1028 qapi_free_UnixSocketAddress(saddr);
1fc05adf
PB
1029 return sock;
1030}
1031
1032
101f9cbc
PB
1033SocketAddress *socket_parse(const char *str, Error **errp)
1034{
afde3f8b 1035 SocketAddress *addr;
101f9cbc 1036
afde3f8b 1037 addr = g_new0(SocketAddress, 1);
101f9cbc
PB
1038 if (strstart(str, "unix:", NULL)) {
1039 if (str[5] == '\0') {
312fd5f2 1040 error_setg(errp, "invalid Unix socket address");
101f9cbc
PB
1041 goto fail;
1042 } else {
2d32adda 1043 addr->type = SOCKET_ADDRESS_KIND_UNIX;
32bafa8f
EB
1044 addr->u.q_unix.data = g_new(UnixSocketAddress, 1);
1045 addr->u.q_unix.data->path = g_strdup(str + 5);
101f9cbc
PB
1046 }
1047 } else if (strstart(str, "fd:", NULL)) {
1048 if (str[3] == '\0') {
312fd5f2 1049 error_setg(errp, "invalid file descriptor address");
101f9cbc
PB
1050 goto fail;
1051 } else {
2d32adda 1052 addr->type = SOCKET_ADDRESS_KIND_FD;
32bafa8f
EB
1053 addr->u.fd.data = g_new(String, 1);
1054 addr->u.fd.data->str = g_strdup(str + 3);
101f9cbc 1055 }
6a02c806
SH
1056 } else if (strstart(str, "vsock:", NULL)) {
1057 addr->type = SOCKET_ADDRESS_KIND_VSOCK;
1058 addr->u.vsock.data = vsock_parse(str + strlen("vsock:"), errp);
1059 if (addr->u.vsock.data == NULL) {
1060 goto fail;
1061 }
101f9cbc 1062 } else {
2d32adda 1063 addr->type = SOCKET_ADDRESS_KIND_INET;
32bafa8f
EB
1064 addr->u.inet.data = inet_parse(str, errp);
1065 if (addr->u.inet.data == NULL) {
101f9cbc
PB
1066 goto fail;
1067 }
1068 }
1069 return addr;
1070
1071fail:
1072 qapi_free_SocketAddress(addr);
1073 return NULL;
1074}
1075
1076int socket_connect(SocketAddress *addr, Error **errp,
1077 NonBlockingConnectHandler *callback, void *opaque)
1078{
101f9cbc
PB
1079 int fd;
1080
2d32adda 1081 switch (addr->type) {
101f9cbc 1082 case SOCKET_ADDRESS_KIND_INET:
32bafa8f 1083 fd = inet_connect_saddr(addr->u.inet.data, errp, callback, opaque);
101f9cbc
PB
1084 break;
1085
1086 case SOCKET_ADDRESS_KIND_UNIX:
32bafa8f 1087 fd = unix_connect_saddr(addr->u.q_unix.data, errp, callback, opaque);
101f9cbc
PB
1088 break;
1089
1090 case SOCKET_ADDRESS_KIND_FD:
32bafa8f 1091 fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp);
d1ec72a4 1092 if (fd >= 0 && callback) {
1a751ebf 1093 qemu_set_nonblock(fd);
51795029 1094 callback(fd, NULL, opaque);
101f9cbc
PB
1095 }
1096 break;
1097
6a02c806
SH
1098 case SOCKET_ADDRESS_KIND_VSOCK:
1099 fd = vsock_connect_saddr(addr->u.vsock.data, errp, callback, opaque);
1100 break;
1101
101f9cbc
PB
1102 default:
1103 abort();
1104 }
101f9cbc
PB
1105 return fd;
1106}
1107
1108int socket_listen(SocketAddress *addr, Error **errp)
1109{
101f9cbc
PB
1110 int fd;
1111
2d32adda 1112 switch (addr->type) {
101f9cbc 1113 case SOCKET_ADDRESS_KIND_INET:
32bafa8f 1114 fd = inet_listen_saddr(addr->u.inet.data, 0, false, errp);
101f9cbc
PB
1115 break;
1116
1117 case SOCKET_ADDRESS_KIND_UNIX:
32bafa8f 1118 fd = unix_listen_saddr(addr->u.q_unix.data, false, errp);
101f9cbc
PB
1119 break;
1120
1121 case SOCKET_ADDRESS_KIND_FD:
32bafa8f 1122 fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp);
101f9cbc
PB
1123 break;
1124
6a02c806
SH
1125 case SOCKET_ADDRESS_KIND_VSOCK:
1126 fd = vsock_listen_saddr(addr->u.vsock.data, errp);
1127 break;
1128
101f9cbc
PB
1129 default:
1130 abort();
1131 }
101f9cbc
PB
1132 return fd;
1133}
1134
74b6ce43
MAL
1135void socket_listen_cleanup(int fd, Error **errp)
1136{
1137 SocketAddress *addr;
1138
1139 addr = socket_local_address(fd, errp);
1140
1141 if (addr->type == SOCKET_ADDRESS_KIND_UNIX
1142 && addr->u.q_unix.data->path) {
1143 if (unlink(addr->u.q_unix.data->path) < 0 && errno != ENOENT) {
1144 error_setg_errno(errp, errno,
1145 "Failed to unlink socket %s",
1146 addr->u.q_unix.data->path);
1147 }
1148 }
1149
73f40c18 1150 qapi_free_SocketAddress(addr);
74b6ce43
MAL
1151}
1152
3ecc059d
GH
1153int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
1154{
3ecc059d
GH
1155 int fd;
1156
2d32adda 1157 switch (remote->type) {
3ecc059d 1158 case SOCKET_ADDRESS_KIND_INET:
32bafa8f
EB
1159 fd = inet_dgram_saddr(remote->u.inet.data,
1160 local ? local->u.inet.data : NULL, errp);
3ecc059d
GH
1161 break;
1162
1163 default:
1164 error_setg(errp, "socket type unsupported for datagram");
7a5b6af1 1165 fd = -1;
3ecc059d 1166 }
3ecc059d
GH
1167 return fd;
1168}
17c55dec
DB
1169
1170
1171static SocketAddress *
1172socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
1173 socklen_t salen,
1174 Error **errp)
1175{
1176 char host[NI_MAXHOST];
1177 char serv[NI_MAXSERV];
1178 SocketAddress *addr;
0399293e 1179 InetSocketAddress *inet;
17c55dec
DB
1180 int ret;
1181
1182 ret = getnameinfo((struct sockaddr *)sa, salen,
1183 host, sizeof(host),
1184 serv, sizeof(serv),
1185 NI_NUMERICHOST | NI_NUMERICSERV);
1186 if (ret != 0) {
1187 error_setg(errp, "Cannot format numeric socket address: %s",
1188 gai_strerror(ret));
1189 return NULL;
1190 }
1191
1192 addr = g_new0(SocketAddress, 1);
2d32adda 1193 addr->type = SOCKET_ADDRESS_KIND_INET;
32bafa8f 1194 inet = addr->u.inet.data = g_new0(InetSocketAddress, 1);
0399293e
EB
1195 inet->host = g_strdup(host);
1196 inet->port = g_strdup(serv);
17c55dec 1197 if (sa->ss_family == AF_INET) {
0399293e 1198 inet->has_ipv4 = inet->ipv4 = true;
17c55dec 1199 } else {
0399293e 1200 inet->has_ipv6 = inet->ipv6 = true;
17c55dec
DB
1201 }
1202
1203 return addr;
1204}
1205
1206
1207#ifndef WIN32
1208static SocketAddress *
1209socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
1210 socklen_t salen,
1211 Error **errp)
1212{
1213 SocketAddress *addr;
1214 struct sockaddr_un *su = (struct sockaddr_un *)sa;
1215
1216 addr = g_new0(SocketAddress, 1);
2d32adda 1217 addr->type = SOCKET_ADDRESS_KIND_UNIX;
32bafa8f 1218 addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
17c55dec 1219 if (su->sun_path[0]) {
32bafa8f
EB
1220 addr->u.q_unix.data->path = g_strndup(su->sun_path,
1221 sizeof(su->sun_path));
17c55dec
DB
1222 }
1223
1224 return addr;
1225}
1226#endif /* WIN32 */
1227
6a02c806
SH
1228#ifdef CONFIG_AF_VSOCK
1229static SocketAddress *
1230socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa,
1231 socklen_t salen,
1232 Error **errp)
1233{
1234 SocketAddress *addr;
1235 VsockSocketAddress *vaddr;
1236 struct sockaddr_vm *svm = (struct sockaddr_vm *)sa;
1237
1238 addr = g_new0(SocketAddress, 1);
1239 addr->type = SOCKET_ADDRESS_KIND_VSOCK;
1240 addr->u.vsock.data = vaddr = g_new0(VsockSocketAddress, 1);
1241 vaddr->cid = g_strdup_printf("%u", svm->svm_cid);
1242 vaddr->port = g_strdup_printf("%u", svm->svm_port);
1243
1244 return addr;
1245}
1246#endif /* CONFIG_AF_VSOCK */
1247
559607ea 1248SocketAddress *
17c55dec
DB
1249socket_sockaddr_to_address(struct sockaddr_storage *sa,
1250 socklen_t salen,
1251 Error **errp)
1252{
1253 switch (sa->ss_family) {
1254 case AF_INET:
1255 case AF_INET6:
1256 return socket_sockaddr_to_address_inet(sa, salen, errp);
1257
1258#ifndef WIN32
1259 case AF_UNIX:
1260 return socket_sockaddr_to_address_unix(sa, salen, errp);
1261#endif /* WIN32 */
1262
6a02c806
SH
1263#ifdef CONFIG_AF_VSOCK
1264 case AF_VSOCK:
1265 return socket_sockaddr_to_address_vsock(sa, salen, errp);
1266#endif
1267
17c55dec
DB
1268 default:
1269 error_setg(errp, "socket family %d unsupported",
1270 sa->ss_family);
1271 return NULL;
1272 }
1273 return 0;
1274}
1275
1276
1277SocketAddress *socket_local_address(int fd, Error **errp)
1278{
1279 struct sockaddr_storage ss;
1280 socklen_t sslen = sizeof(ss);
1281
1282 if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
b16a44e1 1283 error_setg_errno(errp, errno, "%s",
17c55dec
DB
1284 "Unable to query local socket address");
1285 return NULL;
1286 }
1287
1288 return socket_sockaddr_to_address(&ss, sslen, errp);
1289}
1290
1291
1292SocketAddress *socket_remote_address(int fd, Error **errp)
1293{
1294 struct sockaddr_storage ss;
1295 socklen_t sslen = sizeof(ss);
1296
1297 if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) {
b16a44e1 1298 error_setg_errno(errp, errno, "%s",
17c55dec
DB
1299 "Unable to query remote socket address");
1300 return NULL;
1301 }
1302
1303 return socket_sockaddr_to_address(&ss, sslen, errp);
1304}
2a8e21c7 1305
7e844959
AA
1306char *socket_address_to_string(struct SocketAddress *addr, Error **errp)
1307{
1308 char *buf;
1309 InetSocketAddress *inet;
7e844959
AA
1310
1311 switch (addr->type) {
1312 case SOCKET_ADDRESS_KIND_INET:
1313 inet = addr->u.inet.data;
1314 if (strchr(inet->host, ':') == NULL) {
44fdc764 1315 buf = g_strdup_printf("%s:%s", inet->host, inet->port);
7e844959 1316 } else {
44fdc764 1317 buf = g_strdup_printf("[%s]:%s", inet->host, inet->port);
7e844959
AA
1318 }
1319 break;
1320
1321 case SOCKET_ADDRESS_KIND_UNIX:
1322 buf = g_strdup(addr->u.q_unix.data->path);
1323 break;
1324
1325 case SOCKET_ADDRESS_KIND_FD:
1326 buf = g_strdup(addr->u.fd.data->str);
1327 break;
1328
6a02c806
SH
1329 case SOCKET_ADDRESS_KIND_VSOCK:
1330 buf = g_strdup_printf("%s:%s",
1331 addr->u.vsock.data->cid,
1332 addr->u.vsock.data->port);
1333 break;
1334
7e844959
AA
1335 default:
1336 error_setg(errp, "socket family %d unsupported",
1337 addr->type);
1338 return NULL;
1339 }
1340 return buf;
1341}