Statistics
| Branch: | Revision:

root / net / socket.c @ 0056c093

History | View | Annotate | Download (19.7 kB)

1 42281ac9 Mark McLoughlin
/*
2 42281ac9 Mark McLoughlin
 * QEMU System Emulator
3 42281ac9 Mark McLoughlin
 *
4 42281ac9 Mark McLoughlin
 * Copyright (c) 2003-2008 Fabrice Bellard
5 42281ac9 Mark McLoughlin
 *
6 42281ac9 Mark McLoughlin
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 42281ac9 Mark McLoughlin
 * of this software and associated documentation files (the "Software"), to deal
8 42281ac9 Mark McLoughlin
 * in the Software without restriction, including without limitation the rights
9 42281ac9 Mark McLoughlin
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 42281ac9 Mark McLoughlin
 * copies of the Software, and to permit persons to whom the Software is
11 42281ac9 Mark McLoughlin
 * furnished to do so, subject to the following conditions:
12 42281ac9 Mark McLoughlin
 *
13 42281ac9 Mark McLoughlin
 * The above copyright notice and this permission notice shall be included in
14 42281ac9 Mark McLoughlin
 * all copies or substantial portions of the Software.
15 42281ac9 Mark McLoughlin
 *
16 42281ac9 Mark McLoughlin
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 42281ac9 Mark McLoughlin
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 42281ac9 Mark McLoughlin
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 42281ac9 Mark McLoughlin
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 42281ac9 Mark McLoughlin
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 42281ac9 Mark McLoughlin
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 42281ac9 Mark McLoughlin
 * THE SOFTWARE.
23 42281ac9 Mark McLoughlin
 */
