socket.c 21.7 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 24 25
/*
 * 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.
 */
#include "config-host.h"

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

typedef struct NetSocketState {
37
    NetClientState nc;
38
    int listen_fd;
39 40 41 42
    int fd;
    int state; /* 0 = getting length, 1 = getting data */
    unsigned int index;
    unsigned int packet_len;
43
    unsigned int send_index;      /* number of bytes sent (only SOCK_STREAM) */
44
    uint8_t buf[NET_BUFSIZE];
45
    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
46 47 48
    IOHandler *send_fn;           /* differs between SOCK_STREAM/SOCK_DGRAM */
    bool read_poll;               /* waiting to receive data? */
    bool write_poll;              /* waiting to transmit data? */
49 50
} NetSocketState;

51
static void net_socket_accept(void *opaque);
52 53 54 55
static void net_socket_writable(void *opaque);

static void net_socket_update_fd_handler(NetSocketState *s)
{
F
Fam Zheng 已提交
56
    qemu_set_fd_handler2(s->fd, NULL,
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
                         s->read_poll  ? s->send_fn : NULL,
                         s->write_poll ? net_socket_writable : NULL,
                         s);
}

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);
}
82

83
static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size)
84
{
85
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
86 87 88 89 90 91 92 93 94 95 96 97
    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;
98

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    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;
116 117
}

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

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

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

F
Fam Zheng 已提交
136 137 138 139 140 141 142 143 144
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);
    }
}

145 146 147 148 149
static void net_socket_send(void *opaque)
{
    NetSocketState *s = opaque;
    int size, err;
    unsigned l;
150
    uint8_t buf1[NET_BUFSIZE];
151 152
    const uint8_t *buf;

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

        s->fd = -1;
        s->state = 0;
        s->index = 0;
        s->packet_len = 0;
        s->nc.link_down = true;
        memset(s->buf, 0, sizeof(s->buf));
        memset(s->nc.info_str, 0, sizeof(s->nc.info_str));

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
        return;
    }
    buf = buf1;
    while (size > 0) {
        /* reassemble a packet from the network */
        switch(s->state) {
        case 0:
            l = 4 - s->index;
            if (l > size)
                l = size;
            memcpy(s->buf + s->index, buf, l);
            buf += l;
            size -= l;
            s->index += l;
            if (s->index == 4) {
                /* got length */
                s->packet_len = ntohl(*(uint32_t *)s->buf);
                s->index = 0;
                s->state = 1;
            }
            break;
        case 1:
            l = s->packet_len - s->index;
            if (l > size)
                l = size;
            if (s->index + l <= sizeof(s->buf)) {
                memcpy(s->buf + s->index, buf, l);
            } else {
                fprintf(stderr, "serious error: oversized packet received,"
                    "connection terminated.\n");
                s->state = 0;
                goto eoc;
            }

            s->index += l;
            buf += l;
            size -= l;
            if (s->index >= s->packet_len) {
                s->index = 0;
                s->state = 0;
F
Fam Zheng 已提交
216 217 218 219 220
                if (qemu_send_packet_async(&s->nc, s->buf, size,
                                           net_socket_send_completed) == 0) {
                    net_socket_read_poll(s, false);
                    break;
                }
221 222 223 224 225 226 227 228 229 230 231
            }
            break;
        }
    }
}

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

B
Blue Swirl 已提交
232
    size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
233 234 235 236
    if (size < 0)
        return;
    if (size == 0) {
        /* end of connection */
237 238
        net_socket_read_poll(s, false);
        net_socket_write_poll(s, false);
239 240
        return;
    }
F
Fam Zheng 已提交
241 242 243 244
    if (qemu_send_packet_async(&s->nc, s->buf, size,
                               net_socket_send_completed) == 0) {
        net_socket_read_poll(s, false);
    }
245 246
}

