Statistics
| Branch: | Revision:

root / net / socket.c @ 5d12aa63

History | View | Annotate | Download (21.2 kB)

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

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

    
36
typedef struct NetSocketState {
37
    NetClientState nc;
38
    int listen_fd;
39
    int fd;
40
    int state; /* 0 = getting length, 1 = getting data */
41
    unsigned int index;
42
    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
    IOHandler *send_fn;           /* differs between SOCK_STREAM/SOCK_DGRAM */
47
    bool read_poll;               /* waiting to receive data? */
48
    bool write_poll;              /* waiting to transmit data? */
49
} NetSocketState;
50

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

    
54
/* Only read packets from socket when peer can receive them */
55
static int net_socket_can_send(void *opaque)
56
{
57
    NetSocketState *s = opaque;
58

    
59
    return qemu_can_send_packet(&s->nc);
60
}
61

    
62
static void net_socket_update_fd_handler(NetSocketState *s)
63
{
64
    qemu_set_fd_handler2(s->fd,
65
                         s->read_poll  ? net_socket_can_send : NULL,
66
                         s->read_poll  ? s->send_fn : NULL,
67
                         s->write_poll ? net_socket_writable : NULL,
68
                         s);
69
}
70

    
71
static void net_socket_read_poll(NetSocketState *s, bool enable)
72
{
73
    s->read_poll = enable;
74
    net_socket_update_fd_handler(s);
75
}
76

    
77
static void net_socket_write_poll(NetSocketState *s, bool enable)
78
{
79
    s->write_poll = enable;
80
    net_socket_update_fd_handler(s);
81
}
82

    
83
static void net_socket_writable(void *opaque)
84
{
85
    NetSocketState *s = opaque;
86

    
87
    net_socket_write_poll(s, false);
88

    
89
    qemu_flush_queued_packets(&s->nc);
90
}
91

    
92
static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size)
93
{
94
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
95
    uint32_t len = htonl(size);
96
    struct iovec iov[] = {
97
        {
98
            .iov_base = &len,
99
            .iov_len  = sizeof(len),
100
        }, {
101
            .iov_base = (void *)buf,
102
            .iov_len  = size,
103
        },
104
    };
105
    size_t remaining;
106
    ssize_t ret;
107

    
108
    remaining = iov_size(iov, 2) - s->send_index;
109
    ret = iov_send(s->fd, iov, 2, s->send_index, remaining);
110

    
111
    if (ret == -1 && errno == EAGAIN) {
112
        ret = 0; /* handled further down */
113
    }
114
    if (ret == -1) {
115
        s->send_index = 0;
116
        return -errno;
117
    }
118
    if (ret < (ssize_t)remaining) {
119
        s->send_index += ret;
120
        net_socket_write_poll(s, true);
121
        return 0;
122
    }
123
    s->send_index = 0;
124
    return size;
125
}
126

    
127
static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size)
128
{
129
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
130
    ssize_t ret;
131

    
132
    do {
133
        ret = qemu_sendto(s->fd, buf, size, 0,
134
                          (struct sockaddr *)&s->dgram_dst,
135
                          sizeof(s->dgram_dst));
136
    } while (ret == -1 && errno == EINTR);
137

    
138
    if (ret == -1 && errno == EAGAIN) {
139
        net_socket_write_poll(s, true);
140
        return 0;
141
    }
142
    return ret;
143
}
144

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

    
153
    size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
154
    if (size < 0) {
155
        err = socket_error();
156
        if (err != EWOULDBLOCK)
157
            goto eoc;
158
    } else if (size == 0) {
159
        /* end of connection */
160
    eoc:
161
        net_socket_read_poll(s, false);
162
        net_socket_write_poll(s, false);
163
        if (s->listen_fd != -1) {
164
            qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
165
        }
166
        closesocket(s->fd);
167

    
168
        s->fd = -1;
169
        s->state = 0;
170
        s->index = 0;
171
        s->packet_len = 0;
172
        s->nc.link_down = true;
173
        memset(s->buf, 0, sizeof(s->buf));
174
        memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
175

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

    
210
            s->index += l;
211
            buf += l;
212
            size -= l;
213
            if (s->index >= s->packet_len) {
214
                qemu_send_packet(&s->nc, s->buf, s->packet_len);
215
                s->index = 0;
216
                s->state = 0;
217
            }
218
            break;
219
        }
220
    }