24 42281ac9 Mark McLoughlin
#include "net/socket.h"
25 42281ac9 Mark McLoughlin
26 42281ac9 Mark McLoughlin
#include "config-host.h"
27 42281ac9 Mark McLoughlin
28 42281ac9 Mark McLoughlin
#include "net.h"
29 42281ac9 Mark McLoughlin
#include "qemu-char.h"
30 42281ac9 Mark McLoughlin
#include "qemu-common.h"
31 2f792016 Markus Armbruster
#include "qemu-error.h"
32 42281ac9 Mark McLoughlin
#include "qemu-option.h"
33 42281ac9 Mark McLoughlin
#include "qemu_socket.h"
34 42281ac9 Mark McLoughlin
35 42281ac9 Mark McLoughlin
typedef struct NetSocketState {
36 564f63e3 Mark McLoughlin
    VLANClientState nc;
37 42281ac9 Mark McLoughlin
    int fd;
38 42281ac9 Mark McLoughlin
    int state; /* 0 = getting length, 1 = getting data */
39 42281ac9 Mark McLoughlin
    unsigned int index;
40 42281ac9 Mark McLoughlin
    unsigned int packet_len;
41 42281ac9 Mark McLoughlin
    uint8_t buf[4096];
42 42281ac9 Mark McLoughlin
    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
43 42281ac9 Mark McLoughlin
} NetSocketState;
44 42281ac9 Mark McLoughlin
45 42281ac9 Mark McLoughlin
typedef struct NetSocketListenState {
46 42281ac9 Mark McLoughlin
    VLANState *vlan;
47 42281ac9 Mark McLoughlin
    char *model;
48 42281ac9 Mark McLoughlin
    char *name;
49 42281ac9 Mark McLoughlin
    int fd;
50 42281ac9 Mark McLoughlin
} NetSocketListenState;
51 42281ac9 Mark McLoughlin
52 42281ac9 Mark McLoughlin
/* XXX: we consider we can send the whole packet without blocking */
53 564f63e3 Mark McLoughlin
static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
54 42281ac9 Mark McLoughlin
{
55 564f63e3 Mark McLoughlin
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
56 42281ac9 Mark McLoughlin
    uint32_t len;
57 42281ac9 Mark McLoughlin
    len = htonl(size);
58 42281ac9 Mark McLoughlin
59 42281ac9 Mark McLoughlin
    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
60 42281ac9 Mark McLoughlin
    return send_all(s->fd, buf, size);
61 42281ac9 Mark McLoughlin
}
62 42281ac9 Mark McLoughlin
63 564f63e3 Mark McLoughlin
static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
64 42281ac9 Mark McLoughlin
{
65 564f63e3 Mark McLoughlin
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
66 42281ac9 Mark McLoughlin
67 42281ac9 Mark McLoughlin
    return sendto(s->fd, (const void *)buf, size, 0,
68 42281ac9 Mark McLoughlin
                  (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
69 42281ac9 Mark McLoughlin
}
70 42281ac9 Mark McLoughlin
71 42281ac9 Mark McLoughlin
static void net_socket_send(void *opaque)
72 42281ac9 Mark McLoughlin
{
73 42281ac9 Mark McLoughlin
    NetSocketState *s = opaque;
74 42281ac9 Mark McLoughlin
    int size, err;
75 42281ac9 Mark McLoughlin
    unsigned l;
76 42281ac9 Mark McLoughlin
    uint8_t buf1[4096];
77 42281ac9 Mark McLoughlin
    const uint8_t *buf;
78 42281ac9 Mark McLoughlin
79 00aa0040 Blue Swirl
    size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
80 42281ac9 Mark McLoughlin
    if (size < 0) {
81 42281ac9 Mark McLoughlin
        err = socket_error();
82 42281ac9 Mark McLoughlin
        if (err != EWOULDBLOCK)
83 42281ac9 Mark McLoughlin
            goto eoc;
84 42281ac9 Mark McLoughlin
    } else if (size == 0) {
85 42281ac9 Mark McLoughlin
        /* end of connection */
86 42281ac9 Mark McLoughlin
    eoc:
87 42281ac9 Mark McLoughlin
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
88 42281ac9 Mark McLoughlin
        closesocket(s->fd);
89 42281ac9 Mark McLoughlin
        return;
90 42281ac9 Mark McLoughlin
    }
91 42281ac9 Mark McLoughlin
    buf = buf1;
92 42281ac9 Mark McLoughlin
    while (size > 0) {
93 42281ac9 Mark McLoughlin
        /* reassemble a packet from the network */
94 42281ac9 Mark McLoughlin
        switch(s->state) {
95 42281ac9 Mark McLoughlin
        case 0:
96 42281ac9 Mark McLoughlin
            l = 4 - s->index;
97 42281ac9 Mark McLoughlin
            if (l > size)
98 42281ac9 Mark McLoughlin
                l = size;
99 42281ac9 Mark McLoughlin
            memcpy(s->buf + s->index, buf, l);
100 42281ac9 Mark McLoughlin
            buf += l;
101 42281ac9 Mark McLoughlin
            size -= l;
102 42281ac9 Mark McLoughlin
            s->index += l;
103 42281ac9 Mark McLoughlin
            if (s->index == 4) {
104 42281ac9 Mark McLoughlin
                /* got length */
105 42281ac9 Mark McLoughlin
                s->packet_len = ntohl(*(uint32_t *)s->buf);
106 42281ac9 Mark McLoughlin
                s->index = 0;
107 42281ac9 Mark McLoughlin
                s->state = 1;
108 42281ac9 Mark McLoughlin
            }
109 42281ac9 Mark McLoughlin
            break;
110 42281ac9 Mark McLoughlin
        case 1:
111 42281ac9 Mark McLoughlin
            l = s->packet_len - s->index;
112 42281ac9 Mark McLoughlin
            if (l > size)
113 42281ac9 Mark McLoughlin
                l = size;
114 42281ac9 Mark McLoughlin
            if (s->index + l <= sizeof(s->buf)) {
115 42281ac9 Mark McLoughlin
                memcpy(s->buf + s->index, buf, l);
116 42281ac9 Mark McLoughlin
            } else {
117 42281ac9 Mark McLoughlin
                fprintf(stderr, "serious error: oversized packet received,"
118 42281ac9 Mark McLoughlin
                    "connection terminated.\n");
119 42281ac9 Mark McLoughlin
                s->state = 0;
120 42281ac9 Mark McLoughlin
                goto eoc;
121 42281ac9 Mark McLoughlin
            }
122 42281ac9 Mark McLoughlin
123 42281ac9 Mark McLoughlin
            s->index += l;
124 42281ac9 Mark McLoughlin
            buf += l;
125 42281ac9 Mark McLoughlin
            size -= l;
126 42281ac9 Mark McLoughlin
            if (s->index >= s->packet_len) {
127 564f63e3 Mark McLoughlin
                qemu_send_packet(&s->nc, s->buf, s->packet_len);
128 42281ac9 Mark McLoughlin
                s->index = 0;
129 42281ac9 Mark McLoughlin
                s->state = 0;
130 42281ac9 Mark McLoughlin
            }
131 42281ac9 Mark McLoughlin
            break;
132 42281ac9 Mark McLoughlin
        }
133 42281ac9 Mark McLoughlin
    }
134 42281ac9 Mark McLoughlin
}
135 42281ac9 Mark McLoughlin
136 42281ac9 Mark McLoughlin
static void net_socket_send_dgram(void *opaque)
137 42281ac9 Mark McLoughlin
{
138 42281ac9 Mark McLoughlin
    NetSocketState *s = opaque;
139 42281ac9 Mark McLoughlin
    int size;
140 42281ac9 Mark McLoughlin
141 00aa0040 Blue Swirl
    size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
142 42281ac9 Mark McLoughlin
    if (size < 0)
143 42281ac9 Mark McLoughlin
        return;
144 42281ac9 Mark McLoughlin
    if (size == 0) {
145 42281ac9 Mark McLoughlin
        /* end of connection */
146 42281ac9 Mark McLoughlin
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
147 42281ac9 Mark McLoughlin
        return;
148 42281ac9 Mark McLoughlin
    }
149 564f63e3 Mark McLoughlin
    qemu_send_packet(&s->nc, s->buf, size);
150 42281ac9 Mark McLoughlin
}
151 42281ac9 Mark McLoughlin
152 3a75e74c Mike Ryan
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
153 42281ac9 Mark McLoughlin
{
154 42281ac9 Mark McLoughlin
    struct ip_mreq imr;
155 42281ac9 Mark McLoughlin
    int fd;
156 42281ac9 Mark McLoughlin
    int val, ret;
157 23ddf2bb Brad
#ifdef __OpenBSD__
158 23ddf2bb Brad
    unsigned char loop;
159 23ddf2bb Brad
#else
160 23ddf2bb Brad
    int loop;
161 23ddf2bb Brad
#endif
162 23ddf2bb Brad
163 42281ac9 Mark McLoughlin
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
164 842480d4 Stefan Hajnoczi
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
165 842480d4 Stefan Hajnoczi
                "does not contain a multicast address\n",
166 842480d4 Stefan Hajnoczi
                inet_ntoa(mcastaddr->sin_addr),
167 42281ac9 Mark McLoughlin
                (int)ntohl(mcastaddr->sin_addr.s_addr));
168 842480d4 Stefan Hajnoczi
        return -1;
169 42281ac9 Mark McLoughlin
170 42281ac9 Mark McLoughlin
    }
171 40ff6d7e Kevin Wolf
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
172 42281ac9 Mark McLoughlin
    if (fd < 0) {
173 42281ac9 Mark McLoughlin
        perror("socket(PF_INET, SOCK_DGRAM)");
174 42281ac9 Mark McLoughlin
        return -1;
175 42281ac9 Mark McLoughlin
    }
176 42281ac9 Mark McLoughlin
177 42281ac9 Mark McLoughlin
    val = 1;
178 42281ac9 Mark McLoughlin
    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
179 42281ac9 Mark McLoughlin
                   (const char *)&val, sizeof(val));
