socket.c 20.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * QEMU System Emulator
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
Peter Maydell 已提交
24
#include "qemu/osdep.h"
25

P
Paolo Bonzini 已提交
26
#include "net/net.h"
27
#include "clients.h"
28
#include "monitor/monitor.h"
29
#include "qapi/error.h"
30
#include "qemu-common.h"
31 32 33 34
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "qemu/iov.h"
35
#include "qemu/main-loop.h"
36 37

typedef struct NetSocketState {
38
    NetClientState nc;
39
    int listen_fd;
40
    int fd;
41
    SocketReadState rs;
42
    unsigned int send_index;      /* number of bytes sent (only SOCK_STREAM) */
43
    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
44 45 46
    IOHandler *send_fn;           /* differs between SOCK_STREAM/SOCK_DGRAM */
    bool read_poll;               /* waiting to receive data? */
    bool write_poll;              /* waiting to transmit data? */
47 48
} NetSocketState;

49
static void net_socket_accept(void *opaque);
50 51 52 53
static void net_socket_writable(void *opaque);

static void net_socket_update_fd_handler(NetSocketState *s)
{
54 55 56 57
    qemu_set_fd_handler(s->fd,
                        s->read_poll ? s->send_fn : NULL,
                        s->write_poll ? net_socket_writable : NULL,
                        s);
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
}

static void net_socket_read_poll(NetSocketState *s, bool enable)
{
    s->read_poll = enable;
    net_socket_update_fd_handler(s);
}

static void net_socket_write_poll(NetSocketState *s, bool enable)
{
    s->write_poll = enable;
    net_socket_update_fd_handler(s);
}

static void net_socket_writable(void *opaque)
{
    NetSocketState *s = opaque;

    net_socket_write_poll(s, false);

    qemu_flush_queued_packets(&s->nc);
}
80

81
static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size)
82
{
83
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
84 85 86 87 88 89 90 91 92 93 94 95
    uint32_t len = htonl(size);
    struct iovec iov[] = {
        {
            .iov_base = &len,
            .iov_len  = sizeof(len),
        }, {
            .iov_base = (void *)buf,
            .iov_len  = size,
        },
    };
    size_t remaining;
    ssize_t ret;
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    remaining = iov_size(iov, 2) - s->send_index;
    ret = iov_send(s->fd, iov, 2, s->send_index, remaining);

    if (ret == -1 && errno == EAGAIN) {
        ret = 0; /* handled further down */
    }
    if (ret == -1) {
        s->send_index = 0;
        return -errno;
    }
    if (ret < (ssize_t)remaining) {
        s->send_index += ret;
        net_socket_write_poll(s, true);
        return 0;
    }
    s->send_index = 0;
    return size;
114 115
}

116
static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size)
117
{
118
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
119 120 121
    ssize_t ret;

    do {
122 123 124
        ret = qemu_sendto(s->fd, buf, size, 0,
                          (struct sockaddr *)&s->dgram_dst,
                          sizeof(s->dgram_dst));
125 126 127 128 129 130 131
    } while (ret == -1 && errno == EINTR);

    if (ret == -1 && errno == EAGAIN) {
        net_socket_write_poll(s, true);
        return 0;
    }
    return ret;
132 133
}

F
Fam Zheng 已提交
134 135 136 137 138 139 140 141 142
static void net_socket_send_completed(NetClientState *nc, ssize_t len)
{
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);

    if (!s->read_poll) {
        net_socket_read_poll(s, true);
    }
}

143 144 145 146 147 148 149 150 151 152 153
static void net_socket_rs_finalize(SocketReadState *rs)
{
    NetSocketState *s = container_of(rs, NetSocketState, rs);

    if (qemu_send_packet_async(&s->nc, rs->buf,
                               rs->packet_len,
                               net_socket_send_completed) == 0) {
        net_socket_read_poll(s, false);
    }
}