247
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
248 249 250 251
{
    struct ip_mreq imr;
    int fd;
    int val, ret;
252 253 254 255 256 257
#ifdef __OpenBSD__
    unsigned char loop;
#else
    int loop;
#endif

258
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
S
Stefan Hajnoczi 已提交
259 260 261
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
                "does not contain a multicast address\n",
                inet_ntoa(mcastaddr->sin_addr),
262
                (int)ntohl(mcastaddr->sin_addr.s_addr));
S
Stefan Hajnoczi 已提交
263
        return -1;
264 265

    }
K
Kevin Wolf 已提交
266
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
267 268 269 270 271
    if (fd < 0) {
        perror("socket(PF_INET, SOCK_DGRAM)");
        return -1;
    }

272 273 274 275 276
    /* 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.
     */
277
    val = 1;
278
    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
279
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
280 281
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        goto fail;
282 283 284 285 286 287 288 289 290 291
    }

    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;
292 293 294 295 296
    if (localaddr) {
        imr.imr_interface = *localaddr;
    } else {
        imr.imr_interface.s_addr = htonl(INADDR_ANY);
    }
297

298 299
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                          &imr, sizeof(struct ip_mreq));
300
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
301 302
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
        goto fail;
303 304 305
    }

    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
306
    loop = 1;
307 308
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
                          &loop, sizeof(loop));
309
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
310 311
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
        goto fail;
312 313
    }

314 315
    /* If a bind address is given, only send packets from that address */
    if (localaddr != NULL) {
316 317
        ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                              localaddr, sizeof(*localaddr));
318 319 320 321 322 323
        if (ret < 0) {
            perror("setsockopt(IP_MULTICAST_IF)");
            goto fail;
        }
    }

324
    qemu_set_nonblock(fd);
325 326 327 328 329 330 331
    return fd;
fail:
    if (fd >= 0)
        closesocket(fd);
    return -1;
}

332
static void net_socket_cleanup(NetClientState *nc)
333
{
334
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
335
    if (s->fd != -1) {
336 337
        net_socket_read_poll(s, false);
        net_socket_write_poll(s, false);
338 339 340 341 342 343 344 345
        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;
    }
346 347
}

348
static NetClientInfo net_dgram_socket_info = {
349
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
350 351 352 353 354
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive_dgram,
    .cleanup = net_socket_cleanup,
};

355
static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
356 357 358 359 360 361
                                                const char *model,
                                                const char *name,
                                                int fd, int is_connected)
{
    struct sockaddr_in saddr;
    int newfd;
362
    socklen_t saddr_len = sizeof(saddr);
363
    NetClientState *nc;
364 365 366 367 368 369 370 371
    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 已提交
372 373 374 375 376
        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);
377
                goto err;
S
Stefan Hajnoczi 已提交
378 379 380 381 382
            }
            /* clone dgram socket */
            newfd = net_socket_mcast_create(&saddr, NULL);
            if (newfd < 0) {
                /* error already reported by net_socket_mcast_create() */
383
                goto err;
S
Stefan Hajnoczi 已提交
384 385 386 387 388 389 390 391 392
            }
            /* 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));
393
            goto err;
S
Stefan Hajnoczi 已提交
394
        }
395 396
    }

397
    nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
398 399 400

    s = DO_UPCAST(NetSocketState, nc, nc);

401
    s->fd = fd;
402
    s->listen_fd = -1;
403 404
    s->send_fn = net_socket_send_dgram;
    net_socket_read_poll(s, true);
405 406

    /* mcast: save bound address as dst */
Z
Zhi Yong Wu 已提交
407 408
    if (is_connected) {
        s->dgram_dst = saddr;
409 410 411 412 413 414
        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 已提交
415
    }
416 417

    return s;
418 419 420 421

err:
    closesocket(fd);
    return NULL;
422 423 424 425 426
}

static void net_socket_connect(void *opaque)
{
    NetSocketState *s = opaque;
427 428
    s->send_fn = net_socket_send;
    net_socket_read_poll(s, true);
429 430
}