180 42281ac9 Mark McLoughlin
    if (ret < 0) {
181 842480d4 Stefan Hajnoczi
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
182 842480d4 Stefan Hajnoczi
        goto fail;
183 42281ac9 Mark McLoughlin
    }
184 42281ac9 Mark McLoughlin
185 42281ac9 Mark McLoughlin
    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
186 42281ac9 Mark McLoughlin
    if (ret < 0) {
187 42281ac9 Mark McLoughlin
        perror("bind");
188 42281ac9 Mark McLoughlin
        goto fail;
189 42281ac9 Mark McLoughlin
    }
190 42281ac9 Mark McLoughlin
191 42281ac9 Mark McLoughlin
    /* Add host to multicast group */
192 42281ac9 Mark McLoughlin
    imr.imr_multiaddr = mcastaddr->sin_addr;
193 3a75e74c Mike Ryan
    if (localaddr) {
194 3a75e74c Mike Ryan
        imr.imr_interface = *localaddr;
195 3a75e74c Mike Ryan
    } else {
196 3a75e74c Mike Ryan
        imr.imr_interface.s_addr = htonl(INADDR_ANY);
197 3a75e74c Mike Ryan
    }
198 42281ac9 Mark McLoughlin
199 42281ac9 Mark McLoughlin
    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
200 42281ac9 Mark McLoughlin
                     (const char *)&imr, sizeof(struct ip_mreq));
201 42281ac9 Mark McLoughlin
    if (ret < 0) {
202 842480d4 Stefan Hajnoczi
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
203 842480d4 Stefan Hajnoczi
        goto fail;
204 42281ac9 Mark McLoughlin
    }
205 42281ac9 Mark McLoughlin
206 42281ac9 Mark McLoughlin
    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
207 23ddf2bb Brad
    loop = 1;
208 42281ac9 Mark McLoughlin
    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
209 23ddf2bb Brad
                   (const char *)&loop, sizeof(loop));
210 42281ac9 Mark McLoughlin
    if (ret < 0) {
211 842480d4 Stefan Hajnoczi
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
212 842480d4 Stefan Hajnoczi
        goto fail;
213 42281ac9 Mark McLoughlin
    }
214 42281ac9 Mark McLoughlin
215 3a75e74c Mike Ryan
    /* If a bind address is given, only send packets from that address */
216 3a75e74c Mike Ryan
    if (localaddr != NULL) {
217 4d22c6c2 Blue Swirl
        ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
218 4d22c6c2 Blue Swirl
                         (const char *)localaddr, sizeof(*localaddr));
219 3a75e74c Mike Ryan
        if (ret < 0) {
220 3a75e74c Mike Ryan
            perror("setsockopt(IP_MULTICAST_IF)");
221 3a75e74c Mike Ryan
            goto fail;
222 3a75e74c Mike Ryan
        }
223 3a75e74c Mike Ryan
    }
224 3a75e74c Mike Ryan
225 42281ac9 Mark McLoughlin
    socket_set_nonblock(fd);
226 42281ac9 Mark McLoughlin
    return fd;
227 42281ac9 Mark McLoughlin
fail:
228 42281ac9 Mark McLoughlin
    if (fd >= 0)
229 42281ac9 Mark McLoughlin
        closesocket(fd);
230 42281ac9 Mark McLoughlin
    return -1;
231 42281ac9 Mark McLoughlin
}
232 42281ac9 Mark McLoughlin
233 564f63e3 Mark McLoughlin
static void net_socket_cleanup(VLANClientState *nc)
234 42281ac9 Mark McLoughlin
{
235 564f63e3 Mark McLoughlin
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
236 42281ac9 Mark McLoughlin
    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
237 42281ac9 Mark McLoughlin
    close(s->fd);
238 42281ac9 Mark McLoughlin
}
239 42281ac9 Mark McLoughlin
240 564f63e3 Mark McLoughlin
static NetClientInfo net_dgram_socket_info = {
241 564f63e3 Mark McLoughlin
    .type = NET_CLIENT_TYPE_SOCKET,
242 564f63e3 Mark McLoughlin
    .size = sizeof(NetSocketState),
243 564f63e3 Mark McLoughlin
    .receive = net_socket_receive_dgram,
244 564f63e3 Mark McLoughlin
    .cleanup = net_socket_cleanup,
245 564f63e3 Mark McLoughlin
};
246 564f63e3 Mark McLoughlin
247 42281ac9 Mark McLoughlin
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
248 42281ac9 Mark McLoughlin
                                                const char *model,
249 42281ac9 Mark McLoughlin
                                                const char *name,
250 42281ac9 Mark McLoughlin
                                                int fd, int is_connected)