154 155 156
static void net_socket_send(void *opaque)
{
    NetSocketState *s = opaque;
157
    int size;
158
    int ret;
159
    uint8_t buf1[NET_BUFSIZE];
160 161
    const uint8_t *buf;

B
Blue Swirl 已提交
162
    size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
163
    if (size < 0) {
164
        if (errno != EWOULDBLOCK)
165 166 167 168
            goto eoc;
    } else if (size == 0) {
        /* end of connection */
    eoc:
169 170
        net_socket_read_poll(s, false);
        net_socket_write_poll(s, false);
171 172 173
        if (s->listen_fd != -1) {
            qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
        }
174
        closesocket(s->fd);
175 176

        s->fd = -1;
177
        net_socket_rs_init(&s->rs, net_socket_rs_finalize);
178 179 180
        s->nc.link_down = true;
        memset(s->nc.info_str, 0, sizeof(s->nc.info_str));

181 182 183 184
        return;
    }
    buf = buf1;

185 186 187 188
    ret = net_fill_rstate(&s->rs, buf, size);

    if (ret == -1) {
        goto eoc;
189 190 191 192 193 194 195 196
    }
}

static void net_socket_send_dgram(void *opaque)
{
    NetSocketState *s = opaque;
    int size;

197
    size = qemu_recv(s->fd, s->rs.buf, sizeof(s->rs.buf), 0);
198 199 200 201
    if (size < 0)
        return;
    if (size == 0) {
        /* end of connection */
202 203
        net_socket_read_poll(s, false);
        net_socket_write_poll(s, false);
204 205
        return;
    }
206
    if (qemu_send_packet_async(&s->nc, s->rs.buf, size,
F
Fam Zheng 已提交
207 208 209
                               net_socket_send_completed) == 0) {
        net_socket_read_poll(s, false);
    }
210 211
}

212
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
213 214 215 216
{
    struct ip_mreq imr;
    int fd;
    int val, ret;
217 218 219 220 221 222
#ifdef __OpenBSD__
    unsigned char loop;
#else
    int loop;
#endif

223
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
S
Stefan Hajnoczi 已提交
224 225 226
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
                "does not contain a multicast address\n",
                inet_ntoa(mcastaddr->sin_addr),
227
                (int)ntohl(mcastaddr->sin_addr.s_addr));
S
Stefan Hajnoczi 已提交
228
        return -1;
229 230

    }
K
Kevin Wolf 已提交
231
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
232 233 234 235 236
    if (fd < 0) {
        perror("socket(PF_INET, SOCK_DGRAM)");
        return -1;
    }

237 238 239 240 241
    /* Allow multiple sockets to bind the same multicast ip and port by setting
     * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set
     * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR
     * only on posix systems.
     */
242
    val = 1;
243
    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
244
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
245 246
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        goto fail;
247 248 249 250 251 252 253 254 255 256
    }

    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
    if (ret < 0) {
        perror("bind");
        goto fail;
    }

    /* Add host to multicast group */
    imr.imr_multiaddr = mcastaddr->sin_addr;
257 258 259 260 261
    if (localaddr) {
        imr.imr_interface = *localaddr;
    } else {
        imr.imr_interface.s_addr = htonl(INADDR_ANY);
    }
262

263 264
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                          &imr, sizeof(struct ip_mreq));
265
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
266 267
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
        goto fail;
268 269 270
    }

    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
271
    loop = 1;
272 273
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
                          &loop, sizeof(loop));
274
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
275 276
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
        goto fail;
277 278
    }

279 280
    /* If a bind address is given, only send packets from that address */
    if (localaddr != NULL) {
281 282
        ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                              localaddr, sizeof(*localaddr));
283 284 285 286 287 288
        if (ret < 0) {
            perror("setsockopt(IP_MULTICAST_IF)");
            goto fail;
        }
    }

289
    qemu_set_nonblock(fd);
290 291 292 293 294 295 296
    return fd;
fail:
    if (fd >= 0)
        closesocket(fd);
    return -1;
}

297
static void net_socket_cleanup(NetClientState *nc)
298
{
299
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
300
    if (s->fd != -1) {
301 302
        net_socket_read_poll(s, false);
        net_socket_write_poll(s, false);
303 304 305 306 307 308 309 310
        close(s->fd);
        s->fd = -1;
    }
    if (s->listen_fd != -1) {
        qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
        closesocket(s->listen_fd);
        s->listen_fd = -1;
    }
311 312
}