221
}
222

    
223
static void net_socket_send_dgram(void *opaque)
224
{
225
    NetSocketState *s = opaque;
226
    int size;
227

    
228
    size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
229
    if (size < 0)
230
        return;
231
    if (size == 0) {
232
        /* end of connection */
233
        net_socket_read_poll(s, false);
234
        net_socket_write_poll(s, false);
235
        return;
236
    }
237
    qemu_send_packet(&s->nc, s->buf, size);
238
}
239

    
240
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
241
{
242
    struct ip_mreq imr;
243
    int fd;
244
    int val, ret;
245
#ifdef __OpenBSD__
246
    unsigned char loop;
247
#else
248
    int loop;
249
#endif
250

    
251
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
252
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) "
253
                "does not contain a multicast address\n",
254
                inet_ntoa(mcastaddr->sin_addr),
255
                (int)ntohl(mcastaddr->sin_addr.s_addr));
256
        return -1;
257

    
258
    }
259
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
260
    if (fd < 0) {
261
        perror("socket(PF_INET, SOCK_DGRAM)");
262
        return -1;
263
    }
264

    
265
    /* Allow multiple sockets to bind the same multicast ip and port by setting
266
     * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set
267
     * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR
268
     * only on posix systems.
269
     */
270
    val = 1;
271
    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
272
    if (ret < 0) {
273
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
274
        goto fail;
275
    }
276

    
277
    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
278
    if (ret < 0) {
279
        perror("bind");
280
        goto fail;
281
    }
282

    
283
    /* Add host to multicast group */
284
    imr.imr_multiaddr = mcastaddr->sin_addr;
285
    if (localaddr) {
286
        imr.imr_interface = *localaddr;
287
    } else {
288
        imr.imr_interface.s_addr = htonl(INADDR_ANY);
289
    }
290

    
291
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
292
                          &imr, sizeof(struct ip_mreq));
293
    if (ret < 0) {
294
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
295
        goto fail;
296
    }
297

    
298
    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
299
    loop = 1;
300
    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
301
                          &loop, sizeof(loop));
302
    if (ret < 0) {
303
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
304
        goto fail;
305
    }
306

    
307
    /* If a bind address is given, only send packets from that address */
308
    if (localaddr != NULL) {
309
        ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
310
                              localaddr, sizeof(*localaddr));
311
        if (ret < 0) {
312
            perror("setsockopt(IP_MULTICAST_IF)");
313
            goto fail;
314
        }
315
    }
316

    
317
    qemu_set_nonblock(fd);
318
    return fd;
319
fail:
320
    if (fd >= 0)
321
        closesocket(fd);
322
    return -1;
323
}
324

    
325
static void net_socket_cleanup(NetClientState *nc)
326
{
327
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
328
    if (s->fd != -1) {
329
        net_socket_read_poll(s, false);
330
        net_socket_write_poll(s, false);
331
        close(s->fd);
332
        s->fd = -1;
333
    }
334
    if (s->listen_fd != -1) {
335
        qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
336
        closesocket(s->listen_fd);
337
        s->listen_fd = -1;
338
    }
339
}
340

    
341
static NetClientInfo net_dgram_socket_info = {
342
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
343
    .size = sizeof(NetSocketState),
344
    .receive = net_socket_receive_dgram,
345
    .cleanup = net_socket_cleanup,
346
};
347

    
348
static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
349
                                                const char *model,
350
                                                const char *name,
351
                                                int fd, int is_connected)
352
{
353
    struct sockaddr_in saddr;
354
    int newfd;
355
    socklen_t saddr_len;
356
    NetClientState *nc;
357
    NetSocketState *s;
358

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

    
364
    if (is_connected) {
365
        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
366
            /* must be bound */
367
            if (saddr.sin_addr.s_addr == 0) {
368
                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, "
369
                        "cannot setup multicast dst addr\n", fd);
370
                goto err;
371
            }
372
            /* clone dgram socket */
373
            newfd = net_socket_mcast_create(&saddr, NULL);
374
            if (newfd < 0) {
375
                /* error already reported by net_socket_mcast_create() */
376
                goto err;
377
            }
378
            /* clone newfd to fd, close newfd */
379
            dup2(newfd, fd);
380
            close(newfd);
381

    
382
        } else {
383
            fprintf(stderr,
384
                    "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
385
                    fd, strerror(errno));
386
            goto err;
387
        }
388
    }
389

    
390
    nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