251 42281ac9 Mark McLoughlin
{
252 42281ac9 Mark McLoughlin
    struct sockaddr_in saddr;
253 42281ac9 Mark McLoughlin
    int newfd;
254 42281ac9 Mark McLoughlin
    socklen_t saddr_len;
255 564f63e3 Mark McLoughlin
    VLANClientState *nc;
256 42281ac9 Mark McLoughlin
    NetSocketState *s;
257 42281ac9 Mark McLoughlin
258 42281ac9 Mark McLoughlin
    /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
259 42281ac9 Mark McLoughlin
     * Because this may be "shared" socket from a "master" process, datagrams would be recv()
260 42281ac9 Mark McLoughlin
     * by ONLY ONE process: we must "clone" this dgram socket --jjo
261 42281ac9 Mark McLoughlin
     */
262 42281ac9 Mark McLoughlin
263 42281ac9 Mark McLoughlin
    if (is_connected) {
264 842480d4 Stefan Hajnoczi
        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
265 842480d4 Stefan Hajnoczi
            /* must be bound */
266 842480d4 Stefan Hajnoczi
            if (saddr.sin_addr.s_addr == 0) {
267 842480d4 Stefan Hajnoczi
                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
268 842480d4 Stefan Hajnoczi
                        "cannot setup multicast dst addr\n", fd);
269 e5d1fca0 Stefan Hajnoczi
                goto err;
270 842480d4 Stefan Hajnoczi
            }
271 842480d4 Stefan Hajnoczi
            /* clone dgram socket */
272 842480d4 Stefan Hajnoczi
            newfd = net_socket_mcast_create(&saddr, NULL);
273 842480d4 Stefan Hajnoczi
            if (newfd < 0) {
274 842480d4 Stefan Hajnoczi
                /* error already reported by net_socket_mcast_create() */
275 e5d1fca0 Stefan Hajnoczi
                goto err;
276 842480d4 Stefan Hajnoczi
            }
277 842480d4 Stefan Hajnoczi
            /* clone newfd to fd, close newfd */
278 842480d4 Stefan Hajnoczi
            dup2(newfd, fd);
279 842480d4 Stefan Hajnoczi
            close(newfd);
280 842480d4 Stefan Hajnoczi
281 842480d4 Stefan Hajnoczi
        } else {
282 842480d4 Stefan Hajnoczi
            fprintf(stderr,
283 842480d4 Stefan Hajnoczi
                    "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
284 842480d4 Stefan Hajnoczi
                    fd, strerror(errno));
285 e5d1fca0 Stefan Hajnoczi
            goto err;
286 842480d4 Stefan Hajnoczi
        }
287 42281ac9 Mark McLoughlin
    }
288 42281ac9 Mark McLoughlin
289 564f63e3 Mark McLoughlin
    nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);
290 564f63e3 Mark McLoughlin
291 564f63e3 Mark McLoughlin
    snprintf(nc->info_str, sizeof(nc->info_str),
292 842480d4 Stefan Hajnoczi
            "socket: fd=%d (%s mcast=%s:%d)",
293 842480d4 Stefan Hajnoczi
            fd, is_connected ? "cloned" : "",
294 842480d4 Stefan Hajnoczi
            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
295 564f63e3 Mark McLoughlin
296 564f63e3 Mark McLoughlin
    s = DO_UPCAST(NetSocketState, nc, nc);
297 564f63e3 Mark McLoughlin
298 42281ac9 Mark McLoughlin
    s->fd = fd;
299 42281ac9 Mark McLoughlin
300 42281ac9 Mark McLoughlin
    qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
301 42281ac9 Mark McLoughlin
302 42281ac9 Mark McLoughlin
    /* mcast: save bound address as dst */
303 42281ac9 Mark McLoughlin
    if (is_connected) s->dgram_dst=saddr;
304 42281ac9 Mark McLoughlin
305 42281ac9 Mark McLoughlin
    return s;
306 e5d1fca0 Stefan Hajnoczi
307 e5d1fca0 Stefan Hajnoczi
err:
308 e5d1fca0 Stefan Hajnoczi
    closesocket(fd);
309 e5d1fca0 Stefan Hajnoczi
    return NULL;
310 42281ac9 Mark McLoughlin
}
311 42281ac9 Mark McLoughlin
312 42281ac9 Mark McLoughlin
static void net_socket_connect(void *opaque)
313 42281ac9 Mark McLoughlin
{
314 42281ac9 Mark McLoughlin
    NetSocketState *s = opaque;
315 42281ac9 Mark McLoughlin
    qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
316 42281ac9 Mark McLoughlin
}
317 42281ac9 Mark McLoughlin
318 564f63e3 Mark McLoughlin
static NetClientInfo net_socket_info = {
319 564f63e3 Mark McLoughlin
    .type = NET_CLIENT_TYPE_SOCKET,
320 564f63e3 Mark McLoughlin
    .size = sizeof(NetSocketState),
321 564f63e3 Mark McLoughlin
    .receive = net_socket_receive,
322 564f63e3 Mark McLoughlin
    .cleanup = net_socket_cleanup,
323 564f63e3 Mark McLoughlin
};
324 564f63e3 Mark McLoughlin
325 42281ac9 Mark McLoughlin
static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
326 42281ac9 Mark McLoughlin
                                                 const char *model,
327 42281ac9 Mark McLoughlin
                                                 const char *name,
328 42281ac9 Mark McLoughlin
                                                 int fd, int is_connected)
329 42281ac9 Mark McLoughlin
{
330 564f63e3 Mark McLoughlin
    VLANClientState *nc;
331 42281ac9 Mark McLoughlin
    NetSocketState *s;
332 564f63e3 Mark McLoughlin
333 564f63e3 Mark McLoughlin
    nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name);
334 564f63e3 Mark McLoughlin
335 564f63e3 Mark McLoughlin
    snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);
336 564f63e3 Mark McLoughlin
337 564f63e3 Mark McLoughlin
    s = DO_UPCAST(NetSocketState, nc, nc);
338 564f63e3 Mark McLoughlin
339 42281ac9 Mark McLoughlin
    s->fd = fd;