313
static NetClientInfo net_dgram_socket_info = {
314
    .type = NET_CLIENT_DRIVER_SOCKET,
315 316 317 318 319
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive_dgram,
    .cleanup = net_socket_cleanup,
};

320
static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
321 322 323 324 325 326
                                                const char *model,
                                                const char *name,
                                                int fd, int is_connected)
{
    struct sockaddr_in saddr;
    int newfd;
327
    socklen_t saddr_len = sizeof(saddr);
328
    NetClientState *nc;
329 330 331 332 333 334 335 336
    NetSocketState *s;

    /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
     * Because this may be "shared" socket from a "master" process, datagrams would be recv()
     * by ONLY ONE process: we must "clone" this dgram socket --jjo
     */

    if (is_connected) {
S
Stefan Hajnoczi 已提交
337 338 339 340 341
        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
            /* must be bound */
            if (saddr.sin_addr.s_addr == 0) {
                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
                        "cannot setup multicast dst addr\n", fd);
342
                goto err;
S
Stefan Hajnoczi 已提交
343 344 345 346 347
            }
            /* clone dgram socket */
            newfd = net_socket_mcast_create(&saddr, NULL);
            if (newfd < 0) {
                /* error already reported by net_socket_mcast_create() */
348
                goto err;
S
Stefan Hajnoczi 已提交
349 350 351 352 353 354 355 356 357
            }
            /* clone newfd to fd, close newfd */
            dup2(newfd, fd);
            close(newfd);

        } else {
            fprintf(stderr,
                    "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
                    fd, strerror(errno));
358
            goto err;
S
Stefan Hajnoczi 已提交
359
        }
360 361
    }

362
    nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
363 364 365

    s = DO_UPCAST(NetSocketState, nc, nc);

366
    s->fd = fd;
367
    s->listen_fd = -1;
368
    s->send_fn = net_socket_send_dgram;
369
    net_socket_rs_init(&s->rs, net_socket_rs_finalize);
370
    net_socket_read_poll(s, true);
371 372

    /* mcast: save bound address as dst */
Z
Zhi Yong Wu 已提交
373 374
    if (is_connected) {
        s->dgram_dst = saddr;
375 376 377 378 379 380
        snprintf(nc->info_str, sizeof(nc->info_str),
                 "socket: fd=%d (cloned mcast=%s:%d)",
                 fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    } else {
        snprintf(nc->info_str, sizeof(nc->info_str),
                 "socket: fd=%d", fd);
Z
Zhi Yong Wu 已提交
381
    }
382 383

    return s;
384 385 386 387

err:
    closesocket(fd);
    return NULL;
388 389 390 391 392
}

static void net_socket_connect(void *opaque)
{
    NetSocketState *s = opaque;
393 394
    s->send_fn = net_socket_send;
    net_socket_read_poll(s, true);
395 396
}

397
static NetClientInfo net_socket_info = {
398
    .type = NET_CLIENT_DRIVER_SOCKET,
399 400 401 402 403
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive,
    .cleanup = net_socket_cleanup,
};

404
static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
405 406 407 408
                                                 const char *model,
                                                 const char *name,
                                                 int fd, int is_connected)
{
409
    NetClientState *nc;
410
    NetSocketState *s;
411

412
    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
413 414 415 416 417

    snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd);

    s = DO_UPCAST(NetSocketState, nc, nc);

418
    s->fd = fd;
419
    s->listen_fd = -1;
420
    net_socket_rs_init(&s->rs, net_socket_rs_finalize);
421

422 423 424
    /* Disable Nagle algorithm on TCP sockets to reduce latency */
    socket_set_nodelay(fd);

425 426 427 428 429 430 431 432
    if (is_connected) {
        net_socket_connect(s);
    } else {
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
    }
    return s;
}

433
static NetSocketState *net_socket_fd_init(NetClientState *peer,
434 435 436 437 438 439 440
                                          const char *model, const char *name,
                                          int fd, int is_connected)
{
    int so_type = -1, optlen=sizeof(so_type);

    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
        (socklen_t *)&optlen)< 0) {
S
Stefan Hajnoczi 已提交
441 442
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
                fd);