391

    
392
    snprintf(nc->info_str, sizeof(nc->info_str),
393
            "socket: fd=%d (%s mcast=%s:%d)",
394
            fd, is_connected ? "cloned" : "",
395
            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
396

    
397
    s = DO_UPCAST(NetSocketState, nc, nc);
398

    
399
    s->fd = fd;
400
    s->listen_fd = -1;
401
    s->send_fn = net_socket_send_dgram;
402
    net_socket_read_poll(s, true);
403

    
404
    /* mcast: save bound address as dst */
405
    if (is_connected) {
406
        s->dgram_dst = saddr;
407
    }
408

    
409
    return s;
410

    
411
err:
412
    closesocket(fd);
413
    return NULL;
414
}
415

    
416
static void net_socket_connect(void *opaque)
417
{
418
    NetSocketState *s = opaque;
419
    s->send_fn = net_socket_send;
420
    net_socket_read_poll(s, true);
421
}
422

    
423
static NetClientInfo net_socket_info = {
424
    .type = NET_CLIENT_OPTIONS_KIND_SOCKET,
425
    .size = sizeof(NetSocketState),
426
    .receive = net_socket_receive,
427
    .cleanup = net_socket_cleanup,
428
};
429

    
430
static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
431
                                                 const char *model,
432
                                                 const char *name,
433
                                                 int fd, int is_connected)
434
{
435
    NetClientState *nc;
436
    NetSocketState *s;
437

    
438
    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
439

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

    
442
    s = DO_UPCAST(NetSocketState, nc, nc);
443

    
444
    s->fd = fd;
445
    s->listen_fd = -1;
446

    
447
    /* Disable Nagle algorithm on TCP sockets to reduce latency */
448
    socket_set_nodelay(fd);
449

    
450
    if (is_connected) {
451
        net_socket_connect(s);
452
    } else {
453
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
454
    }
455
    return s;
456
}
457

    
458
static NetSocketState *net_socket_fd_init(NetClientState *peer,
459
                                          const char *model, const char *name,
460
                                          int fd, int is_connected)
461
{
462
    int so_type = -1, optlen=sizeof(so_type);
463

    
464
    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
465
        (socklen_t *)&optlen)< 0) {
466
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n",
467
                fd);
468
        closesocket(fd);
469
        return NULL;
470
    }
471
    switch(so_type) {
472
    case SOCK_DGRAM:
473
        return net_socket_fd_init_dgram(peer, model, name, fd, is_connected);
474
    case SOCK_STREAM:
475
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
476
    default:
477
        /* who knows ... this could be a eg. a pty, do warn and continue as stream */
478
        fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
479
        return net_socket_fd_init_stream(peer, model, name, fd, is_connected);
480
    }
481
    return NULL;
482
}
483

    
484
static void net_socket_accept(void *opaque)
485
{
486
    NetSocketState *s = opaque;
487
    struct sockaddr_in saddr;
488
    socklen_t len;
489
    int fd;
490

    
491
    for(;;) {
492
        len = sizeof(saddr);
493
        fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
494
        if (fd < 0 && errno != EINTR) {
495
            return;
496
        } else if (fd >= 0) {
497
            qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
498
            break;
499
        }
500
    }
501

    
502
    s->fd = fd;
503
    s->nc.link_down = false;
504
    net_socket_connect(s);
505
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
506
             "socket: connection from %s:%d",
507
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
508
}
509

    
510
static int net_socket_listen_init(NetClientState *peer,
511
                                  const char *model,
512
                                  const char *name,
513
                                  const char *host_str)
514
{
515
    NetClientState *nc;
516
    NetSocketState *s;
517
    struct sockaddr_in saddr;
518
    int fd, ret;
519

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

    
523
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
524
    if (fd < 0) {
525
        perror("socket");
526
        return -1;
527
    }
528
    qemu_set_nonblock(fd);
529

    
530
    socket_set_fast_reuse(fd);
531

    
532
    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
533
    if (ret < 0) {
534
        perror("bind");
535
        closesocket(fd);
536
        return -1;
537
    }
538
    ret = listen(fd, 0);
539
    if (ret < 0) {
540
        perror("listen");
541
        closesocket(fd);
542
        return -1;
543
    }
544

    
545
    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
546
    s = DO_UPCAST(NetSocketState, nc, nc);
547
    s->fd = -1;
548
    s->listen_fd = fd;
549
    s->nc.link_down = true;
550

    
551
    qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
552
    return 0;
553
}
554

    
555
static int net_socket_connect_init(NetClientState *peer,
556
                                   const char *model,
557
                                   const char *name,
558
                                   const char *host_str)