340 564f63e3 Mark McLoughlin
341 42281ac9 Mark McLoughlin
    if (is_connected) {
342 42281ac9 Mark McLoughlin
        net_socket_connect(s);
343 42281ac9 Mark McLoughlin
    } else {
344 42281ac9 Mark McLoughlin
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
345 42281ac9 Mark McLoughlin
    }
346 42281ac9 Mark McLoughlin
    return s;
347 42281ac9 Mark McLoughlin
}
348 42281ac9 Mark McLoughlin
349 42281ac9 Mark McLoughlin
static NetSocketState *net_socket_fd_init(VLANState *vlan,
350 42281ac9 Mark McLoughlin
                                          const char *model, const char *name,
351 42281ac9 Mark McLoughlin
                                          int fd, int is_connected)
352 42281ac9 Mark McLoughlin
{
353 42281ac9 Mark McLoughlin
    int so_type = -1, optlen=sizeof(so_type);
354 42281ac9 Mark McLoughlin
355 42281ac9 Mark McLoughlin
    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
356 42281ac9 Mark McLoughlin
        (socklen_t *)&optlen)< 0) {
357 842480d4 Stefan Hajnoczi
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
358 842480d4 Stefan Hajnoczi
                fd);
359 e5d1fca0 Stefan Hajnoczi
        closesocket(fd);
360 842480d4 Stefan Hajnoczi
        return NULL;
361 42281ac9 Mark McLoughlin
    }
362 42281ac9 Mark McLoughlin
    switch(so_type) {
363 42281ac9 Mark McLoughlin
    case SOCK_DGRAM:
364 42281ac9 Mark McLoughlin
        return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected);
365 42281ac9 Mark McLoughlin
    case SOCK_STREAM:
366 42281ac9 Mark McLoughlin
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
367 42281ac9 Mark McLoughlin
    default:
368 42281ac9 Mark McLoughlin
        /* who knows ... this could be a eg. a pty, do warn and continue as stream */
369 42281ac9 Mark McLoughlin
        fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
370 42281ac9 Mark McLoughlin
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
371 42281ac9 Mark McLoughlin
    }
372 42281ac9 Mark McLoughlin
    return NULL;
373 42281ac9 Mark McLoughlin
}
374 42281ac9 Mark McLoughlin
375 42281ac9 Mark McLoughlin
static void net_socket_accept(void *opaque)
376 42281ac9 Mark McLoughlin
{
377 42281ac9 Mark McLoughlin
    NetSocketListenState *s = opaque;
378 42281ac9 Mark McLoughlin
    NetSocketState *s1;
379 42281ac9 Mark McLoughlin
    struct sockaddr_in saddr;
380 42281ac9 Mark McLoughlin
    socklen_t len;
381 42281ac9 Mark McLoughlin
    int fd;
382 42281ac9 Mark McLoughlin
383 42281ac9 Mark McLoughlin
    for(;;) {
384 42281ac9 Mark McLoughlin
        len = sizeof(saddr);
385 40ff6d7e Kevin Wolf
        fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len);
386 42281ac9 Mark McLoughlin
        if (fd < 0 && errno != EINTR) {
387 42281ac9 Mark McLoughlin
            return;
388 42281ac9 Mark McLoughlin
        } else if (fd >= 0) {
389 42281ac9 Mark McLoughlin
            break;
390 42281ac9 Mark McLoughlin
        }
391 42281ac9 Mark McLoughlin
    }
392 42281ac9 Mark McLoughlin
    s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
393 e5d1fca0 Stefan Hajnoczi
    if (s1) {
394 564f63e3 Mark McLoughlin
        snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
395 42281ac9 Mark McLoughlin
                 "socket: connection from %s:%d",
396 42281ac9 Mark McLoughlin
                 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
397 42281ac9 Mark McLoughlin
    }
398 42281ac9 Mark McLoughlin
}
399 42281ac9 Mark McLoughlin
400 42281ac9 Mark McLoughlin
static int net_socket_listen_init(VLANState *vlan,
401 42281ac9 Mark McLoughlin
                                  const char *model,
402 42281ac9 Mark McLoughlin
                                  const char *name,
403 42281ac9 Mark McLoughlin
                                  const char *host_str)
404 42281ac9 Mark McLoughlin
{
405 42281ac9 Mark McLoughlin
    NetSocketListenState *s;
406 42281ac9 Mark McLoughlin
    int fd, val, ret;
407 42281ac9 Mark McLoughlin
    struct sockaddr_in saddr;
408 42281ac9 Mark McLoughlin
409 42281ac9 Mark McLoughlin
    if (parse_host_port(&saddr, host_str) < 0)
410 42281ac9 Mark McLoughlin
        return -1;
411 42281ac9 Mark McLoughlin
412 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(NetSocketListenState));
413 42281ac9 Mark McLoughlin
414 40ff6d7e Kevin Wolf
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
415 42281ac9 Mark McLoughlin
    if (fd < 0) {
416 42281ac9 Mark McLoughlin
        perror("socket");
417 c7ee8f68 Zhi Hui Li
        g_free(s);
418 42281ac9 Mark McLoughlin
        return -1;
419 42281ac9 Mark McLoughlin
    }
420 42281ac9 Mark McLoughlin
    socket_set_nonblock(fd);
421 42281ac9 Mark McLoughlin
422 42281ac9 Mark McLoughlin
    /* allow fast reuse */
423 42281ac9 Mark McLoughlin
    val = 1;
424 42281ac9 Mark McLoughlin
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
425 42281ac9 Mark McLoughlin
426 42281ac9 Mark McLoughlin
    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
