socket.c 18.3 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 26 27 28
/*
 * 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 "net/socket.h"

#include "config-host.h"

#include "net.h"
29
#include "monitor.h"
30 31
#include "qemu-char.h"
#include "qemu-common.h"
32
#include "qemu-error.h"
33 34 35 36
#include "qemu-option.h"
#include "qemu_socket.h"

typedef struct NetSocketState {
37
    VLANClientState nc;
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
    int fd;
    int state; /* 0 = getting length, 1 = getting data */
    unsigned int index;
    unsigned int packet_len;
    uint8_t buf[4096];
    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
} NetSocketState;

typedef struct NetSocketListenState {
    VLANState *vlan;
    char *model;
    char *name;
    int fd;
} NetSocketListenState;

/* XXX: we consider we can send the whole packet without blocking */
54
static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
55
{
56
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
57 58 59 60 61 62 63
    uint32_t len;
    len = htonl(size);

    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
    return send_all(s->fd, buf, size);
}

64
static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
65
{
66
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
67 68 69 70 71 72 73 74 75 76 77 78 79

    return sendto(s->fd, (const void *)buf, size, 0,
                  (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
}

static void net_socket_send(void *opaque)
{
    NetSocketState *s = opaque;
    int size, err;
    unsigned l;
    uint8_t buf1[4096];
    const uint8_t *buf;

B
Blue Swirl 已提交
80
    size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    if (size < 0) {
        err = socket_error();
        if (err != EWOULDBLOCK)
            goto eoc;
    } else if (size == 0) {
        /* end of connection */
    eoc:
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
        closesocket(s->fd);
        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) {
128
                qemu_send_packet(&s->nc, s->buf, s->packet_len);
129 130 131 132 133 134 135 136 137 138 139 140 141
                s->index = 0;
                s->state = 0;
            }
            break;
        }
    }
}

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

B
Blue Swirl 已提交
142
    size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
143 144 145 146 147 148 149
    if (size < 0)
        return;
    if (size == 0) {
        /* end of connection */
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
        return;
    }
150
    qemu_send_packet(&s->nc, s->buf, size);
151 152
}

153
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
154 155 156 157
{
    struct ip_mreq imr;
    int fd;
    int val, ret;
158 159 160 161 162 163
#ifdef __OpenBSD__
    unsigned char loop;
#else
    int loop;
#endif

164
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
S
Stefan Hajnoczi 已提交
165 166 167
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
                "does not contain a multicast address\n",
                inet_ntoa(mcastaddr->sin_addr),
168
                (int)ntohl(mcastaddr->sin_addr.s_addr));
S
Stefan Hajnoczi 已提交
169
        return -1;
170 171

    }
K
Kevin Wolf 已提交
172
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
173 174 175 176 177 178 179 180 181
    if (fd < 0) {
        perror("socket(PF_INET, SOCK_DGRAM)");
        return -1;
    }

    val = 1;
    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                   (const char *)&val, sizeof(val));
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
182 183
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        goto fail;
184 185 186 187 188 189 190 191 192 193
    }

    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;
194 195 196 197 198
    if (localaddr) {
        imr.imr_interface = *localaddr;
    } else {
        imr.imr_interface.s_addr = htonl(INADDR_ANY);
    }
199 200 201 202

    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                     (const char *)&imr, sizeof(struct ip_mreq));
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
203 204
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
        goto fail;
205 206 207
    }

    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
208
    loop = 1;
209
    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
210
                   (const char *)&loop, sizeof(loop));
211
    if (ret < 0) {
S
Stefan Hajnoczi 已提交
212 213
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
        goto fail;
214 215
    }

216 217
    /* If a bind address is given, only send packets from that address */
    if (localaddr != NULL) {
B
Blue Swirl 已提交
218 219
        ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                         (const char *)localaddr, sizeof(*localaddr));
220 221 222 223 224 225
        if (ret < 0) {
            perror("setsockopt(IP_MULTICAST_IF)");
            goto fail;
        }
    }

226 227 228 229 230 231 232 233
    socket_set_nonblock(fd);
    return fd;
fail:
    if (fd >= 0)
        closesocket(fd);
    return -1;
}

234
static void net_socket_cleanup(VLANClientState *nc)
235
{
236
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
237 238 239 240
    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
    close(s->fd);
}