559
{
560
    NetSocketState *s;
561
    int fd, connected, ret, err;
562
    struct sockaddr_in saddr;
563

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

    
567
    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
568
    if (fd < 0) {
569
        perror("socket");
570
        return -1;
571
    }
572
    qemu_set_nonblock(fd);
573

    
574
    connected = 0;
575
    for(;;) {
576
        ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
577
        if (ret < 0) {
578
            err = socket_error();
579
            if (err == EINTR || err == EWOULDBLOCK) {
580
            } else if (err == EINPROGRESS) {
581
                break;
582
#ifdef _WIN32
583
            } else if (err == WSAEALREADY || err == WSAEINVAL) {
584
                break;
585
#endif
586
            } else {
587
                perror("connect");
588
                closesocket(fd);
589
                return -1;
590
            }
591
        } else {
592
            connected = 1;
593
            break;
594
        }
595
    }
596
    s = net_socket_fd_init(peer, model, name, fd, connected);
597
    if (!s)
598
        return -1;
599
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
600
             "socket: connect to %s:%d",
601
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
602
    return 0;
603
}
604

    
605
static int net_socket_mcast_init(NetClientState *peer,
606
                                 const char *model,
607
                                 const char *name,
608
                                 const char *host_str,
609
                                 const char *localaddr_str)
610
{
611
    NetSocketState *s;
612
    int fd;
613
    struct sockaddr_in saddr;
614
    struct in_addr localaddr, *param_localaddr;
615

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

    
619
    if (localaddr_str != NULL) {
620
        if (inet_aton(localaddr_str, &localaddr) == 0)
621
            return -1;
622
        param_localaddr = &localaddr;
623
    } else {
624
        param_localaddr = NULL;
625
    }
626

    
627
    fd = net_socket_mcast_create(&saddr, param_localaddr);
628
    if (fd < 0)
629
        return -1;
630

    
631
    s = net_socket_fd_init(peer, model, name, fd, 0);
632
    if (!s)
633
        return -1;
634

    
635
    s->dgram_dst = saddr;
636

    
637
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
638
             "socket: mcast=%s:%d",
639
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
640
    return 0;
641

    
642
}
643

    
644
static int net_socket_udp_init(NetClientState *peer,
645
                                 const char *model,
646
                                 const char *name,
647
                                 const char *rhost,
648
                                 const char *lhost)
649
{
650
    NetSocketState *s;
651
    int fd, ret;
652
    struct sockaddr_in laddr, raddr;
653

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

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

    
662
    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
663
    if (fd < 0) {
664
        perror("socket(PF_INET, SOCK_DGRAM)");
665
        return -1;
666
    }
667

    
668
    ret = socket_set_fast_reuse(fd);
669
    if (ret < 0) {
670
        closesocket(fd);
671
        return -1;
672
    }
673
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
674
    if (ret < 0) {
675
        perror("bind");
676
        closesocket(fd);
677
        return -1;
678
    }
679
    qemu_set_nonblock(fd);
680

    
681
    s = net_socket_fd_init(peer, model, name, fd, 0);
682
    if (!s) {
683
        return -1;
684
    }
685

    
686
    s->dgram_dst = raddr;
687

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

    
694
int net_init_socket(const NetClientOptions *opts, const char *name,
695
                    NetClientState *peer)
696
{
697
    const NetdevSocketOptions *sock;
698

    
699
    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET);
700
    sock = opts->socket;
701

    
702
    if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
703
        sock->has_udp != 1) {
704
        error_report("exactly one of fd=, listen=, connect=, mcast= or udp="
705
                     " is required");
706
        return -1;
707
    }
708

    
709
    if (sock->has_localaddr && !sock->has_mcast && !sock->has_udp) {
710
        error_report("localaddr= is only valid with mcast= or udp=");
711
        return -1;
712
    }
713

    
714
    if (sock->has_fd) {
715
        int fd;
716

    
717
        fd = monitor_handle_fd_param(cur_mon, sock->fd);
718
        if (fd == -1) {
719
            return -1;
720
        }
721
        qemu_set_nonblock(fd);
722
        if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
723
            return -1;
724
        }
725
        return 0;
726
    }
727

    
728
    if (sock->has_listen) {
729
        if (net_socket_listen_init(peer, "socket", name, sock->listen) == -1) {
730
            return -1;
731
        }
732
        return 0;
733
    }
734

    
735
    if (sock->has_connect) {
736
        if (net_socket_connect_init(peer, "socket", name, sock->connect) ==
737
            -1) {
738
            return -1;
739
        }
740
        return 0;
741
    }
742

    
743
    if (sock->has_mcast) {
744
        /* if sock->localaddr is missing, it has been initialized to "all bits
745
         * zero" */
746
        if (net_socket_mcast_init(peer, "socket", name, sock->mcast,
747
            sock->localaddr) == -1) {
748
            return -1;
749
        }
750
        return 0;
751
    }
752

    
753
    assert(sock->has_udp);
754
    if (!sock->has_localaddr) {
755
        error_report("localaddr= is mandatory with udp=");
756
        return -1;
757
    }
758
    if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) ==
759
        -1) {
760
        return -1;
761
    }
762
    return 0;
763
}