427 42281ac9 Mark McLoughlin
    if (ret < 0) {
428 42281ac9 Mark McLoughlin
        perror("bind");
429 c7ee8f68 Zhi Hui Li
        g_free(s);
430 a46667ea Peter Maydell
        closesocket(fd);
431 42281ac9 Mark McLoughlin
        return -1;
432 42281ac9 Mark McLoughlin
    }
433 42281ac9 Mark McLoughlin
    ret = listen(fd, 0);
434 42281ac9 Mark McLoughlin
    if (ret < 0) {
435 42281ac9 Mark McLoughlin
        perror("listen");
436 c7ee8f68 Zhi Hui Li
        g_free(s);
437 a46667ea Peter Maydell
        closesocket(fd);
438 42281ac9 Mark McLoughlin
        return -1;
439 42281ac9 Mark McLoughlin
    }
440 42281ac9 Mark McLoughlin
    s->vlan = vlan;
441 7267c094 Anthony Liguori
    s->model = g_strdup(model);
442 7267c094 Anthony Liguori
    s->name = name ? g_strdup(name) : NULL;
443 42281ac9 Mark McLoughlin
    s->fd = fd;
444 42281ac9 Mark McLoughlin
    qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
445 42281ac9 Mark McLoughlin
    return 0;
446 42281ac9 Mark McLoughlin
}
447 42281ac9 Mark McLoughlin
448 42281ac9 Mark McLoughlin
static int net_socket_connect_init(VLANState *vlan,
449 42281ac9 Mark McLoughlin
                                   const char *model,
450 42281ac9 Mark McLoughlin
                                   const char *name,
451 42281ac9 Mark McLoughlin
                                   const char *host_str)
452 42281ac9 Mark McLoughlin
{
453 42281ac9 Mark McLoughlin
    NetSocketState *s;
454 42281ac9 Mark McLoughlin
    int fd, connected, ret, err;
455 42281ac9 Mark McLoughlin
    struct sockaddr_in saddr;
456 42281ac9 Mark McLoughlin
457 42281ac9 Mark McLoughlin
    if (parse_host_port(&saddr, host_str) < 0)
458 42281ac9 Mark McLoughlin
        return -1;
459 42281ac9 Mark McLoughlin
460 40ff6d7e Kevin Wolf
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
461 42281ac9 Mark McLoughlin
    if (fd < 0) {
462 42281ac9 Mark McLoughlin
        perror("socket");
463 42281ac9 Mark McLoughlin
        return -1;
464 42281ac9 Mark McLoughlin
    }
465 42281ac9 Mark McLoughlin
    socket_set_nonblock(fd);
466 42281ac9 Mark McLoughlin
467 42281ac9 Mark McLoughlin
    connected = 0;
468 42281ac9 Mark McLoughlin
    for(;;) {
469 42281ac9 Mark McLoughlin
        ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
470 42281ac9 Mark McLoughlin
        if (ret < 0) {
471 42281ac9 Mark McLoughlin
            err = socket_error();
472 42281ac9 Mark McLoughlin
            if (err == EINTR || err == EWOULDBLOCK) {
473 42281ac9 Mark McLoughlin
            } else if (err == EINPROGRESS) {
474 42281ac9 Mark McLoughlin
                break;
475 42281ac9 Mark McLoughlin
#ifdef _WIN32
476 c7eb1f02 Pavel Dovgaluk
            } else if (err == WSAEALREADY || err == WSAEINVAL) {
477 42281ac9 Mark McLoughlin
                break;
478 42281ac9 Mark McLoughlin
#endif
479 42281ac9 Mark McLoughlin
            } else {
480 42281ac9 Mark McLoughlin
                perror("connect");
481 42281ac9 Mark McLoughlin
                closesocket(fd);
482 42281ac9 Mark McLoughlin
                return -1;
483 42281ac9 Mark McLoughlin
            }
484 42281ac9 Mark McLoughlin
        } else {
485 42281ac9 Mark McLoughlin
            connected = 1;
486 42281ac9 Mark McLoughlin
            break;
487 42281ac9 Mark McLoughlin
        }
488 42281ac9 Mark McLoughlin
    }
489 42281ac9 Mark McLoughlin
    s = net_socket_fd_init(vlan, model, name, fd, connected);
490 42281ac9 Mark McLoughlin
    if (!s)
491 42281ac9 Mark McLoughlin
        return -1;
492 564f63e3 Mark McLoughlin
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
493 42281ac9 Mark McLoughlin
             "socket: connect to %s:%d",
494 42281ac9 Mark McLoughlin
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
495 42281ac9 Mark McLoughlin
    return 0;
496 42281ac9 Mark McLoughlin
}
497 42281ac9 Mark McLoughlin
498 42281ac9 Mark McLoughlin
static int net_socket_mcast_init(VLANState *vlan,
499 42281ac9 Mark McLoughlin
                                 const char *model,
500 42281ac9 Mark McLoughlin
                                 const char *name,
501 3a75e74c Mike Ryan
                                 const char *host_str,
502 3a75e74c Mike Ryan
                                 const char *localaddr_str)
