Statistics
| Branch: | Revision:

root / util / qemu-sockets.c @ 1f8f987d

History | View | Annotate | Download (26.5 kB)

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