241
static NetClientInfo net_dgram_socket_info = {
242
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
243 244 245 246 247
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive_dgram,
    .cleanup = net_socket_cleanup,
};

248 249 250 251 252 253 254 255
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
                                                const char *model,
                                                const char *name,
                                                int fd, int is_connected)
{
    struct sockaddr_in saddr;
    int newfd;
    socklen_t saddr_len;
256
    VLANClientState *nc;
257 258 259 260 261 262 263 264
    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 已提交
265 266 267 268 269
        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);
270
                goto err;
S
Stefan Hajnoczi 已提交
271 272 273 274 275
            }
            /* clone dgram socket */
            newfd = net_socket_mcast_create(&saddr, NULL);
            if (newfd < 0) {
                /* error already reported by net_socket_mcast_create() */
276
                goto err;
S
Stefan Hajnoczi 已提交
277 278 279 280 281 282 283 284 285
            }
            /* 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));
286
            goto err;
S
Stefan Hajnoczi 已提交
287
        }
288 289
    }

290 291 292
    nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name);

    snprintf(nc->info_str, sizeof(nc->info_str),
S
Stefan Hajnoczi 已提交
293 294 295
            "socket: fd=%d (%s mcast=%s:%d)",
            fd, is_connected ? "cloned" : "",
            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
296 297 298

    s = DO_UPCAST(NetSocketState, nc, nc);

299 300 301 302 303 304 305 306
    s->fd = fd;

    qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);

    /* mcast: save bound address as dst */
    if (is_connected) s->dgram_dst=saddr;

    return s;
307 308 309 310

err:
    closesocket(fd);
    return NULL;
311 312 313 314 315 316 317 318
}

static void net_socket_connect(void *opaque)
{
    NetSocketState *s = opaque;
    qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
}

319
static NetClientInfo net_socket_info = {
320
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
321 322 323 324 325
    .size = sizeof(NetSocketState),
    .receive = net_socket_receive,
    .cleanup = net_socket_cleanup,
};

326 327 328 329 330
static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
                                                 const char *model,
                                                 const char *name,
                                                 int fd, int is_connected)
{
331
    VLANClientState *nc;
332
    NetSocketState *s;
333 334 335 336 337 338 339

    nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name);

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

    s = DO_UPCAST(NetSocketState, nc, nc);

340
    s->fd = fd;
341

342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
    if (is_connected) {
        net_socket_connect(s);
    } else {
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
    }
    return s;
}

static NetSocketState *net_socket_fd_init(VLANState *vlan,
                                          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 已提交
358 359
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
                fd);
360
        closesocket(fd);
S
Stefan Hajnoczi 已提交
361
        return NULL;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    }
    switch(so_type) {
    case SOCK_DGRAM:
        return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected);
    case SOCK_STREAM:
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
    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);
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
    }
    return NULL;
}

static void net_socket_accept(void *opaque)
{
    NetSocketListenState *s = opaque;
    NetSocketState *s1;
    struct sockaddr_in saddr;
    socklen_t len;
    int fd;

    for(;;) {
        len = sizeof(saddr);
K
Kevin Wolf 已提交
386
        fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len);
387 388 389 390 391 392 393
        if (fd < 0 && errno != EINTR) {
            return;
        } else if (fd >= 0) {
            break;
        }
    }
    s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
394
    if (s1) {
395
        snprintf(s1->nc.info_str, sizeof(s1->nc.info_str),
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
                 "socket: connection from %s:%d",
                 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    }
}

static int net_socket_listen_init(VLANState *vlan,
                                  const char *model,
                                  const char *name,
                                  const char *host_str)
{
    NetSocketListenState *s;
    int fd, val, ret;
    struct sockaddr_in saddr;

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

413
    s = g_malloc0(sizeof(NetSocketListenState));
414

K
Kevin Wolf 已提交
415
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
416 417
    if (fd < 0) {
        perror("socket");
Z
Zhi Hui Li 已提交
418
        g_free(s);
419 420 421 422 423 424 425 426 427 428 429
        return -1;
    }
    socket_set_nonblock(fd);

    /* allow fast reuse */
    val = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));

    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret < 0) {
        perror("bind");
Z
Zhi Hui Li 已提交
430
        g_free(s);
431
        closesocket(fd);
432 433 434 435 436
        return -1;
    }
    ret = listen(fd, 0);
    if (ret < 0) {
        perror("listen");
Z
Zhi Hui Li 已提交
437
        g_free(s);
438
        closesocket(fd);
439 440 441
        return -1;
    }
    s->vlan = vlan;