503 42281ac9 Mark McLoughlin
{
504 42281ac9 Mark McLoughlin
    NetSocketState *s;
505 42281ac9 Mark McLoughlin
    int fd;
506 42281ac9 Mark McLoughlin
    struct sockaddr_in saddr;
507 3a75e74c Mike Ryan
    struct in_addr localaddr, *param_localaddr;
508 42281ac9 Mark McLoughlin
509 42281ac9 Mark McLoughlin
    if (parse_host_port(&saddr, host_str) < 0)
510 42281ac9 Mark McLoughlin
        return -1;
511 42281ac9 Mark McLoughlin
512 3a75e74c Mike Ryan
    if (localaddr_str != NULL) {
513 3a75e74c Mike Ryan
        if (inet_aton(localaddr_str, &localaddr) == 0)
514 3a75e74c Mike Ryan
            return -1;
515 3a75e74c Mike Ryan
        param_localaddr = &localaddr;
516 3a75e74c Mike Ryan
    } else {
517 3a75e74c Mike Ryan
        param_localaddr = NULL;
518 3a75e74c Mike Ryan
    }
519 42281ac9 Mark McLoughlin
520 3a75e74c Mike Ryan
    fd = net_socket_mcast_create(&saddr, param_localaddr);
521 42281ac9 Mark McLoughlin
    if (fd < 0)
522 842480d4 Stefan Hajnoczi
        return -1;
523 42281ac9 Mark McLoughlin
524 42281ac9 Mark McLoughlin
    s = net_socket_fd_init(vlan, model, name, fd, 0);
525 42281ac9 Mark McLoughlin
    if (!s)
526 42281ac9 Mark McLoughlin
        return -1;
527 42281ac9 Mark McLoughlin
528 42281ac9 Mark McLoughlin
    s->dgram_dst = saddr;
529 42281ac9 Mark McLoughlin
530 564f63e3 Mark McLoughlin
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
531 42281ac9 Mark McLoughlin
             "socket: mcast=%s:%d",
532 42281ac9 Mark McLoughlin
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
533 42281ac9 Mark McLoughlin
    return 0;
534 42281ac9 Mark McLoughlin
535 42281ac9 Mark McLoughlin
}
536 42281ac9 Mark McLoughlin
537 0e0e7fac Benjamin
static int net_socket_udp_init(VLANState *vlan,
538 0e0e7fac Benjamin
                                 const char *model,
539 0e0e7fac Benjamin
                                 const char *name,
540 0e0e7fac Benjamin
                                 const char *rhost,
541 0e0e7fac Benjamin
                                 const char *lhost)
542 0e0e7fac Benjamin
{
543 0e0e7fac Benjamin
    NetSocketState *s;
544 0e0e7fac Benjamin
    int fd, val, ret;
545 0e0e7fac Benjamin
    struct sockaddr_in laddr, raddr;
546 0e0e7fac Benjamin
547 0e0e7fac Benjamin
    if (parse_host_port(&laddr, lhost) < 0) {
548 0e0e7fac Benjamin
        return -1;
549 0e0e7fac Benjamin
    }
550 0e0e7fac Benjamin
551 0e0e7fac Benjamin
    if (parse_host_port(&raddr, rhost) < 0) {
552 0e0e7fac Benjamin
        return -1;
553 0e0e7fac Benjamin
    }
554 0e0e7fac Benjamin
555 0e0e7fac Benjamin
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
556 0e0e7fac Benjamin
    if (fd < 0) {
557 0e0e7fac Benjamin
        perror("socket(PF_INET, SOCK_DGRAM)");
558 0e0e7fac Benjamin
        return -1;
559 0e0e7fac Benjamin
    }
560 0e0e7fac Benjamin
    val = 1;
561 0e0e7fac Benjamin
    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
562 0e0e7fac Benjamin
                   (const char *)&val, sizeof(val));
563 0e0e7fac Benjamin
    if (ret < 0) {
564 0e0e7fac Benjamin
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
565 0e0e7fac Benjamin
        closesocket(fd);
566 0e0e7fac Benjamin
        return -1;
567 0e0e7fac Benjamin
    }
568 0e0e7fac Benjamin
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
569 0e0e7fac Benjamin
    if (ret < 0) {
570 0e0e7fac Benjamin
        perror("bind");
571 0e0e7fac Benjamin
        closesocket(fd);
572 0e0e7fac Benjamin
        return -1;
573 0e0e7fac Benjamin
    }
574 0e0e7fac Benjamin
575 0e0e7fac Benjamin
    s = net_socket_fd_init(vlan, model, name, fd, 0);
576 0e0e7fac Benjamin
    if (!s) {
577 0e0e7fac Benjamin
        return -1;
578 0e0e7fac Benjamin
    }
579 0e0e7fac Benjamin
580 0e0e7fac Benjamin
    s->dgram_dst = raddr;
581 0e0e7fac Benjamin
582 0e0e7fac Benjamin
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
583 0e0e7fac Benjamin
             "socket: udp=%s:%d",
584 0e0e7fac Benjamin
             inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
585 0e0e7fac Benjamin
    return 0;
586 0e0e7fac Benjamin
}
587 0e0e7fac Benjamin
588 42281ac9 Mark McLoughlin
int net_init_socket(QemuOpts *opts,
589 42281ac9 Mark McLoughlin
                    Monitor *mon,
590 42281ac9 Mark McLoughlin
                    const char *name,
591 42281ac9 Mark McLoughlin
                    VLANState *vlan)