431
static NetClientInfo net_socket_info = {
432
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
433 434 435 436 437
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive,
    .cleanup = net_socket_cleanup,
};

438
static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
439 440 441 442
                                                 const char *model,
                                                 const char *name,
                                                 int fd, int is_connected)
{
443
    NetClientState *nc;
444
    NetSocketState *s;
445

446
    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
447 448 449 450 451

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

    s = DO_UPCAST(NetSocketState, nc, nc);

452
    s->fd = fd;
453
    s->listen_fd = -1;
454

455 456 457
    /* Disable Nagle algorithm on TCP sockets to reduce latency */
    socket_set_nodelay(fd);

458 459 460 461 462 463 464 465
    if (is_connected) {
        net_socket_connect(s);
    } else {
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
    }
    return s;
}

466
static NetSocketState *net_socket_fd_init(NetClientState *peer,
467 468 469 470 471 472 473
                                          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 已提交
474 475
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
                fd);
476
        closesocket(fd);
S
Stefan Hajnoczi 已提交
477
        return NULL;
478 479 480
    }
    switch(so_type) {
    case SOCK_DGRAM:
481
        return net_socket_fd_init_dgram(peer, model, name, fd, is_connected);
482
    case SOCK_STREAM:
483
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
484 485 486
    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);
487
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
488 489 490 491 492 493
    }
    return NULL;
}

static void net_socket_accept(void *opaque)
{
494
    NetSocketState *s = opaque;
495 496 497 498 499 500
    struct sockaddr_in saddr;
    socklen_t len;
    int fd;

    for(;;) {
        len = sizeof(saddr);
501
        fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
502 503 504
        if (fd < 0 && errno != EINTR) {
            return;
        } else if (fd >= 0) {
505
            qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
506 507 508
            break;
        }
    }
509 510 511 512 513 514 515

    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));
516 517
}

518
static int net_socket_listen_init(NetClientState *peer,
519 520 521 522
                                  const char *model,
                                  const char *name,
                                  const char *host_str)
{
523 524
    NetClientState *nc;
    NetSocketState *s;
525
    struct sockaddr_in saddr;
526
    int fd, ret;
527 528 529 530

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

K
Kevin Wolf 已提交
531
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
532 533 534 535
    if (fd < 0) {
        perror("socket");
        return -1;
    }
536
    qemu_set_nonblock(fd);
537

538
    socket_set_fast_reuse(fd);
539 540 541 542

    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret < 0) {
        perror("bind");
543
        closesocket(fd);
544 545 546 547 548
        return -1;
    }
    ret = listen(fd, 0);
    if (ret < 0) {
        perror("listen");
549
        closesocket(fd);
550 551
        return -1;
    }
552 553 554 555 556 557 558 559

    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
    s = DO_UPCAST(NetSocketState, nc, nc);
    s->fd = -1;
    s->listen_fd = fd;
    s->nc.link_down = true;

    qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
560 561 562
    return 0;
}

563
static int net_socket_connect_init(NetClientState *peer,
564 565 566 567 568 569 570 571 572 573 574
                                   const char *model,
                                   const char *name,
                                   const char *host_str)
{
    NetSocketState *s;
    int fd, connected, ret, err;
    struct sockaddr_in saddr;

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

K
Kevin Wolf 已提交
575
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
576 577 578 579
    if (fd < 0) {
        perror("socket");
        return -1;
    }
580
    qemu_set_nonblock(fd);
581 582 583 584 585 586 587 588 589 590

    connected = 0;
    for(;;) {
        ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
        if (ret < 0) {
            err = socket_error();
            if (err == EINTR || err == EWOULDBLOCK) {
            } else if (err == EINPROGRESS) {
                break;
#ifdef _WIN32
591
            } else if (err == WSAEALREADY || err == WSAEINVAL) {
592 593 594 595 596 597 598 599 600 601 602 603
                break;
#endif
            } else {
                perror("connect");
                closesocket(fd);
                return -1;
            }
        } else {
            connected = 1;
            break;
        }
    }
604
    s = net_socket_fd_init(peer, model, name, fd, connected);
605 606
    if (!s)
        return -1;
607
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
608 609 610 611 612
             "socket: connect to %s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;
}