443
        closesocket(fd);
S
Stefan Hajnoczi 已提交
444
        return NULL;
445 446 447
    }
    switch(so_type) {
    case SOCK_DGRAM:
448
        return net_socket_fd_init_dgram(peer, model, name, fd, is_connected);
449
    case SOCK_STREAM:
450
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
451 452 453
    default:
        /* who knows ... this could be a eg. a pty, do warn and continue as stream */
        fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
454
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
455 456 457 458 459 460
    }
    return NULL;
}

static void net_socket_accept(void *opaque)
{
461
    NetSocketState *s = opaque;
462 463 464 465 466 467
    struct sockaddr_in saddr;
    socklen_t len;
    int fd;

    for(;;) {
        len = sizeof(saddr);
468
        fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
469 470 471
        if (fd < 0 && errno != EINTR) {
            return;
        } else if (fd >= 0) {
472
            qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
473 474 475
            break;
        }
    }
476 477 478 479 480 481 482

    s->fd = fd;
    s->nc.link_down = false;
    net_socket_connect(s);
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: connection from %s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
483 484
}

485
static int net_socket_listen_init(NetClientState *peer,
486 487 488 489
                                  const char *model,
                                  const char *name,
                                  const char *host_str)
{
490 491
    NetClientState *nc;
    NetSocketState *s;
492
    SocketAddress *saddr;
493 494
    int ret;
    Error *local_error = NULL;
495

496 497 498
    saddr = socket_parse(host_str, &local_error);
    if (saddr == NULL) {
        error_report_err(local_error);
499 500 501
        return -1;
    }

502
    ret = socket_listen(saddr, &local_error);
503
    if (ret < 0) {
504
        qapi_free_SocketAddress(saddr);
505
        error_report_err(local_error);
506 507
        return -1;
    }
508 509 510 511

    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
    s = DO_UPCAST(NetSocketState, nc, nc);
    s->fd = -1;
512
    s->listen_fd = ret;
513
    s->nc.link_down = true;
514
    net_socket_rs_init(&s->rs, net_socket_rs_finalize);
515 516

    qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
517
    qapi_free_SocketAddress(saddr);
518 519 520
    return 0;
}

521 522
typedef struct {
    NetClientState *peer;
523
    SocketAddress *saddr;
524 525 526 527 528 529
    char *model;
    char *name;
} socket_connect_data;

static void socket_connect_data_free(socket_connect_data *c)
{
530
    qapi_free_SocketAddress(c->saddr);
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
    g_free(c->model);
    g_free(c->name);
    g_free(c);
}

static void net_socket_connected(int fd, Error *err, void *opaque)
{
    socket_connect_data *c = opaque;
    NetSocketState *s;
    char *addr_str = NULL;
    Error *local_error = NULL;

    addr_str = socket_address_to_string(c->saddr, &local_error);
    if (addr_str == NULL) {
        error_report_err(local_error);
        closesocket(fd);
        goto end;
    }

    s = net_socket_fd_init(c->peer, c->model, c->name, fd, true);
    if (!s) {
        closesocket(fd);
        goto end;
    }

    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: connect to %s", addr_str);

end:
    g_free(addr_str);
    socket_connect_data_free(c);
}

564
static int net_socket_connect_init(NetClientState *peer,
565 566 567 568
                                   const char *model,
                                   const char *name,
                                   const char *host_str)
{
569 570 571 572 573 574 575 576 577 578 579
    socket_connect_data *c = g_new0(socket_connect_data, 1);
    int fd = -1;
    Error *local_error = NULL;

    c->peer = peer;
    c->model = g_strdup(model);
    c->name = g_strdup(name);
    c->saddr = socket_parse(host_str, &local_error);
    if (c->saddr == NULL) {
        goto err;
    }
580

581
    fd = socket_connect(c->saddr, net_socket_connected, c, &local_error);
582
    if (fd < 0) {
583
        goto err;
584
    }
585

586
    return 0;
587 588 589 590 591

err:
    error_report_err(local_error);
    socket_connect_data_free(c);
    return -1;
592 593
}