592 42281ac9 Mark McLoughlin
{
593 42281ac9 Mark McLoughlin
    if (qemu_opt_get(opts, "fd")) {
594 42281ac9 Mark McLoughlin
        int fd;
595 42281ac9 Mark McLoughlin
596 42281ac9 Mark McLoughlin
        if (qemu_opt_get(opts, "listen") ||
597 42281ac9 Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
598 3a75e74c Mike Ryan
            qemu_opt_get(opts, "mcast") ||
599 3a75e74c Mike Ryan
            qemu_opt_get(opts, "localaddr")) {
600 6daf194d Markus Armbruster
            error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=");
601 42281ac9 Mark McLoughlin
            return -1;
602 42281ac9 Mark McLoughlin
        }
603 42281ac9 Mark McLoughlin
604 42281ac9 Mark McLoughlin
        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
605 42281ac9 Mark McLoughlin
        if (fd == -1) {
606 42281ac9 Mark McLoughlin
            return -1;
607 42281ac9 Mark McLoughlin
        }
608 42281ac9 Mark McLoughlin
609 42281ac9 Mark McLoughlin
        if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
610 42281ac9 Mark McLoughlin
            return -1;
611 42281ac9 Mark McLoughlin
        }
612 42281ac9 Mark McLoughlin
    } else if (qemu_opt_get(opts, "listen")) {
613 42281ac9 Mark McLoughlin
        const char *listen;
614 42281ac9 Mark McLoughlin
615 42281ac9 Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
616 42281ac9 Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
617 3a75e74c Mike Ryan
            qemu_opt_get(opts, "mcast") ||
618 3a75e74c Mike Ryan
            qemu_opt_get(opts, "localaddr")) {
619 6daf194d Markus Armbruster
            error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=");
620 42281ac9 Mark McLoughlin
            return -1;
621 42281ac9 Mark McLoughlin
        }
622 42281ac9 Mark McLoughlin
623 42281ac9 Mark McLoughlin
        listen = qemu_opt_get(opts, "listen");
624 42281ac9 Mark McLoughlin
625 42281ac9 Mark McLoughlin
        if (net_socket_listen_init(vlan, "socket", name, listen) == -1) {
626 42281ac9 Mark McLoughlin
            return -1;
627 42281ac9 Mark McLoughlin
        }
628 42281ac9 Mark McLoughlin
    } else if (qemu_opt_get(opts, "connect")) {
629 42281ac9 Mark McLoughlin
        const char *connect;
630 42281ac9 Mark McLoughlin
631 42281ac9 Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
632 42281ac9 Mark McLoughlin
            qemu_opt_get(opts, "listen") ||
633 3a75e74c Mike Ryan
            qemu_opt_get(opts, "mcast") ||
634 3a75e74c Mike Ryan
            qemu_opt_get(opts, "localaddr")) {
635 6daf194d Markus Armbruster
            error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=");
636 42281ac9 Mark McLoughlin
            return -1;
637 42281ac9 Mark McLoughlin
        }
638 42281ac9 Mark McLoughlin
639 42281ac9 Mark McLoughlin
        connect = qemu_opt_get(opts, "connect");
640 42281ac9 Mark McLoughlin
641 42281ac9 Mark McLoughlin
        if (net_socket_connect_init(vlan, "socket", name, connect) == -1) {
642 42281ac9 Mark McLoughlin
            return -1;
643 42281ac9 Mark McLoughlin
        }
644 42281ac9 Mark McLoughlin
    } else if (qemu_opt_get(opts, "mcast")) {
645 3a75e74c Mike Ryan
        const char *mcast, *localaddr;
646 42281ac9 Mark McLoughlin
647 42281ac9 Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
648 42281ac9 Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
649 42281ac9 Mark McLoughlin
            qemu_opt_get(opts, "listen")) {
650 1ecda02b Markus Armbruster
            error_report("fd=, connect= and listen= is invalid with mcast=");
651 42281ac9 Mark McLoughlin
            return -1;
652 42281ac9 Mark McLoughlin
        }
653 42281ac9 Mark McLoughlin
654 42281ac9 Mark McLoughlin
        mcast = qemu_opt_get(opts, "mcast");
655 3a75e74c Mike Ryan
        localaddr = qemu_opt_get(opts, "localaddr");
656 42281ac9 Mark McLoughlin
657 3a75e74c Mike Ryan
        if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
658 42281ac9 Mark McLoughlin
            return -1;
659 42281ac9 Mark McLoughlin
        }
660 0e0e7fac Benjamin
    } else if (qemu_opt_get(opts, "udp")) {
661 0e0e7fac Benjamin
        const char *udp, *localaddr;
662 0e0e7fac Benjamin
663 0e0e7fac Benjamin
        if (qemu_opt_get(opts, "fd") ||
664 0e0e7fac Benjamin
            qemu_opt_get(opts, "connect") ||
665 0e0e7fac Benjamin
            qemu_opt_get(opts, "listen") ||
666 0e0e7fac Benjamin
            qemu_opt_get(opts, "mcast")) {
667 da8d6057 Benjamin MARSILI
            error_report("fd=, connect=, listen="
668 da8d6057 Benjamin MARSILI
                         " and mcast= is invalid with udp=");
669 0e0e7fac Benjamin
            return -1;
670 0e0e7fac Benjamin
        }
671 0e0e7fac Benjamin
672 0e0e7fac Benjamin
        udp = qemu_opt_get(opts, "udp");
673 0e0e7fac Benjamin
        localaddr = qemu_opt_get(opts, "localaddr");
674 0e0e7fac Benjamin
        if (localaddr == NULL) {
675 0e0e7fac Benjamin
                error_report("localaddr= is mandatory with udp=");
676 0e0e7fac Benjamin
                return -1;
677 0e0e7fac Benjamin
        }
678 0e0e7fac Benjamin
679 0e0e7fac Benjamin
        if (net_socket_udp_init(vlan, "udp", name, udp, localaddr) == -1) {
680 0e0e7fac Benjamin
            return -1;
681 0e0e7fac Benjamin
        }
682 42281ac9 Mark McLoughlin
    } else {
683 da8d6057 Benjamin MARSILI
        error_report("-socket requires fd=, listen=,"
684 da8d6057 Benjamin MARSILI
                     " connect=, mcast= or udp=");
685 42281ac9 Mark McLoughlin
        return -1;
686 42281ac9 Mark McLoughlin
    }
687 42281ac9 Mark McLoughlin
    return 0;
688 42281ac9 Mark McLoughlin
}