613
static int net_socket_mcast_init(NetClientState *peer,
614 615
                                 const char *model,
                                 const char *name,
616 617
                                 const char *host_str,
                                 const char *localaddr_str)
618 619 620 621
{
    NetSocketState *s;
    int fd;
    struct sockaddr_in saddr;
622
    struct in_addr localaddr, *param_localaddr;
623 624 625 626

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

627 628 629 630 631 632 633
    if (localaddr_str != NULL) {
        if (inet_aton(localaddr_str, &localaddr) == 0)
            return -1;
        param_localaddr = &localaddr;
    } else {
        param_localaddr = NULL;
    }
634

635
    fd = net_socket_mcast_create(&saddr, param_localaddr);
636
    if (fd < 0)
S
Stefan Hajnoczi 已提交
637
        return -1;
638

639
    s = net_socket_fd_init(peer, model, name, fd, 0);
640 641 642 643 644
    if (!s)
        return -1;

    s->dgram_dst = saddr;

645
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
646 647 648 649 650 651
             "socket: mcast=%s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;

}

652
static int net_socket_udp_init(NetClientState *peer,
653 654 655 656 657 658
                                 const char *model,
                                 const char *name,
                                 const char *rhost,
                                 const char *lhost)
{
    NetSocketState *s;
659
    int fd, ret;
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
    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;
    }
675 676

    ret = socket_set_fast_reuse(fd);
677 678 679 680 681 682 683 684 685 686
    if (ret < 0) {
        closesocket(fd);
        return -1;
    }
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    if (ret < 0) {
        perror("bind");
        closesocket(fd);
        return -1;
    }
687
    qemu_set_nonblock(fd);
688

689
    s = net_socket_fd_init(peer, model, name, fd, 0);
690 691 692 693 694 695 696 697 698 699 700 701
    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;
}

702
int net_init_socket(const NetClientOptions *opts, const char *name,
703
                    NetClientState *peer, Error **errp)
704
{
705
    /* FIXME error_setg(errp, ...) on failure */
706
    Error *err = NULL;
707
    const NetdevSocketOptions *sock;
708

709 710
    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
    sock = opts->socket;
711

712 713 714 715 716 717
    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;
    }
718

719 720 721 722
    if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
        error_report("localaddr= is only valid with mcast= or udp=");
        return -1;
    }
723

724 725
    if (sock->has_fd) {
        int fd;
726

727
        fd = monitor_fd_param(cur_mon, sock->fd, &err);
728
        if (fd == -1) {
729
            error_report_err(err);
730 731 732 733
            return -1;
        }
        qemu_set_nonblock(fd);
        if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
734 735
            return -1;
        }
736 737
        return 0;
    }
738

739
    if (sock->has_listen) {
740
        if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
741 742
            return -1;
        }
743 744
        return 0;
    }
745

746
    if (sock->has_connect) {
747
        if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
748
            -1) {
749 750
            return -1;
        }
751 752
        return 0;
    }
753

754 755 756
    if (sock->has_mcast) {
        /* if sock->localaddr is missing, it has been initialized to "all bits
         * zero" */
757
        if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
758
            sock->localaddr) == -1) {
759 760
            return -1;
        }
761 762
        return 0;
    }
763

764 765 766 767 768
    assert(sock->has_udp);
    if (!sock->has_localaddr) {
        error_report("localaddr= is mandatory with udp=");
        return -1;
    }
769
    if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
770
        -1) {
771 772 773 774
        return -1;
    }
    return 0;
}