594
static int net_socket_mcast_init(NetClientState *peer,
595 596
                                 const char *model,
                                 const char *name,
597 598
                                 const char *host_str,
                                 const char *localaddr_str)
599 600 601 602
{
    NetSocketState *s;
    int fd;
    struct sockaddr_in saddr;
603
    struct in_addr localaddr, *param_localaddr;
604 605 606 607

    if (parse_host_port(&saddr, host_str) < 0)
        return -1;

608 609 610 611 612 613 614
    if (localaddr_str != NULL) {
        if (inet_aton(localaddr_str, &localaddr) == 0)
            return -1;
        param_localaddr = &localaddr;
    } else {
        param_localaddr = NULL;
    }
615

616
    fd = net_socket_mcast_create(&saddr, param_localaddr);
617
    if (fd < 0)
S
Stefan Hajnoczi 已提交
618
        return -1;
619

620
    s = net_socket_fd_init(peer, model, name, fd, 0);
621 622 623 624 625
    if (!s)
        return -1;

    s->dgram_dst = saddr;

626
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
627 628 629 630 631 632
             "socket: mcast=%s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;

}

633
static int net_socket_udp_init(NetClientState *peer,
634 635 636 637 638 639
                                 const char *model,
                                 const char *name,
                                 const char *rhost,
                                 const char *lhost)
{
    NetSocketState *s;
640
    int fd, ret;
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
    struct sockaddr_in laddr, raddr;

    if (parse_host_port(&laddr, lhost) < 0) {
        return -1;
    }

    if (parse_host_port(&raddr, rhost) < 0) {
        return -1;
    }

    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("socket(PF_INET, SOCK_DGRAM)");
        return -1;
    }
656 657

    ret = socket_set_fast_reuse(fd);
658 659 660 661 662 663 664 665 666 667
    if (ret < 0) {
        closesocket(fd);
        return -1;
    }
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    if (ret < 0) {
        perror("bind");
        closesocket(fd);
        return -1;
    }
668
    qemu_set_nonblock(fd);
669

670
    s = net_socket_fd_init(peer, model, name, fd, 0);
671 672 673 674 675 676 677 678 679 680 681 682
    if (!s) {
        return -1;
    }

    s->dgram_dst = raddr;

    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: udp=%s:%d",
             inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
    return 0;
}

683
int net_init_socket(const Netdev *netdev, const char *name,
684
                    NetClientState *peer, Error **errp)
685
{
686
    /* FIXME error_setg(errp, ...) on failure */
687
    Error *err = NULL;
688
    const NetdevSocketOptions *sock;
689

690 691
    assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
    sock = &netdev->u.socket;
692

693 694 695 696 697 698
    if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
        sock->has_udp != 1) {
        error_report("exactly one of fd=, listen=, connect=, mcast= or udp="
                     " is required");
        return -1;
    }
699

700 701 702 703
    if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
        error_report("localaddr= is only valid with mcast= or udp=");
        return -1;
    }
704

705 706
    if (sock->has_fd) {
        int fd;
707

708
        fd = monitor_fd_param(cur_mon, sock->fd, &err);
709
        if (fd == -1) {
710
            error_report_err(err);
711 712 713 714
            return -1;
        }
        qemu_set_nonblock(fd);
        if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
715 716
            return -1;
        }
717 718
        return 0;
    }
719

720
    if (sock->has_listen) {
721
        if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
722 723
            return -1;
        }
724 725
        return 0;
    }
726

727
    if (sock->has_connect) {
728
        if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
729
            -1) {
730 731
            return -1;
        }
732 733
        return 0;
    }
734

735 736 737
    if (sock->has_mcast) {
        /* if sock->localaddr is missing, it has been initialized to "all bits
         * zero" */
738
        if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
739
            sock->localaddr) == -1) {
740 741
            return -1;
        }
742 743
        return 0;
    }
744

745 746 747 748 749
    assert(sock->has_udp);
    if (!sock->has_localaddr) {
        error_report("localaddr= is mandatory with udp=");
        return -1;
    }
750
    if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
751
        -1) {
752 753 754 755
        return -1;
    }
    return 0;
}