442 443
    s->model = g_strdup(model);
    s->name = name ? g_strdup(name) : NULL;
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    s->fd = fd;
    qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
    return 0;
}

static int net_socket_connect_init(VLANState *vlan,
                                   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 已提交
461
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
    if (fd < 0) {
        perror("socket");
        return -1;
    }
    socket_set_nonblock(fd);

    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
477
            } else if (err == WSAEALREADY || err == WSAEINVAL) {
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
                break;
#endif
            } else {
                perror("connect");
                closesocket(fd);
                return -1;
            }
        } else {
            connected = 1;
            break;
        }
    }
    s = net_socket_fd_init(vlan, model, name, fd, connected);
    if (!s)
        return -1;
493
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
494 495 496 497 498 499 500 501
             "socket: connect to %s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;
}

static int net_socket_mcast_init(VLANState *vlan,
                                 const char *model,
                                 const char *name,
502 503
                                 const char *host_str,
                                 const char *localaddr_str)
504 505 506 507
{
    NetSocketState *s;
    int fd;
    struct sockaddr_in saddr;
508
    struct in_addr localaddr, *param_localaddr;
509 510 511 512

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

513 514 515 516 517 518 519
    if (localaddr_str != NULL) {
        if (inet_aton(localaddr_str, &localaddr) == 0)
            return -1;
        param_localaddr = &localaddr;
    } else {
        param_localaddr = NULL;
    }
520

521
    fd = net_socket_mcast_create(&saddr, param_localaddr);
522
    if (fd < 0)
S
Stefan Hajnoczi 已提交
523
        return -1;
524 525 526 527 528 529 530

    s = net_socket_fd_init(vlan, model, name, fd, 0);
    if (!s)
        return -1;

    s->dgram_dst = saddr;

531
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
532 533 534 535 536 537
             "socket: mcast=%s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;

}

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 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
static int net_socket_udp_init(VLANState *vlan,
                                 const char *model,
                                 const char *name,
                                 const char *rhost,
                                 const char *lhost)
{
    NetSocketState *s;
    int fd, val, ret;
    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;
    }
    val = 1;
    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                   (const char *)&val, sizeof(val));
    if (ret < 0) {
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        closesocket(fd);
        return -1;
    }
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    if (ret < 0) {
        perror("bind");
        closesocket(fd);
        return -1;
    }

    s = net_socket_fd_init(vlan, model, name, fd, 0);
    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;
}

589 590
int net_init_socket(const NetClientOptions *opts, const char *name,
                    VLANState *vlan)
591
{
592
    const NetdevSocketOptions *sock;
593

594 595
    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
    sock = opts->socket;
596

597 598 599 600 601 602
    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;
    }
603

604 605 606 607
    if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
        error_report("localaddr= is only valid with mcast= or udp=");
        return -1;
    }
608

609 610
    if (sock->has_fd) {
        int fd;
611

612 613
        fd = net_handle_fd_param(cur_mon, sock->fd);
        if (fd == -1 || !net_socket_fd_init(vlan, "socket", name, fd, 1)) {
614 615
            return -1;
        }
616 617
        return 0;
    }
618

619 620
    if (sock->has_listen) {
        if (net_socket_listen_init(vlan, "socket", name, sock->listen) == -1) {
621 622
            return -1;
        }
623 624
        return 0;
    }
625

626 627 628
    if (sock->has_connect) {
        if (net_socket_connect_init(vlan, "socket", name, sock->connect) ==
            -1) {
629 630
            return -1;
        }
631 632
        return 0;
    }
633

634 635 636 637 638
    if (sock->has_mcast) {
        /* if sock->localaddr is missing, it has been initialized to "all bits
         * zero" */
        if (net_socket_mcast_init(vlan, "socket", name, sock->mcast,
            sock->localaddr) == -1) {
639 640
            return -1;
        }
641 642
        return 0;
    }
643

644 645 646 647 648 649 650
    assert(sock->has_udp);
    if (!sock->has_localaddr) {
        error_report("localaddr= is mandatory with udp=");
        return -1;
    }
    if (net_socket_udp_init(vlan, "udp", name, sock->udp, sock->localaddr) ==
        -1) {
651 652 653 654
        return -1;
    }
    return 0;
}