Statistics
| Branch: | Revision:

root / net.c @ 1e5b9d2f

History | View | Annotate | Download (75.9 kB)

1 63a01ef8 aliguori
/*
2 63a01ef8 aliguori
 * QEMU System Emulator
3 63a01ef8 aliguori
 *
4 63a01ef8 aliguori
 * Copyright (c) 2003-2008 Fabrice Bellard
5 63a01ef8 aliguori
 *
6 63a01ef8 aliguori
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 63a01ef8 aliguori
 * of this software and associated documentation files (the "Software"), to deal
8 63a01ef8 aliguori
 * in the Software without restriction, including without limitation the rights
9 63a01ef8 aliguori
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 63a01ef8 aliguori
 * copies of the Software, and to permit persons to whom the Software is
11 63a01ef8 aliguori
 * furnished to do so, subject to the following conditions:
12 63a01ef8 aliguori
 *
13 63a01ef8 aliguori
 * The above copyright notice and this permission notice shall be included in
14 63a01ef8 aliguori
 * all copies or substantial portions of the Software.
15 63a01ef8 aliguori
 *
16 63a01ef8 aliguori
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 63a01ef8 aliguori
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 63a01ef8 aliguori
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 63a01ef8 aliguori
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 63a01ef8 aliguori
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 63a01ef8 aliguori
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 63a01ef8 aliguori
 * THE SOFTWARE.
23 63a01ef8 aliguori
 */
24 63a01ef8 aliguori
#include <unistd.h>
25 63a01ef8 aliguori
#include <fcntl.h>
26 63a01ef8 aliguori
#include <signal.h>
27 63a01ef8 aliguori
#include <time.h>
28 63a01ef8 aliguori
#include <errno.h>
29 63a01ef8 aliguori
#include <sys/time.h>
30 63a01ef8 aliguori
#include <zlib.h>
31 63a01ef8 aliguori
32 71e72a19 Juan Quintela
/* Needed early for CONFIG_BSD etc. */
33 d40cdb10 blueswir1
#include "config-host.h"
34 d40cdb10 blueswir1
35 63a01ef8 aliguori
#ifndef _WIN32
36 63a01ef8 aliguori
#include <sys/times.h>
37 63a01ef8 aliguori
#include <sys/wait.h>
38 63a01ef8 aliguori
#include <termios.h>
39 63a01ef8 aliguori
#include <sys/mman.h>
40 63a01ef8 aliguori
#include <sys/ioctl.h>
41 24646c7e blueswir1
#include <sys/resource.h>
42 63a01ef8 aliguori
#include <sys/socket.h>
43 63a01ef8 aliguori
#include <netinet/in.h>
44 24646c7e blueswir1
#include <net/if.h>
45 24646c7e blueswir1
#include <arpa/inet.h>
46 63a01ef8 aliguori
#include <dirent.h>
47 63a01ef8 aliguori
#include <netdb.h>
48 63a01ef8 aliguori
#include <sys/select.h>
49 71e72a19 Juan Quintela
#ifdef CONFIG_BSD
50 63a01ef8 aliguori
#include <sys/stat.h>
51 c5e97233 blueswir1
#if defined(__FreeBSD__) || defined(__DragonFly__)
52 63a01ef8 aliguori
#include <libutil.h>
53 24646c7e blueswir1
#else
54 24646c7e blueswir1
#include <util.h>
55 63a01ef8 aliguori
#endif
56 63a01ef8 aliguori
#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
57 63a01ef8 aliguori
#include <freebsd/stdlib.h>
58 63a01ef8 aliguori
#else
59 63a01ef8 aliguori
#ifdef __linux__
60 63a01ef8 aliguori
#include <pty.h>
61 63a01ef8 aliguori
#include <malloc.h>
62 63a01ef8 aliguori
#include <linux/rtc.h>
63 63a01ef8 aliguori
64 63a01ef8 aliguori
/* For the benefit of older linux systems which don't supply it,
65 63a01ef8 aliguori
   we use a local copy of hpet.h. */
66 63a01ef8 aliguori
/* #include <linux/hpet.h> */
67 63a01ef8 aliguori
#include "hpet.h"
68 63a01ef8 aliguori
69 63a01ef8 aliguori
#include <linux/ppdev.h>
70 63a01ef8 aliguori
#include <linux/parport.h>
71 63a01ef8 aliguori
#endif
72 63a01ef8 aliguori
#ifdef __sun__
73 63a01ef8 aliguori
#include <sys/stat.h>
74 63a01ef8 aliguori
#include <sys/ethernet.h>
75 63a01ef8 aliguori
#include <sys/sockio.h>
76 63a01ef8 aliguori
#include <netinet/arp.h>
77 63a01ef8 aliguori
#include <netinet/in.h>
78 63a01ef8 aliguori
#include <netinet/in_systm.h>
79 63a01ef8 aliguori
#include <netinet/ip.h>
80 63a01ef8 aliguori
#include <netinet/ip_icmp.h> // must come after ip.h
81 63a01ef8 aliguori
#include <netinet/udp.h>
82 63a01ef8 aliguori
#include <netinet/tcp.h>
83 63a01ef8 aliguori
#include <net/if.h>
84 63a01ef8 aliguori
#include <syslog.h>
85 63a01ef8 aliguori
#include <stropts.h>
86 63a01ef8 aliguori
#endif
87 63a01ef8 aliguori
#endif
88 63a01ef8 aliguori
#endif
89 63a01ef8 aliguori
90 63a01ef8 aliguori
#if defined(__OpenBSD__)
91 63a01ef8 aliguori
#include <util.h>
92 63a01ef8 aliguori
#endif
93 63a01ef8 aliguori
94 63a01ef8 aliguori
#if defined(CONFIG_VDE)
95 63a01ef8 aliguori
#include <libvdeplug.h>
96 63a01ef8 aliguori
#endif
97 63a01ef8 aliguori
98 511d2b14 blueswir1
#include "qemu-common.h"
99 511d2b14 blueswir1
#include "net.h"
100 a8ed73f7 Mark McLoughlin
#include "net/tap.h"
101 511d2b14 blueswir1
#include "monitor.h"
102 511d2b14 blueswir1
#include "sysemu.h"
103 511d2b14 blueswir1
#include "qemu-timer.h"
104 511d2b14 blueswir1
#include "qemu-char.h"
105 511d2b14 blueswir1
#include "audio/audio.h"
106 511d2b14 blueswir1
#include "qemu_socket.h"
107 bb9ea79e aliguori
#include "qemu-log.h"
108 f83c6e10 Mark McLoughlin
#include "qemu-config.h"
109 511d2b14 blueswir1
110 d918f23e Jan Kiszka
#include "slirp/libslirp.h"
111 511d2b14 blueswir1
112 5610c3aa Mark McLoughlin
static QTAILQ_HEAD(, VLANState) vlans;
113 577c4af9 Mark McLoughlin
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
114 63a01ef8 aliguori
115 63a01ef8 aliguori
/***********************************************************/
116 63a01ef8 aliguori
/* network device redirectors */
117 63a01ef8 aliguori
118 63a01ef8 aliguori
#if defined(DEBUG_NET) || defined(DEBUG_SLIRP)
119 63a01ef8 aliguori
static void hex_dump(FILE *f, const uint8_t *buf, int size)
120 63a01ef8 aliguori
{
121 63a01ef8 aliguori
    int len, i, j, c;
122 63a01ef8 aliguori
123 63a01ef8 aliguori
    for(i=0;i<size;i+=16) {
124 63a01ef8 aliguori
        len = size - i;
125 63a01ef8 aliguori
        if (len > 16)
126 63a01ef8 aliguori
            len = 16;
127 63a01ef8 aliguori
        fprintf(f, "%08x ", i);
128 63a01ef8 aliguori
        for(j=0;j<16;j++) {
129 63a01ef8 aliguori
            if (j < len)
130 63a01ef8 aliguori
                fprintf(f, " %02x", buf[i+j]);
131 63a01ef8 aliguori
            else
132 63a01ef8 aliguori
                fprintf(f, "   ");
133 63a01ef8 aliguori
        }
134 63a01ef8 aliguori
        fprintf(f, " ");
135 63a01ef8 aliguori
        for(j=0;j<len;j++) {
136 63a01ef8 aliguori
            c = buf[i+j];
137 63a01ef8 aliguori
            if (c < ' ' || c > '~')
138 63a01ef8 aliguori
                c = '.';
139 63a01ef8 aliguori
            fprintf(f, "%c", c);
140 63a01ef8 aliguori
        }
141 63a01ef8 aliguori
        fprintf(f, "\n");
142 63a01ef8 aliguori
    }
143 63a01ef8 aliguori
}
144 63a01ef8 aliguori
#endif
145 63a01ef8 aliguori
146 63a01ef8 aliguori
static int parse_macaddr(uint8_t *macaddr, const char *p)
147 63a01ef8 aliguori
{
148 63a01ef8 aliguori
    int i;
149 63a01ef8 aliguori
    char *last_char;
150 63a01ef8 aliguori
    long int offset;
151 63a01ef8 aliguori
152 63a01ef8 aliguori
    errno = 0;
153 63a01ef8 aliguori
    offset = strtol(p, &last_char, 0);    
154 63a01ef8 aliguori
    if (0 == errno && '\0' == *last_char &&
155 63a01ef8 aliguori
            offset >= 0 && offset <= 0xFFFFFF) {
156 63a01ef8 aliguori
        macaddr[3] = (offset & 0xFF0000) >> 16;
157 63a01ef8 aliguori
        macaddr[4] = (offset & 0xFF00) >> 8;
158 63a01ef8 aliguori
        macaddr[5] = offset & 0xFF;
159 63a01ef8 aliguori
        return 0;
160 63a01ef8 aliguori
    } else {
161 63a01ef8 aliguori
        for(i = 0; i < 6; i++) {
162 63a01ef8 aliguori
            macaddr[i] = strtol(p, (char **)&p, 16);
163 63a01ef8 aliguori
            if (i == 5) {
164 63a01ef8 aliguori
                if (*p != '\0')
165 63a01ef8 aliguori
                    return -1;
166 63a01ef8 aliguori
            } else {
167 63a01ef8 aliguori
                if (*p != ':' && *p != '-')
168 63a01ef8 aliguori
                    return -1;
169 63a01ef8 aliguori
                p++;
170 63a01ef8 aliguori
            }
171 63a01ef8 aliguori
        }
172 63a01ef8 aliguori
        return 0;    
173 63a01ef8 aliguori
    }
174 63a01ef8 aliguori
175 63a01ef8 aliguori
    return -1;
176 63a01ef8 aliguori
}
177 63a01ef8 aliguori
178 63a01ef8 aliguori
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
179 63a01ef8 aliguori
{
180 63a01ef8 aliguori
    const char *p, *p1;
181 63a01ef8 aliguori
    int len;
182 63a01ef8 aliguori
    p = *pp;
183 63a01ef8 aliguori
    p1 = strchr(p, sep);
184 63a01ef8 aliguori
    if (!p1)
185 63a01ef8 aliguori
        return -1;
186 63a01ef8 aliguori
    len = p1 - p;
187 63a01ef8 aliguori
    p1++;
188 63a01ef8 aliguori
    if (buf_size > 0) {
189 63a01ef8 aliguori
        if (len > buf_size - 1)
190 63a01ef8 aliguori
            len = buf_size - 1;
191 63a01ef8 aliguori
        memcpy(buf, p, len);
192 63a01ef8 aliguori
        buf[len] = '\0';
193 63a01ef8 aliguori
    }
194 63a01ef8 aliguori
    *pp = p1;
195 63a01ef8 aliguori
    return 0;
196 63a01ef8 aliguori
}
197 63a01ef8 aliguori
198 63a01ef8 aliguori
int parse_host_src_port(struct sockaddr_in *haddr,
199 63a01ef8 aliguori
                        struct sockaddr_in *saddr,
200 63a01ef8 aliguori
                        const char *input_str)
201 63a01ef8 aliguori
{
202 63a01ef8 aliguori
    char *str = strdup(input_str);
203 63a01ef8 aliguori
    char *host_str = str;
204 63a01ef8 aliguori
    char *src_str;
205 63a01ef8 aliguori
    const char *src_str2;
206 63a01ef8 aliguori
    char *ptr;
207 63a01ef8 aliguori
208 63a01ef8 aliguori
    /*
209 63a01ef8 aliguori
     * Chop off any extra arguments at the end of the string which
210 63a01ef8 aliguori
     * would start with a comma, then fill in the src port information
211 63a01ef8 aliguori
     * if it was provided else use the "any address" and "any port".
212 63a01ef8 aliguori
     */
213 63a01ef8 aliguori
    if ((ptr = strchr(str,',')))
214 63a01ef8 aliguori
        *ptr = '\0';
215 63a01ef8 aliguori
216 63a01ef8 aliguori
    if ((src_str = strchr(input_str,'@'))) {
217 63a01ef8 aliguori
        *src_str = '\0';
218 63a01ef8 aliguori
        src_str++;
219 63a01ef8 aliguori
    }
220 63a01ef8 aliguori
221 63a01ef8 aliguori
    if (parse_host_port(haddr, host_str) < 0)
222 63a01ef8 aliguori
        goto fail;
223 63a01ef8 aliguori
224 63a01ef8 aliguori
    src_str2 = src_str;
225 63a01ef8 aliguori
    if (!src_str || *src_str == '\0')
226 63a01ef8 aliguori
        src_str2 = ":0";
227 63a01ef8 aliguori
228 63a01ef8 aliguori
    if (parse_host_port(saddr, src_str2) < 0)
229 63a01ef8 aliguori
        goto fail;
230 63a01ef8 aliguori
231 63a01ef8 aliguori
    free(str);
232 63a01ef8 aliguori
    return(0);
233 63a01ef8 aliguori
234 63a01ef8 aliguori
fail:
235 63a01ef8 aliguori
    free(str);
236 63a01ef8 aliguori
    return -1;
237 63a01ef8 aliguori
}
238 63a01ef8 aliguori
239 63a01ef8 aliguori
int parse_host_port(struct sockaddr_in *saddr, const char *str)
240 63a01ef8 aliguori
{
241 63a01ef8 aliguori
    char buf[512];
242 63a01ef8 aliguori
    struct hostent *he;
243 63a01ef8 aliguori
    const char *p, *r;
244 63a01ef8 aliguori
    int port;
245 63a01ef8 aliguori
246 63a01ef8 aliguori
    p = str;
247 63a01ef8 aliguori
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
248 63a01ef8 aliguori
        return -1;
249 63a01ef8 aliguori
    saddr->sin_family = AF_INET;
250 63a01ef8 aliguori
    if (buf[0] == '\0') {
251 63a01ef8 aliguori
        saddr->sin_addr.s_addr = 0;
252 63a01ef8 aliguori
    } else {
253 cd390083 blueswir1
        if (qemu_isdigit(buf[0])) {
254 63a01ef8 aliguori
            if (!inet_aton(buf, &saddr->sin_addr))
255 63a01ef8 aliguori
                return -1;
256 63a01ef8 aliguori
        } else {
257 63a01ef8 aliguori
            if ((he = gethostbyname(buf)) == NULL)
258 63a01ef8 aliguori
                return - 1;
259 63a01ef8 aliguori
            saddr->sin_addr = *(struct in_addr *)he->h_addr;
260 63a01ef8 aliguori
        }
261 63a01ef8 aliguori
    }
262 63a01ef8 aliguori
    port = strtol(p, (char **)&r, 0);
263 63a01ef8 aliguori
    if (r == p)
264 63a01ef8 aliguori
        return -1;
265 63a01ef8 aliguori
    saddr->sin_port = htons(port);
266 63a01ef8 aliguori
    return 0;
267 63a01ef8 aliguori
}
268 63a01ef8 aliguori
269 7cb7434b aliguori
void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6])
270 7cb7434b aliguori
{
271 7cb7434b aliguori
    snprintf(vc->info_str, sizeof(vc->info_str),
272 4dda4063 aliguori
             "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
273 4dda4063 aliguori
             vc->model,
274 7cb7434b aliguori
             macaddr[0], macaddr[1], macaddr[2],
275 7cb7434b aliguori
             macaddr[3], macaddr[4], macaddr[5]);
276 7cb7434b aliguori
}
277 7cb7434b aliguori
278 76d32cba Gerd Hoffmann
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
279 76d32cba Gerd Hoffmann
{
280 76d32cba Gerd Hoffmann
    static int index = 0;
281 76d32cba Gerd Hoffmann
    static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
282 76d32cba Gerd Hoffmann
283 76d32cba Gerd Hoffmann
    if (memcmp(macaddr, &zero, sizeof(zero)) != 0)
284 76d32cba Gerd Hoffmann
        return;
285 76d32cba Gerd Hoffmann
    macaddr->a[0] = 0x52;
286 76d32cba Gerd Hoffmann
    macaddr->a[1] = 0x54;
287 76d32cba Gerd Hoffmann
    macaddr->a[2] = 0x00;
288 76d32cba Gerd Hoffmann
    macaddr->a[3] = 0x12;
289 76d32cba Gerd Hoffmann
    macaddr->a[4] = 0x34;
290 76d32cba Gerd Hoffmann
    macaddr->a[5] = 0x56 + index++;
291 76d32cba Gerd Hoffmann
}
292 76d32cba Gerd Hoffmann
293 676cff29 aliguori
static char *assign_name(VLANClientState *vc1, const char *model)
294 676cff29 aliguori
{
295 676cff29 aliguori
    VLANState *vlan;
296 676cff29 aliguori
    char buf[256];
297 676cff29 aliguori
    int id = 0;
298 676cff29 aliguori
299 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
300 676cff29 aliguori
        VLANClientState *vc;
301 676cff29 aliguori
302 5610c3aa Mark McLoughlin
        QTAILQ_FOREACH(vc, &vlan->clients, next) {
303 5610c3aa Mark McLoughlin
            if (vc != vc1 && strcmp(vc->model, model) == 0) {
304 676cff29 aliguori
                id++;
305 5610c3aa Mark McLoughlin
            }
306 5610c3aa Mark McLoughlin
        }
307 676cff29 aliguori
    }
308 676cff29 aliguori
309 676cff29 aliguori
    snprintf(buf, sizeof(buf), "%s.%d", model, id);
310 676cff29 aliguori
311 02374aa0 Mark McLoughlin
    return qemu_strdup(buf);
312 676cff29 aliguori
}
313 676cff29 aliguori
314 9a6ecb30 Mark McLoughlin
static ssize_t qemu_deliver_packet(VLANClientState *sender,
315 c0b8e49c Mark McLoughlin
                                   unsigned flags,
316 9a6ecb30 Mark McLoughlin
                                   const uint8_t *data,
317 9a6ecb30 Mark McLoughlin
                                   size_t size,
318 9a6ecb30 Mark McLoughlin
                                   void *opaque);
319 9a6ecb30 Mark McLoughlin
static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
320 c0b8e49c Mark McLoughlin
                                       unsigned flags,
321 9a6ecb30 Mark McLoughlin
                                       const struct iovec *iov,
322 9a6ecb30 Mark McLoughlin
                                       int iovcnt,
323 9a6ecb30 Mark McLoughlin
                                       void *opaque);
324 9a6ecb30 Mark McLoughlin
325 bb6e6364 Mark McLoughlin
VLANClientState *qemu_new_vlan_client(net_client_type type,
326 bb6e6364 Mark McLoughlin
                                      VLANState *vlan,
327 283c7c63 Mark McLoughlin
                                      VLANClientState *peer,
328 bf38c1a0 aliguori
                                      const char *model,
329 7a9f6e4a aliguori
                                      const char *name,
330 cda9046b Mark McLoughlin
                                      NetCanReceive *can_receive,
331 cda9046b Mark McLoughlin
                                      NetReceive *receive,
332 70783b9c Mark McLoughlin
                                      NetReceive *receive_raw,
333 cda9046b Mark McLoughlin
                                      NetReceiveIOV *receive_iov,
334 b946a153 aliguori
                                      NetCleanup *cleanup,
335 63a01ef8 aliguori
                                      void *opaque)
336 63a01ef8 aliguori
{
337 5610c3aa Mark McLoughlin
    VLANClientState *vc;
338 5610c3aa Mark McLoughlin
339 63a01ef8 aliguori
    vc = qemu_mallocz(sizeof(VLANClientState));
340 5610c3aa Mark McLoughlin
341 bb6e6364 Mark McLoughlin
    vc->type = type;
342 02374aa0 Mark McLoughlin
    vc->model = qemu_strdup(model);
343 7a9f6e4a aliguori
    if (name)
344 02374aa0 Mark McLoughlin
        vc->name = qemu_strdup(name);
345 7a9f6e4a aliguori
    else
346 7a9f6e4a aliguori
        vc->name = assign_name(vc, model);
347 cda9046b Mark McLoughlin
    vc->can_receive = can_receive;
348 cda9046b Mark McLoughlin
    vc->receive = receive;
349 70783b9c Mark McLoughlin
    vc->receive_raw = receive_raw;
350 cda9046b Mark McLoughlin
    vc->receive_iov = receive_iov;
351 b946a153 aliguori
    vc->cleanup = cleanup;
352 63a01ef8 aliguori
    vc->opaque = opaque;
353 5610c3aa Mark McLoughlin
354 d80b9fc6 Mark McLoughlin
    if (vlan) {
355 283c7c63 Mark McLoughlin
        assert(!peer);
356 d80b9fc6 Mark McLoughlin
        vc->vlan = vlan;
357 d80b9fc6 Mark McLoughlin
        QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
358 577c4af9 Mark McLoughlin
    } else {
359 283c7c63 Mark McLoughlin
        if (peer) {
360 283c7c63 Mark McLoughlin
            vc->peer = peer;
361 283c7c63 Mark McLoughlin
            peer->peer = vc;
362 283c7c63 Mark McLoughlin
        }
363 577c4af9 Mark McLoughlin
        QTAILQ_INSERT_TAIL(&non_vlan_clients, vc, next);
364 9a6ecb30 Mark McLoughlin
365 9a6ecb30 Mark McLoughlin
        vc->send_queue = qemu_new_net_queue(qemu_deliver_packet,
366 9a6ecb30 Mark McLoughlin
                                            qemu_deliver_packet_iov,
367 9a6ecb30 Mark McLoughlin
                                            vc);
368 d80b9fc6 Mark McLoughlin
    }
369 63a01ef8 aliguori
370 63a01ef8 aliguori
    return vc;
371 63a01ef8 aliguori
}
372 63a01ef8 aliguori
373 63a01ef8 aliguori
void qemu_del_vlan_client(VLANClientState *vc)
374 63a01ef8 aliguori
{
375 d80b9fc6 Mark McLoughlin
    if (vc->vlan) {
376 d80b9fc6 Mark McLoughlin
        QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
377 577c4af9 Mark McLoughlin
    } else {
378 9a6ecb30 Mark McLoughlin
        if (vc->send_queue) {
379 9a6ecb30 Mark McLoughlin
            qemu_del_net_queue(vc->send_queue);
380 9a6ecb30 Mark McLoughlin
        }
381 577c4af9 Mark McLoughlin
        QTAILQ_REMOVE(&non_vlan_clients, vc, next);
382 283c7c63 Mark McLoughlin
        if (vc->peer) {
383 283c7c63 Mark McLoughlin
            vc->peer->peer = NULL;
384 283c7c63 Mark McLoughlin
        }
385 d80b9fc6 Mark McLoughlin
    }
386 63a01ef8 aliguori
387 5610c3aa Mark McLoughlin
    if (vc->cleanup) {
388 5610c3aa Mark McLoughlin
        vc->cleanup(vc);
389 5610c3aa Mark McLoughlin
    }
390 5610c3aa Mark McLoughlin
391 5610c3aa Mark McLoughlin
    qemu_free(vc->name);
392 5610c3aa Mark McLoughlin
    qemu_free(vc->model);
393 5610c3aa Mark McLoughlin
    qemu_free(vc);
394 63a01ef8 aliguori
}
395 63a01ef8 aliguori
396 8b13c4a7 aliguori
VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
397 8b13c4a7 aliguori
{
398 5610c3aa Mark McLoughlin
    VLANClientState *vc;
399 8b13c4a7 aliguori
400 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vc, &vlan->clients, next) {
401 5610c3aa Mark McLoughlin
        if (vc->opaque == opaque) {
402 5610c3aa Mark McLoughlin
            return vc;
403 5610c3aa Mark McLoughlin
        }
404 5610c3aa Mark McLoughlin
    }
405 8b13c4a7 aliguori
406 8b13c4a7 aliguori
    return NULL;
407 8b13c4a7 aliguori
}
408 8b13c4a7 aliguori
409 1a609520 Jan Kiszka
static VLANClientState *
410 1a609520 Jan Kiszka
qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
411 1a609520 Jan Kiszka
                              const char *client_str)
412 1a609520 Jan Kiszka
{
413 1a609520 Jan Kiszka
    VLANState *vlan;
414 1a609520 Jan Kiszka
    VLANClientState *vc;
415 1a609520 Jan Kiszka
416 1a609520 Jan Kiszka
    vlan = qemu_find_vlan(vlan_id, 0);
417 1a609520 Jan Kiszka
    if (!vlan) {
418 1a609520 Jan Kiszka
        monitor_printf(mon, "unknown VLAN %d\n", vlan_id);
419 1a609520 Jan Kiszka
        return NULL;
420 1a609520 Jan Kiszka
    }
421 1a609520 Jan Kiszka
422 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vc, &vlan->clients, next) {
423 1a609520 Jan Kiszka
        if (!strcmp(vc->name, client_str)) {
424 1a609520 Jan Kiszka
            break;
425 1a609520 Jan Kiszka
        }
426 1a609520 Jan Kiszka
    }
427 1a609520 Jan Kiszka
    if (!vc) {
428 1a609520 Jan Kiszka
        monitor_printf(mon, "can't find device %s on VLAN %d\n",
429 1a609520 Jan Kiszka
                       client_str, vlan_id);
430 1a609520 Jan Kiszka
    }
431 1a609520 Jan Kiszka
432 1a609520 Jan Kiszka
    return vc;
433 1a609520 Jan Kiszka
}
434 1a609520 Jan Kiszka
435 2e1e0641 Mark McLoughlin
int qemu_can_send_packet(VLANClientState *sender)
436 63a01ef8 aliguori
{
437 2e1e0641 Mark McLoughlin
    VLANState *vlan = sender->vlan;
438 63a01ef8 aliguori
    VLANClientState *vc;
439 63a01ef8 aliguori
440 9a6ecb30 Mark McLoughlin
    if (sender->peer) {
441 9a6ecb30 Mark McLoughlin
        if (!sender->peer->can_receive ||
442 9a6ecb30 Mark McLoughlin
            sender->peer->can_receive(sender->peer)) {
443 9a6ecb30 Mark McLoughlin
            return 1;
444 9a6ecb30 Mark McLoughlin
        } else {
445 9a6ecb30 Mark McLoughlin
            return 0;
446 9a6ecb30 Mark McLoughlin
        }
447 9a6ecb30 Mark McLoughlin
    }
448 9a6ecb30 Mark McLoughlin
449 d80b9fc6 Mark McLoughlin
    if (!sender->vlan) {
450 d80b9fc6 Mark McLoughlin
        return 1;
451 d80b9fc6 Mark McLoughlin
    }
452 d80b9fc6 Mark McLoughlin
453 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vc, &vlan->clients, next) {
454 2e1e0641 Mark McLoughlin
        if (vc == sender) {
455 2e1e0641 Mark McLoughlin
            continue;
456 2e1e0641 Mark McLoughlin
        }
457 2e1e0641 Mark McLoughlin
458 cda9046b Mark McLoughlin
        /* no can_receive() handler, they can always receive */
459 e3f5ec2b Mark McLoughlin
        if (!vc->can_receive || vc->can_receive(vc)) {
460 2e1e0641 Mark McLoughlin
            return 1;
461 63a01ef8 aliguori
        }
462 63a01ef8 aliguori
    }
463 63a01ef8 aliguori
    return 0;
464 63a01ef8 aliguori
}
465 63a01ef8 aliguori
466 9a6ecb30 Mark McLoughlin
static ssize_t qemu_deliver_packet(VLANClientState *sender,
467 c0b8e49c Mark McLoughlin
                                   unsigned flags,
468 9a6ecb30 Mark McLoughlin
                                   const uint8_t *data,
469 9a6ecb30 Mark McLoughlin
                                   size_t size,
470 9a6ecb30 Mark McLoughlin
                                   void *opaque)
471 9a6ecb30 Mark McLoughlin
{
472 9a6ecb30 Mark McLoughlin
    VLANClientState *vc = opaque;
473 9a6ecb30 Mark McLoughlin
474 9a6ecb30 Mark McLoughlin
    if (vc->link_down) {
475 9a6ecb30 Mark McLoughlin
        return size;
476 9a6ecb30 Mark McLoughlin
    }
477 9a6ecb30 Mark McLoughlin
478 ca77d175 Mark McLoughlin
    if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw)
479 ca77d175 Mark McLoughlin
        return vc->receive_raw(vc, data, size);
480 ca77d175 Mark McLoughlin
    else
481 ca77d175 Mark McLoughlin
        return vc->receive(vc, data, size);
482 9a6ecb30 Mark McLoughlin
}
483 9a6ecb30 Mark McLoughlin
484 f7105843 Mark McLoughlin
static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
485 c0b8e49c Mark McLoughlin
                                        unsigned flags,
486 f7105843 Mark McLoughlin
                                        const uint8_t *buf,
487 f7105843 Mark McLoughlin
                                        size_t size,
488 f7105843 Mark McLoughlin
                                        void *opaque)
489 63a01ef8 aliguori
{
490 f7105843 Mark McLoughlin
    VLANState *vlan = opaque;
491 63a01ef8 aliguori
    VLANClientState *vc;
492 3e021d40 Mark McLoughlin
    int ret = -1;
493 63a01ef8 aliguori
494 f7105843 Mark McLoughlin
    QTAILQ_FOREACH(vc, &vlan->clients, next) {
495 3e021d40 Mark McLoughlin
        ssize_t len;
496 3e021d40 Mark McLoughlin
497 3e021d40 Mark McLoughlin
        if (vc == sender) {
498 3e021d40 Mark McLoughlin
            continue;
499 764a4d1d aliguori
        }
500 3e021d40 Mark McLoughlin
501 3e021d40 Mark McLoughlin
        if (vc->link_down) {
502 3e021d40 Mark McLoughlin
            ret = size;
503 3e021d40 Mark McLoughlin
            continue;
504 3e021d40 Mark McLoughlin
        }
505 3e021d40 Mark McLoughlin
506 ca77d175 Mark McLoughlin
        if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw)
507 ca77d175 Mark McLoughlin
            len = vc->receive_raw(vc, buf, size);
508 ca77d175 Mark McLoughlin
        else
509 ca77d175 Mark McLoughlin
            len = vc->receive(vc, buf, size);
510 3e021d40 Mark McLoughlin
511 3e021d40 Mark McLoughlin
        ret = (ret >= 0) ? ret : len;
512 764a4d1d aliguori
    }
513 3e021d40 Mark McLoughlin
514 3e021d40 Mark McLoughlin
    return ret;
515 764a4d1d aliguori
}
516 764a4d1d aliguori
517 8cad5516 Mark McLoughlin
void qemu_purge_queued_packets(VLANClientState *vc)
518 8cad5516 Mark McLoughlin
{
519 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
520 9a6ecb30 Mark McLoughlin
521 9a6ecb30 Mark McLoughlin
    if (!vc->peer && !vc->vlan) {
522 d80b9fc6 Mark McLoughlin
        return;
523 9a6ecb30 Mark McLoughlin
    }
524 d80b9fc6 Mark McLoughlin
525 9a6ecb30 Mark McLoughlin
    if (vc->peer) {
526 9a6ecb30 Mark McLoughlin
        queue = vc->peer->send_queue;
527 9a6ecb30 Mark McLoughlin
    } else {
528 9a6ecb30 Mark McLoughlin
        queue = vc->vlan->send_queue;
529 9a6ecb30 Mark McLoughlin
    }
530 9a6ecb30 Mark McLoughlin
531 9a6ecb30 Mark McLoughlin
    qemu_net_queue_purge(queue, vc);
532 8cad5516 Mark McLoughlin
}
533 8cad5516 Mark McLoughlin
534 f3b6c7fc Mark McLoughlin
void qemu_flush_queued_packets(VLANClientState *vc)
535 e94667b9 Mark McLoughlin
{
536 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
537 9a6ecb30 Mark McLoughlin
538 9a6ecb30 Mark McLoughlin
    if (vc->vlan) {
539 9a6ecb30 Mark McLoughlin
        queue = vc->vlan->send_queue;
540 9a6ecb30 Mark McLoughlin
    } else {
541 9a6ecb30 Mark McLoughlin
        queue = vc->send_queue;
542 9a6ecb30 Mark McLoughlin
    }
543 d80b9fc6 Mark McLoughlin
544 9a6ecb30 Mark McLoughlin
    qemu_net_queue_flush(queue);
545 e94667b9 Mark McLoughlin
}
546 e94667b9 Mark McLoughlin
547 ca77d175 Mark McLoughlin
static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender,
548 ca77d175 Mark McLoughlin
                                                 unsigned flags,
549 ca77d175 Mark McLoughlin
                                                 const uint8_t *buf, int size,
550 ca77d175 Mark McLoughlin
                                                 NetPacketSent *sent_cb)
551 764a4d1d aliguori
{
552 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
553 436e5e53 aliguori
554 63a01ef8 aliguori
#ifdef DEBUG_NET
555 d80b9fc6 Mark McLoughlin
    printf("qemu_send_packet_async:\n");
556 63a01ef8 aliguori
    hex_dump(stdout, buf, size);
557 63a01ef8 aliguori
#endif
558 f3b6c7fc Mark McLoughlin
559 9a6ecb30 Mark McLoughlin
    if (sender->link_down || (!sender->peer && !sender->vlan)) {
560 9a6ecb30 Mark McLoughlin
        return size;
561 9a6ecb30 Mark McLoughlin
    }
562 9a6ecb30 Mark McLoughlin
563 9a6ecb30 Mark McLoughlin
    if (sender->peer) {
564 9a6ecb30 Mark McLoughlin
        queue = sender->peer->send_queue;
565 9a6ecb30 Mark McLoughlin
    } else {
566 9a6ecb30 Mark McLoughlin
        queue = sender->vlan->send_queue;
567 9a6ecb30 Mark McLoughlin
    }
568 9a6ecb30 Mark McLoughlin
569 ca77d175 Mark McLoughlin
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
570 ca77d175 Mark McLoughlin
}
571 ca77d175 Mark McLoughlin
572 ca77d175 Mark McLoughlin
ssize_t qemu_send_packet_async(VLANClientState *sender,
573 ca77d175 Mark McLoughlin
                               const uint8_t *buf, int size,
574 ca77d175 Mark McLoughlin
                               NetPacketSent *sent_cb)
575 ca77d175 Mark McLoughlin
{
576 ca77d175 Mark McLoughlin
    return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
577 ca77d175 Mark McLoughlin
                                             buf, size, sent_cb);
578 f3b6c7fc Mark McLoughlin
}
579 f3b6c7fc Mark McLoughlin
580 f3b6c7fc Mark McLoughlin
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
581 f3b6c7fc Mark McLoughlin
{
582 f3b6c7fc Mark McLoughlin
    qemu_send_packet_async(vc, buf, size, NULL);
583 63a01ef8 aliguori
}
584 63a01ef8 aliguori
585 ca77d175 Mark McLoughlin
ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size)
586 ca77d175 Mark McLoughlin
{
587 ca77d175 Mark McLoughlin
    return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW,
588 ca77d175 Mark McLoughlin
                                             buf, size, NULL);
589 ca77d175 Mark McLoughlin
}
590 ca77d175 Mark McLoughlin
591 fbe78f4f aliguori
static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov,
592 fbe78f4f aliguori
                               int iovcnt)
593 fbe78f4f aliguori
{
594 fbe78f4f aliguori
    uint8_t buffer[4096];
595 fbe78f4f aliguori
    size_t offset = 0;
596 fbe78f4f aliguori
    int i;
597 fbe78f4f aliguori
598 fbe78f4f aliguori
    for (i = 0; i < iovcnt; i++) {
599 fbe78f4f aliguori
        size_t len;
600 fbe78f4f aliguori
601 fbe78f4f aliguori
        len = MIN(sizeof(buffer) - offset, iov[i].iov_len);
602 fbe78f4f aliguori
        memcpy(buffer + offset, iov[i].iov_base, len);
603 fbe78f4f aliguori
        offset += len;
604 fbe78f4f aliguori
    }
605 fbe78f4f aliguori
606 f3b6c7fc Mark McLoughlin
    return vc->receive(vc, buffer, offset);
607 fbe78f4f aliguori
}
608 fbe78f4f aliguori
609 e0e7877a aliguori
static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
610 e0e7877a aliguori
{
611 e0e7877a aliguori
    size_t offset = 0;
612 e0e7877a aliguori
    int i;
613 e0e7877a aliguori
614 e0e7877a aliguori
    for (i = 0; i < iovcnt; i++)
615 e0e7877a aliguori
        offset += iov[i].iov_len;
616 e0e7877a aliguori
    return offset;
617 e0e7877a aliguori
}
618 e0e7877a aliguori
619 9a6ecb30 Mark McLoughlin
static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
620 c0b8e49c Mark McLoughlin
                                       unsigned flags,
621 9a6ecb30 Mark McLoughlin
                                       const struct iovec *iov,
622 9a6ecb30 Mark McLoughlin
                                       int iovcnt,
623 9a6ecb30 Mark McLoughlin
                                       void *opaque)
624 9a6ecb30 Mark McLoughlin
{
625 9a6ecb30 Mark McLoughlin
    VLANClientState *vc = opaque;
626 9a6ecb30 Mark McLoughlin
627 9a6ecb30 Mark McLoughlin
    if (vc->link_down) {
628 9a6ecb30 Mark McLoughlin
        return calc_iov_length(iov, iovcnt);
629 9a6ecb30 Mark McLoughlin
    }
630 9a6ecb30 Mark McLoughlin
631 9a6ecb30 Mark McLoughlin
    if (vc->receive_iov) {
632 9a6ecb30 Mark McLoughlin
        return vc->receive_iov(vc, iov, iovcnt);
633 9a6ecb30 Mark McLoughlin
    } else {
634 9a6ecb30 Mark McLoughlin
        return vc_sendv_compat(vc, iov, iovcnt);
635 9a6ecb30 Mark McLoughlin
    }
636 9a6ecb30 Mark McLoughlin
}
637 9a6ecb30 Mark McLoughlin
638 f7105843 Mark McLoughlin
static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
639 c0b8e49c Mark McLoughlin
                                            unsigned flags,
640 f7105843 Mark McLoughlin
                                            const struct iovec *iov,
641 f7105843 Mark McLoughlin
                                            int iovcnt,
642 f7105843 Mark McLoughlin
                                            void *opaque)
643 fbe78f4f aliguori
{
644 f7105843 Mark McLoughlin
    VLANState *vlan = opaque;
645 fbe78f4f aliguori
    VLANClientState *vc;
646 f7105843 Mark McLoughlin
    ssize_t ret = -1;
647 e94667b9 Mark McLoughlin
648 f7105843 Mark McLoughlin
    QTAILQ_FOREACH(vc, &vlan->clients, next) {
649 e94667b9 Mark McLoughlin
        ssize_t len;
650 e94667b9 Mark McLoughlin
651 e94667b9 Mark McLoughlin
        if (vc == sender) {
652 e94667b9 Mark McLoughlin
            continue;
653 e94667b9 Mark McLoughlin
        }
654 e94667b9 Mark McLoughlin
655 e94667b9 Mark McLoughlin
        if (vc->link_down) {
656 e94667b9 Mark McLoughlin
            ret = calc_iov_length(iov, iovcnt);
657 e94667b9 Mark McLoughlin
            continue;
658 e94667b9 Mark McLoughlin
        }
659 e94667b9 Mark McLoughlin
660 ca77d175 Mark McLoughlin
        assert(!(flags & QEMU_NET_PACKET_FLAG_RAW));
661 ca77d175 Mark McLoughlin
662 e94667b9 Mark McLoughlin
        if (vc->receive_iov) {
663 e94667b9 Mark McLoughlin
            len = vc->receive_iov(vc, iov, iovcnt);
664 e94667b9 Mark McLoughlin
        } else {
665 e94667b9 Mark McLoughlin
            len = vc_sendv_compat(vc, iov, iovcnt);
666 e94667b9 Mark McLoughlin
        }
667 e94667b9 Mark McLoughlin
668 e94667b9 Mark McLoughlin
        ret = (ret >= 0) ? ret : len;
669 e94667b9 Mark McLoughlin
    }
670 e94667b9 Mark McLoughlin
671 e94667b9 Mark McLoughlin
    return ret;
672 e94667b9 Mark McLoughlin
}
673 e94667b9 Mark McLoughlin
674 f3b6c7fc Mark McLoughlin
ssize_t qemu_sendv_packet_async(VLANClientState *sender,
675 f3b6c7fc Mark McLoughlin
                                const struct iovec *iov, int iovcnt,
676 f3b6c7fc Mark McLoughlin
                                NetPacketSent *sent_cb)
677 e94667b9 Mark McLoughlin
{
678 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
679 9a6ecb30 Mark McLoughlin
680 9a6ecb30 Mark McLoughlin
    if (sender->link_down || (!sender->peer && !sender->vlan)) {
681 e94667b9 Mark McLoughlin
        return calc_iov_length(iov, iovcnt);
682 e94667b9 Mark McLoughlin
    }
683 e94667b9 Mark McLoughlin
684 9a6ecb30 Mark McLoughlin
    if (sender->peer) {
685 9a6ecb30 Mark McLoughlin
        queue = sender->peer->send_queue;
686 9a6ecb30 Mark McLoughlin
    } else {
687 9a6ecb30 Mark McLoughlin
        queue = sender->vlan->send_queue;
688 9a6ecb30 Mark McLoughlin
    }
689 9a6ecb30 Mark McLoughlin
690 c0b8e49c Mark McLoughlin
    return qemu_net_queue_send_iov(queue, sender,
691 c0b8e49c Mark McLoughlin
                                   QEMU_NET_PACKET_FLAG_NONE,
692 c0b8e49c Mark McLoughlin
                                   iov, iovcnt, sent_cb);
693 fbe78f4f aliguori
}
694 fbe78f4f aliguori
695 f3b6c7fc Mark McLoughlin
ssize_t
696 f3b6c7fc Mark McLoughlin
qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt)
697 f3b6c7fc Mark McLoughlin
{
698 f3b6c7fc Mark McLoughlin
    return qemu_sendv_packet_async(vc, iov, iovcnt, NULL);
699 f3b6c7fc Mark McLoughlin
}
700 f3b6c7fc Mark McLoughlin
701 63a01ef8 aliguori
#if defined(CONFIG_SLIRP)
702 63a01ef8 aliguori
703 63a01ef8 aliguori
/* slirp network adapter */
704 63a01ef8 aliguori
705 c92ef6a2 Jan Kiszka
#define SLIRP_CFG_HOSTFWD 1
706 c92ef6a2 Jan Kiszka
#define SLIRP_CFG_LEGACY  2
707 ad196a9d Jan Kiszka
708 b8e8af38 Jan Kiszka
struct slirp_config_str {
709 b8e8af38 Jan Kiszka
    struct slirp_config_str *next;
710 ad196a9d Jan Kiszka
    int flags;
711 ad196a9d Jan Kiszka
    char str[1024];
712 c92ef6a2 Jan Kiszka
    int legacy_format;
713 b8e8af38 Jan Kiszka
};
714 b8e8af38 Jan Kiszka
715 9f8bd042 Jan Kiszka
typedef struct SlirpState {
716 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(SlirpState) entry;
717 9f8bd042 Jan Kiszka
    VLANClientState *vc;
718 9f8bd042 Jan Kiszka
    Slirp *slirp;
719 28432466 Jan Kiszka
#ifndef _WIN32
720 28432466 Jan Kiszka
    char smb_dir[128];
721 28432466 Jan Kiszka
#endif
722 9f8bd042 Jan Kiszka
} SlirpState;
723 9f8bd042 Jan Kiszka
724 ad196a9d Jan Kiszka
static struct slirp_config_str *slirp_configs;
725 ad196a9d Jan Kiszka
const char *legacy_tftp_prefix;
726 ad196a9d Jan Kiszka
const char *legacy_bootp_filename;
727 72cf2d4f Blue Swirl
static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
728 72cf2d4f Blue Swirl
    QTAILQ_HEAD_INITIALIZER(slirp_stacks);
729 63a01ef8 aliguori
730 fb12577c Markus Armbruster
static int slirp_hostfwd(SlirpState *s, const char *redir_str,
731 0752706d Markus Armbruster
                         int legacy_format);
732 fb12577c Markus Armbruster
static int slirp_guestfwd(SlirpState *s, const char *config_str,
733 3c6a0580 Jan Kiszka
                          int legacy_format);
734 ad196a9d Jan Kiszka
735 c5b76b38 Blue Swirl
#ifndef _WIN32
736 ad196a9d Jan Kiszka
static const char *legacy_smb_export;
737 ad196a9d Jan Kiszka
738 fb12577c Markus Armbruster
static int slirp_smb(SlirpState *s, const char *exported_dir,
739 0752706d Markus Armbruster
                     struct in_addr vserver_addr);
740 28432466 Jan Kiszka
static void slirp_smb_cleanup(SlirpState *s);
741 28432466 Jan Kiszka
#else
742 28432466 Jan Kiszka
static inline void slirp_smb_cleanup(SlirpState *s) { }
743 c5b76b38 Blue Swirl
#endif
744 b8e8af38 Jan Kiszka
745 9f8bd042 Jan Kiszka
int slirp_can_output(void *opaque)
746 63a01ef8 aliguori
{
747 9f8bd042 Jan Kiszka
    SlirpState *s = opaque;
748 9f8bd042 Jan Kiszka
749 9f8bd042 Jan Kiszka
    return qemu_can_send_packet(s->vc);
750 63a01ef8 aliguori
}
751 63a01ef8 aliguori
752 9f8bd042 Jan Kiszka
void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
753 63a01ef8 aliguori
{
754 9f8bd042 Jan Kiszka
    SlirpState *s = opaque;
755 9f8bd042 Jan Kiszka
756 63a01ef8 aliguori
#ifdef DEBUG_SLIRP
757 63a01ef8 aliguori
    printf("slirp output:\n");
758 63a01ef8 aliguori
    hex_dump(stdout, pkt, pkt_len);
759 63a01ef8 aliguori
#endif
760 9f8bd042 Jan Kiszka
    qemu_send_packet(s->vc, pkt, pkt_len);
761 63a01ef8 aliguori
}
762 63a01ef8 aliguori
763 4f1c942b Mark McLoughlin
static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
764 63a01ef8 aliguori
{
765 9f8bd042 Jan Kiszka
    SlirpState *s = vc->opaque;
766 9f8bd042 Jan Kiszka
767 63a01ef8 aliguori
#ifdef DEBUG_SLIRP
768 63a01ef8 aliguori
    printf("slirp input:\n");
769 63a01ef8 aliguori
    hex_dump(stdout, buf, size);
770 63a01ef8 aliguori
#endif
771 9f8bd042 Jan Kiszka
    slirp_input(s->slirp, buf, size);
772 4f1c942b Mark McLoughlin
    return size;
773 63a01ef8 aliguori
}
774 63a01ef8 aliguori
775 8d6249a7 aliguori
static void net_slirp_cleanup(VLANClientState *vc)
776 8d6249a7 aliguori
{
777 ad0d8c4c Jan Kiszka
    SlirpState *s = vc->opaque;
778 ad0d8c4c Jan Kiszka
779 ad0d8c4c Jan Kiszka
    slirp_cleanup(s->slirp);
780 28432466 Jan Kiszka
    slirp_smb_cleanup(s);
781 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&slirp_stacks, s, entry);
782 ad0d8c4c Jan Kiszka
    qemu_free(s);
783 8d6249a7 aliguori
}
784 8d6249a7 aliguori
785 fb12577c Markus Armbruster
static int net_slirp_init(VLANState *vlan, const char *model,
786 c92ef6a2 Jan Kiszka
                          const char *name, int restricted,
787 c92ef6a2 Jan Kiszka
                          const char *vnetwork, const char *vhost,
788 c92ef6a2 Jan Kiszka
                          const char *vhostname, const char *tftp_export,
789 c92ef6a2 Jan Kiszka
                          const char *bootfile, const char *vdhcp_start,
790 c92ef6a2 Jan Kiszka
                          const char *vnameserver, const char *smb_export,
791 c92ef6a2 Jan Kiszka
                          const char *vsmbserver)
792 63a01ef8 aliguori
{
793 ad0d8c4c Jan Kiszka
    /* default settings according to historic slirp */
794 8389e7f4 Anthony Liguori
    struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
795 8389e7f4 Anthony Liguori
    struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
796 ad0d8c4c Jan Kiszka
    struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
797 ad0d8c4c Jan Kiszka
    struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
798 ad0d8c4c Jan Kiszka
    struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
799 c92ef6a2 Jan Kiszka
#ifndef _WIN32
800 ad0d8c4c Jan Kiszka
    struct in_addr smbsrv = { .s_addr = 0 };
801 c92ef6a2 Jan Kiszka
#endif
802 ad0d8c4c Jan Kiszka
    SlirpState *s;
803 ad0d8c4c Jan Kiszka
    char buf[20];
804 ad0d8c4c Jan Kiszka
    uint32_t addr;
805 ad0d8c4c Jan Kiszka
    int shift;
806 ad0d8c4c Jan Kiszka
    char *end;
807 3a179c66 Markus Armbruster
    struct slirp_config_str *config;
808 ad0d8c4c Jan Kiszka
809 ad0d8c4c Jan Kiszka
    if (!tftp_export) {
810 ad0d8c4c Jan Kiszka
        tftp_export = legacy_tftp_prefix;
811 ad0d8c4c Jan Kiszka
    }
812 ad0d8c4c Jan Kiszka
    if (!bootfile) {
813 ad0d8c4c Jan Kiszka
        bootfile = legacy_bootp_filename;
814 ad0d8c4c Jan Kiszka
    }
815 c92ef6a2 Jan Kiszka
816 ad0d8c4c Jan Kiszka
    if (vnetwork) {
817 ad0d8c4c Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
818 ad0d8c4c Jan Kiszka
            if (!inet_aton(vnetwork, &net)) {
819 ad0d8c4c Jan Kiszka
                return -1;
820 ad0d8c4c Jan Kiszka
            }
821 ad0d8c4c Jan Kiszka
            addr = ntohl(net.s_addr);
822 ad0d8c4c Jan Kiszka
            if (!(addr & 0x80000000)) {
823 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xff000000); /* class A */
824 ad0d8c4c Jan Kiszka
            } else if ((addr & 0xfff00000) == 0xac100000) {
825 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
826 ad0d8c4c Jan Kiszka
            } else if ((addr & 0xc0000000) == 0x80000000) {
827 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xffff0000); /* class B */
828 ad0d8c4c Jan Kiszka
            } else if ((addr & 0xffff0000) == 0xc0a80000) {
829 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
830 ad0d8c4c Jan Kiszka
            } else if ((addr & 0xffff0000) == 0xc6120000) {
831 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
832 ad0d8c4c Jan Kiszka
            } else if ((addr & 0xe0000000) == 0xe0000000) {
833 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xffffff00); /* class C */
834 c92ef6a2 Jan Kiszka
            } else {
835 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
836 ad0d8c4c Jan Kiszka
            }
837 ad0d8c4c Jan Kiszka
        } else {
838 ad0d8c4c Jan Kiszka
            if (!inet_aton(buf, &net)) {
839 ad0d8c4c Jan Kiszka
                return -1;
840 ad0d8c4c Jan Kiszka
            }
841 ad0d8c4c Jan Kiszka
            shift = strtol(vnetwork, &end, 10);
842 ad0d8c4c Jan Kiszka
            if (*end != '\0') {
843 ad0d8c4c Jan Kiszka
                if (!inet_aton(vnetwork, &mask)) {
844 c92ef6a2 Jan Kiszka
                    return -1;
845 c92ef6a2 Jan Kiszka
                }
846 ad0d8c4c Jan Kiszka
            } else if (shift < 4 || shift > 32) {
847 ad0d8c4c Jan Kiszka
                return -1;
848 ad0d8c4c Jan Kiszka
            } else {
849 ad0d8c4c Jan Kiszka
                mask.s_addr = htonl(0xffffffff << (32 - shift));
850 c92ef6a2 Jan Kiszka
            }
851 c92ef6a2 Jan Kiszka
        }
852 ad0d8c4c Jan Kiszka
        net.s_addr &= mask.s_addr;
853 ad0d8c4c Jan Kiszka
        host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
854 ad0d8c4c Jan Kiszka
        dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
855 ad0d8c4c Jan Kiszka
        dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
856 ad0d8c4c Jan Kiszka
    }
857 c92ef6a2 Jan Kiszka
858 ad0d8c4c Jan Kiszka
    if (vhost && !inet_aton(vhost, &host)) {
859 ad0d8c4c Jan Kiszka
        return -1;
860 ad0d8c4c Jan Kiszka
    }
861 ad0d8c4c Jan Kiszka
    if ((host.s_addr & mask.s_addr) != net.s_addr) {
862 ad0d8c4c Jan Kiszka
        return -1;
863 ad0d8c4c Jan Kiszka
    }
864 c92ef6a2 Jan Kiszka
865 ad0d8c4c Jan Kiszka
    if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
866 ad0d8c4c Jan Kiszka
        return -1;
867 ad0d8c4c Jan Kiszka
    }
868 ad0d8c4c Jan Kiszka
    if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
869 ad0d8c4c Jan Kiszka
        dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
870 ad0d8c4c Jan Kiszka
        return -1;
871 ad0d8c4c Jan Kiszka
    }
872 c92ef6a2 Jan Kiszka
873 ad0d8c4c Jan Kiszka
    if (vnameserver && !inet_aton(vnameserver, &dns)) {
874 ad0d8c4c Jan Kiszka
        return -1;
875 ad0d8c4c Jan Kiszka
    }
876 ad0d8c4c Jan Kiszka
    if ((dns.s_addr & mask.s_addr) != net.s_addr ||
877 ad0d8c4c Jan Kiszka
        dns.s_addr == host.s_addr) {
878 ad0d8c4c Jan Kiszka
        return -1;
879 ad0d8c4c Jan Kiszka
    }
880 c92ef6a2 Jan Kiszka
881 c92ef6a2 Jan Kiszka
#ifndef _WIN32
882 ad0d8c4c Jan Kiszka
    if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
883 ad0d8c4c Jan Kiszka
        return -1;
884 ad0d8c4c Jan Kiszka
    }
885 c92ef6a2 Jan Kiszka
#endif
886 c92ef6a2 Jan Kiszka
887 ad0d8c4c Jan Kiszka
    s = qemu_mallocz(sizeof(SlirpState));
888 ad0d8c4c Jan Kiszka
    s->slirp = slirp_init(restricted, net, mask, host, vhostname,
889 ad0d8c4c Jan Kiszka
                          tftp_export, bootfile, dhcp, dns, s);
890 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
891 b8e8af38 Jan Kiszka
892 3a179c66 Markus Armbruster
    for (config = slirp_configs; config; config = config->next) {
893 ad0d8c4c Jan Kiszka
        if (config->flags & SLIRP_CFG_HOSTFWD) {
894 fb12577c Markus Armbruster
            if (slirp_hostfwd(s, config->str,
895 0752706d Markus Armbruster
                              config->flags & SLIRP_CFG_LEGACY) < 0)
896 0752706d Markus Armbruster
                return -1;
897 ad0d8c4c Jan Kiszka
        } else {
898 fb12577c Markus Armbruster
            if (slirp_guestfwd(s, config->str,
899 0752706d Markus Armbruster
                               config->flags & SLIRP_CFG_LEGACY) < 0)
900 0752706d Markus Armbruster
                return -1;
901 b8e8af38 Jan Kiszka
        }
902 ad0d8c4c Jan Kiszka
    }
903 b8e8af38 Jan Kiszka
#ifndef _WIN32
904 ad0d8c4c Jan Kiszka
    if (!smb_export) {
905 ad0d8c4c Jan Kiszka
        smb_export = legacy_smb_export;
906 ad0d8c4c Jan Kiszka
    }
907 ad0d8c4c Jan Kiszka
    if (smb_export) {
908 fb12577c Markus Armbruster
        if (slirp_smb(s, smb_export, smbsrv) < 0)
909 0752706d Markus Armbruster
            return -1;
910 63a01ef8 aliguori
    }
911 ad0d8c4c Jan Kiszka
#endif
912 b8e8af38 Jan Kiszka
913 bb6e6364 Mark McLoughlin
    s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_SLIRP,
914 bb6e6364 Mark McLoughlin
                                 vlan, NULL, model, name, NULL,
915 70783b9c Mark McLoughlin
                                 slirp_receive, NULL, NULL,
916 9f8bd042 Jan Kiszka
                                 net_slirp_cleanup, s);
917 fc57bc57 Jan Kiszka
    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
918 fc57bc57 Jan Kiszka
             "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n');
919 63a01ef8 aliguori
    return 0;
920 63a01ef8 aliguori
}
921 63a01ef8 aliguori
922 f13b572c Jan Kiszka
static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
923 f13b572c Jan Kiszka
                                const char *stack)
924 f13b572c Jan Kiszka
{
925 f13b572c Jan Kiszka
    VLANClientState *vc;
926 f13b572c Jan Kiszka
927 f13b572c Jan Kiszka
    if (vlan) {
928 f13b572c Jan Kiszka
        vc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack);
929 f13b572c Jan Kiszka
        if (!vc) {
930 f13b572c Jan Kiszka
            return NULL;
931 f13b572c Jan Kiszka
        }
932 f13b572c Jan Kiszka
        if (strcmp(vc->model, "user")) {
933 f13b572c Jan Kiszka
            monitor_printf(mon, "invalid device specified\n");
934 f13b572c Jan Kiszka
            return NULL;
935 f13b572c Jan Kiszka
        }
936 f13b572c Jan Kiszka
        return vc->opaque;
937 f13b572c Jan Kiszka
    } else {
938 72cf2d4f Blue Swirl
        if (QTAILQ_EMPTY(&slirp_stacks)) {
939 f13b572c Jan Kiszka
            monitor_printf(mon, "user mode network stack not in use\n");
940 f13b572c Jan Kiszka
            return NULL;
941 f13b572c Jan Kiszka
        }
942 72cf2d4f Blue Swirl
        return QTAILQ_FIRST(&slirp_stacks);
943 f13b572c Jan Kiszka
    }
944 f13b572c Jan Kiszka
}
945 f13b572c Jan Kiszka
946 1d4daa91 Luiz Capitulino
void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
947 c1261d8d Alexander Graf
{
948 3c6a0580 Jan Kiszka
    struct in_addr host_addr = { .s_addr = INADDR_ANY };
949 c1261d8d Alexander Graf
    int host_port;
950 c1261d8d Alexander Graf
    char buf[256] = "";
951 f13b572c Jan Kiszka
    const char *src_str, *p;
952 f13b572c Jan Kiszka
    SlirpState *s;
953 c1261d8d Alexander Graf
    int is_udp = 0;
954 9c12a6f2 Jan Kiszka
    int err;
955 1d4daa91 Luiz Capitulino
    const char *arg1 = qdict_get_str(qdict, "arg1");
956 1d4daa91 Luiz Capitulino
    const char *arg2 = qdict_get_try_str(qdict, "arg2");
957 1d4daa91 Luiz Capitulino
    const char *arg3 = qdict_get_try_str(qdict, "arg3");
958 c1261d8d Alexander Graf
959 f13b572c Jan Kiszka
    if (arg2) {
960 f13b572c Jan Kiszka
        s = slirp_lookup(mon, arg1, arg2);
961 f13b572c Jan Kiszka
        src_str = arg3;
962 f13b572c Jan Kiszka
    } else {
963 f13b572c Jan Kiszka
        s = slirp_lookup(mon, NULL, NULL);
964 f13b572c Jan Kiszka
        src_str = arg1;
965 f13b572c Jan Kiszka
    }
966 f13b572c Jan Kiszka
    if (!s) {
967 c1261d8d Alexander Graf
        return;
968 f3546deb Jan Kiszka
    }
969 c1261d8d Alexander Graf
970 3c6a0580 Jan Kiszka
    if (!src_str || !src_str[0])
971 c1261d8d Alexander Graf
        goto fail_syntax;
972 c1261d8d Alexander Graf
973 f13b572c Jan Kiszka
    p = src_str;
974 c1261d8d Alexander Graf
    get_str_sep(buf, sizeof(buf), &p, ':');
975 c1261d8d Alexander Graf
976 c1261d8d Alexander Graf
    if (!strcmp(buf, "tcp") || buf[0] == '\0') {
977 c1261d8d Alexander Graf
        is_udp = 0;
978 c1261d8d Alexander Graf
    } else if (!strcmp(buf, "udp")) {
979 c1261d8d Alexander Graf
        is_udp = 1;
980 c1261d8d Alexander Graf
    } else {
981 c1261d8d Alexander Graf
        goto fail_syntax;
982 c1261d8d Alexander Graf
    }
983 c1261d8d Alexander Graf
984 3c6a0580 Jan Kiszka
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
985 3c6a0580 Jan Kiszka
        goto fail_syntax;
986 3c6a0580 Jan Kiszka
    }
987 3c6a0580 Jan Kiszka
    if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
988 3c6a0580 Jan Kiszka
        goto fail_syntax;
989 3c6a0580 Jan Kiszka
    }
990 3c6a0580 Jan Kiszka
991 c1261d8d Alexander Graf
    host_port = atoi(p);
992 c1261d8d Alexander Graf
993 72cf2d4f Blue Swirl
    err = slirp_remove_hostfwd(QTAILQ_FIRST(&slirp_stacks)->slirp, is_udp,
994 9f8bd042 Jan Kiszka
                               host_addr, host_port);
995 c1261d8d Alexander Graf
996 9c12a6f2 Jan Kiszka
    monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
997 9c12a6f2 Jan Kiszka
                   err ? "removed" : "not found");
998 c1261d8d Alexander Graf
    return;
999 c1261d8d Alexander Graf
1000 c1261d8d Alexander Graf
 fail_syntax:
1001 c1261d8d Alexander Graf
    monitor_printf(mon, "invalid format\n");
1002 c1261d8d Alexander Graf
}
1003 c1261d8d Alexander Graf
1004 fb12577c Markus Armbruster
static int slirp_hostfwd(SlirpState *s, const char *redir_str,
1005 0752706d Markus Armbruster
                         int legacy_format)
1006 63a01ef8 aliguori
{
1007 3c6a0580 Jan Kiszka
    struct in_addr host_addr = { .s_addr = INADDR_ANY };
1008 c92ef6a2 Jan Kiszka
    struct in_addr guest_addr = { .s_addr = 0 };
1009 63a01ef8 aliguori
    int host_port, guest_port;
1010 b8e8af38 Jan Kiszka
    const char *p;
1011 c92ef6a2 Jan Kiszka
    char buf[256];
1012 b8e8af38 Jan Kiszka
    int is_udp;
1013 c92ef6a2 Jan Kiszka
    char *end;
1014 1c6ed9f3 Alexander Graf
1015 63a01ef8 aliguori
    p = redir_str;
1016 f13b572c Jan Kiszka
    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1017 d4ebe193 aliguori
        goto fail_syntax;
1018 b8e8af38 Jan Kiszka
    }
1019 d4ebe193 aliguori
    if (!strcmp(buf, "tcp") || buf[0] == '\0') {
1020 63a01ef8 aliguori
        is_udp = 0;
1021 63a01ef8 aliguori
    } else if (!strcmp(buf, "udp")) {
1022 63a01ef8 aliguori
        is_udp = 1;
1023 63a01ef8 aliguori
    } else {
1024 d4ebe193 aliguori
        goto fail_syntax;
1025 63a01ef8 aliguori
    }
1026 63a01ef8 aliguori
1027 3c6a0580 Jan Kiszka
    if (!legacy_format) {
1028 3c6a0580 Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1029 3c6a0580 Jan Kiszka
            goto fail_syntax;
1030 3c6a0580 Jan Kiszka
        }
1031 3c6a0580 Jan Kiszka
        if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
1032 3c6a0580 Jan Kiszka
            goto fail_syntax;
1033 3c6a0580 Jan Kiszka
        }
1034 3c6a0580 Jan Kiszka
    }
1035 3c6a0580 Jan Kiszka
1036 3c6a0580 Jan Kiszka
    if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
1037 d4ebe193 aliguori
        goto fail_syntax;
1038 b8e8af38 Jan Kiszka
    }
1039 c92ef6a2 Jan Kiszka
    host_port = strtol(buf, &end, 0);
1040 c92ef6a2 Jan Kiszka
    if (*end != '\0' || host_port < 1 || host_port > 65535) {
1041 d4ebe193 aliguori
        goto fail_syntax;
1042 b8e8af38 Jan Kiszka
    }
1043 63a01ef8 aliguori
1044 b8e8af38 Jan Kiszka
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1045 d4ebe193 aliguori
        goto fail_syntax;
1046 b8e8af38 Jan Kiszka
    }
1047 c92ef6a2 Jan Kiszka
    if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
1048 d4ebe193 aliguori
        goto fail_syntax;
1049 b8e8af38 Jan Kiszka
    }
1050 63a01ef8 aliguori
1051 c92ef6a2 Jan Kiszka
    guest_port = strtol(p, &end, 0);
1052 c92ef6a2 Jan Kiszka
    if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
1053 d4ebe193 aliguori
        goto fail_syntax;
1054 b8e8af38 Jan Kiszka
    }
1055 63a01ef8 aliguori
1056 9f8bd042 Jan Kiszka
    if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
1057 9f8bd042 Jan Kiszka
                          guest_port) < 0) {
1058 fb12577c Markus Armbruster
        qemu_error("could not set up host forwarding rule '%s'\n",
1059 fb12577c Markus Armbruster
                   redir_str);
1060 0752706d Markus Armbruster
        return -1;
1061 63a01ef8 aliguori
    }
1062 0752706d Markus Armbruster
    return 0;
1063 d4ebe193 aliguori
1064 d4ebe193 aliguori
 fail_syntax:
1065 fb12577c Markus Armbruster
    qemu_error("invalid host forwarding rule '%s'\n", redir_str);
1066 0752706d Markus Armbruster
    return -1;
1067 63a01ef8 aliguori
}
1068 63a01ef8 aliguori
1069 1d4daa91 Luiz Capitulino
void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict)
1070 b8e8af38 Jan Kiszka
{
1071 f13b572c Jan Kiszka
    const char *redir_str;
1072 f13b572c Jan Kiszka
    SlirpState *s;
1073 1d4daa91 Luiz Capitulino
    const char *arg1 = qdict_get_str(qdict, "arg1");
1074 1d4daa91 Luiz Capitulino
    const char *arg2 = qdict_get_try_str(qdict, "arg2");
1075 1d4daa91 Luiz Capitulino
    const char *arg3 = qdict_get_try_str(qdict, "arg3");
1076 f13b572c Jan Kiszka
1077 f13b572c Jan Kiszka
    if (arg2) {
1078 f13b572c Jan Kiszka
        s = slirp_lookup(mon, arg1, arg2);
1079 f13b572c Jan Kiszka
        redir_str = arg3;
1080 f13b572c Jan Kiszka
    } else {
1081 f13b572c Jan Kiszka
        s = slirp_lookup(mon, NULL, NULL);
1082 f13b572c Jan Kiszka
        redir_str = arg1;
1083 f13b572c Jan Kiszka
    }
1084 f13b572c Jan Kiszka
    if (s) {
1085 fb12577c Markus Armbruster
        slirp_hostfwd(s, redir_str, 0);
1086 b8e8af38 Jan Kiszka
    }
1087 b8e8af38 Jan Kiszka
1088 f3546deb Jan Kiszka
}
1089 f3546deb Jan Kiszka
1090 0752706d Markus Armbruster
int net_slirp_redir(const char *redir_str)
1091 f3546deb Jan Kiszka
{
1092 f3546deb Jan Kiszka
    struct slirp_config_str *config;
1093 f3546deb Jan Kiszka
1094 72cf2d4f Blue Swirl
    if (QTAILQ_EMPTY(&slirp_stacks)) {
1095 f3546deb Jan Kiszka
        config = qemu_malloc(sizeof(*config));
1096 f3546deb Jan Kiszka
        pstrcpy(config->str, sizeof(config->str), redir_str);
1097 3c6a0580 Jan Kiszka
        config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
1098 f3546deb Jan Kiszka
        config->next = slirp_configs;
1099 f3546deb Jan Kiszka
        slirp_configs = config;
1100 0752706d Markus Armbruster
        return 0;
1101 b8e8af38 Jan Kiszka
    }
1102 b8e8af38 Jan Kiszka
1103 fb12577c Markus Armbruster
    return slirp_hostfwd(QTAILQ_FIRST(&slirp_stacks), redir_str, 1);
1104 b8e8af38 Jan Kiszka
}
1105 b8e8af38 Jan Kiszka
1106 63a01ef8 aliguori
#ifndef _WIN32
1107 63a01ef8 aliguori
1108 63a01ef8 aliguori
/* automatic user mode samba server configuration */
1109 28432466 Jan Kiszka
static void slirp_smb_cleanup(SlirpState *s)
1110 63a01ef8 aliguori
{
1111 28432466 Jan Kiszka
    char cmd[128];
1112 09c18925 Jan Kiszka
1113 28432466 Jan Kiszka
    if (s->smb_dir[0] != '\0') {
1114 28432466 Jan Kiszka
        snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
1115 28432466 Jan Kiszka
        system(cmd);
1116 28432466 Jan Kiszka
        s->smb_dir[0] = '\0';
1117 28432466 Jan Kiszka
    }
1118 63a01ef8 aliguori
}
1119 63a01ef8 aliguori
1120 fb12577c Markus Armbruster
static int slirp_smb(SlirpState* s, const char *exported_dir,
1121 0752706d Markus Armbruster
                     struct in_addr vserver_addr)
1122 63a01ef8 aliguori
{
1123 28432466 Jan Kiszka
    static int instance;
1124 28432466 Jan Kiszka
    char smb_conf[128];
1125 28432466 Jan Kiszka
    char smb_cmdline[128];
1126 63a01ef8 aliguori
    FILE *f;
1127 63a01ef8 aliguori
1128 28432466 Jan Kiszka
    snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
1129 28432466 Jan Kiszka
             (long)getpid(), instance++);
1130 28432466 Jan Kiszka
    if (mkdir(s->smb_dir, 0700) < 0) {
1131 fb12577c Markus Armbruster
        qemu_error("could not create samba server dir '%s'\n", s->smb_dir);
1132 0752706d Markus Armbruster
        return -1;
1133 63a01ef8 aliguori
    }
1134 28432466 Jan Kiszka
    snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
1135 63a01ef8 aliguori
1136 63a01ef8 aliguori
    f = fopen(smb_conf, "w");
1137 63a01ef8 aliguori
    if (!f) {
1138 28432466 Jan Kiszka
        slirp_smb_cleanup(s);
1139 fb12577c Markus Armbruster
        qemu_error("could not create samba server configuration file '%s'\n",
1140 fb12577c Markus Armbruster
                   smb_conf);
1141 0752706d Markus Armbruster
        return -1;
1142 63a01ef8 aliguori
    }
1143 63a01ef8 aliguori
    fprintf(f,
1144 63a01ef8 aliguori
            "[global]\n"
1145 63a01ef8 aliguori
            "private dir=%s\n"
1146 63a01ef8 aliguori
            "smb ports=0\n"
1147 63a01ef8 aliguori
            "socket address=127.0.0.1\n"
1148 63a01ef8 aliguori
            "pid directory=%s\n"
1149 63a01ef8 aliguori
            "lock directory=%s\n"
1150 63a01ef8 aliguori
            "log file=%s/log.smbd\n"
1151 63a01ef8 aliguori
            "smb passwd file=%s/smbpasswd\n"
1152 63a01ef8 aliguori
            "security = share\n"
1153 63a01ef8 aliguori
            "[qemu]\n"
1154 63a01ef8 aliguori
            "path=%s\n"
1155 63a01ef8 aliguori
            "read only=no\n"
1156 63a01ef8 aliguori
            "guest ok=yes\n",
1157 28432466 Jan Kiszka
            s->smb_dir,
1158 28432466 Jan Kiszka
            s->smb_dir,
1159 28432466 Jan Kiszka
            s->smb_dir,
1160 28432466 Jan Kiszka
            s->smb_dir,
1161 28432466 Jan Kiszka
            s->smb_dir,
1162 63a01ef8 aliguori
            exported_dir
1163 63a01ef8 aliguori
            );
1164 63a01ef8 aliguori
    fclose(f);
1165 63a01ef8 aliguori
1166 63a01ef8 aliguori
    snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
1167 63a01ef8 aliguori
             SMBD_COMMAND, smb_conf);
1168 63a01ef8 aliguori
1169 bb53fc53 Jan Kiszka
    if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0) {
1170 28432466 Jan Kiszka
        slirp_smb_cleanup(s);
1171 fb12577c Markus Armbruster
        qemu_error("conflicting/invalid smbserver address\n");
1172 0752706d Markus Armbruster
        return -1;
1173 c92ef6a2 Jan Kiszka
    }
1174 0752706d Markus Armbruster
    return 0;
1175 63a01ef8 aliguori
}
1176 63a01ef8 aliguori
1177 ad196a9d Jan Kiszka
/* automatic user mode samba server configuration (legacy interface) */
1178 0752706d Markus Armbruster
int net_slirp_smb(const char *exported_dir)
1179 b8e8af38 Jan Kiszka
{
1180 c92ef6a2 Jan Kiszka
    struct in_addr vserver_addr = { .s_addr = 0 };
1181 c92ef6a2 Jan Kiszka
1182 ad196a9d Jan Kiszka
    if (legacy_smb_export) {
1183 b8e8af38 Jan Kiszka
        fprintf(stderr, "-smb given twice\n");
1184 0752706d Markus Armbruster
        return -1;
1185 b8e8af38 Jan Kiszka
    }
1186 ad196a9d Jan Kiszka
    legacy_smb_export = exported_dir;
1187 72cf2d4f Blue Swirl
    if (!QTAILQ_EMPTY(&slirp_stacks)) {
1188 fb12577c Markus Armbruster
        return slirp_smb(QTAILQ_FIRST(&slirp_stacks), exported_dir,
1189 0752706d Markus Armbruster
                         vserver_addr);
1190 b8e8af38 Jan Kiszka
    }
1191 0752706d Markus Armbruster
    return 0;
1192 b8e8af38 Jan Kiszka
}
1193 b8e8af38 Jan Kiszka
1194 63a01ef8 aliguori
#endif /* !defined(_WIN32) */
1195 b8e8af38 Jan Kiszka
1196 c92ef6a2 Jan Kiszka
struct GuestFwd {
1197 8ca9217d aliguori
    CharDriverState *hd;
1198 c92ef6a2 Jan Kiszka
    struct in_addr server;
1199 8ca9217d aliguori
    int port;
1200 9f8bd042 Jan Kiszka
    Slirp *slirp;
1201 511d2b14 blueswir1
};
1202 8ca9217d aliguori
1203 c92ef6a2 Jan Kiszka
static int guestfwd_can_read(void *opaque)
1204 8ca9217d aliguori
{
1205 c92ef6a2 Jan Kiszka
    struct GuestFwd *fwd = opaque;
1206 9f8bd042 Jan Kiszka
    return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
1207 8ca9217d aliguori
}
1208 8ca9217d aliguori
1209 c92ef6a2 Jan Kiszka
static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
1210 8ca9217d aliguori
{
1211 c92ef6a2 Jan Kiszka
    struct GuestFwd *fwd = opaque;
1212 9f8bd042 Jan Kiszka
    slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
1213 8ca9217d aliguori
}
1214 8ca9217d aliguori
1215 fb12577c Markus Armbruster
static int slirp_guestfwd(SlirpState *s, const char *config_str,
1216 0752706d Markus Armbruster
                          int legacy_format)
1217 ad196a9d Jan Kiszka
{
1218 c92ef6a2 Jan Kiszka
    struct in_addr server = { .s_addr = 0 };
1219 c92ef6a2 Jan Kiszka
    struct GuestFwd *fwd;
1220 c92ef6a2 Jan Kiszka
    const char *p;
1221 c92ef6a2 Jan Kiszka
    char buf[128];
1222 c92ef6a2 Jan Kiszka
    char *end;
1223 ad196a9d Jan Kiszka
    int port;
1224 ad196a9d Jan Kiszka
1225 c92ef6a2 Jan Kiszka
    p = config_str;
1226 c92ef6a2 Jan Kiszka
    if (legacy_format) {
1227 c92ef6a2 Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1228 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1229 c92ef6a2 Jan Kiszka
        }
1230 c92ef6a2 Jan Kiszka
    } else {
1231 c92ef6a2 Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1232 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1233 c92ef6a2 Jan Kiszka
        }
1234 c92ef6a2 Jan Kiszka
        if (strcmp(buf, "tcp") && buf[0] != '\0') {
1235 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1236 c92ef6a2 Jan Kiszka
        }
1237 c92ef6a2 Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
1238 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1239 c92ef6a2 Jan Kiszka
        }
1240 c92ef6a2 Jan Kiszka
        if (buf[0] != '\0' && !inet_aton(buf, &server)) {
1241 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1242 c92ef6a2 Jan Kiszka
        }
1243 c92ef6a2 Jan Kiszka
        if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
1244 c92ef6a2 Jan Kiszka
            goto fail_syntax;
1245 c92ef6a2 Jan Kiszka
        }
1246 c92ef6a2 Jan Kiszka
    }
1247 c92ef6a2 Jan Kiszka
    port = strtol(buf, &end, 10);
1248 c92ef6a2 Jan Kiszka
    if (*end != '\0' || port < 1 || port > 65535) {
1249 c92ef6a2 Jan Kiszka
        goto fail_syntax;
1250 ad196a9d Jan Kiszka
    }
1251 ad196a9d Jan Kiszka
1252 c92ef6a2 Jan Kiszka
    fwd = qemu_malloc(sizeof(struct GuestFwd));
1253 c92ef6a2 Jan Kiszka
    snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
1254 c92ef6a2 Jan Kiszka
    fwd->hd = qemu_chr_open(buf, p, NULL);
1255 c92ef6a2 Jan Kiszka
    if (!fwd->hd) {
1256 fb12577c Markus Armbruster
        qemu_error("could not open guest forwarding device '%s'\n", buf);
1257 c92ef6a2 Jan Kiszka
        qemu_free(fwd);
1258 0752706d Markus Armbruster
        return -1;
1259 ad196a9d Jan Kiszka
    }
1260 ad196a9d Jan Kiszka
1261 bb53fc53 Jan Kiszka
    if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
1262 fb12577c Markus Armbruster
        qemu_error("conflicting/invalid host:port in guest forwarding "
1263 fb12577c Markus Armbruster
                   "rule '%s'\n", config_str);
1264 c92ef6a2 Jan Kiszka
        qemu_free(fwd);
1265 0752706d Markus Armbruster
        return -1;
1266 c92ef6a2 Jan Kiszka
    }
1267 bb53fc53 Jan Kiszka
    fwd->server = server;
1268 bb53fc53 Jan Kiszka
    fwd->port = port;
1269 bb53fc53 Jan Kiszka
    fwd->slirp = s->slirp;
1270 bb53fc53 Jan Kiszka
1271 c92ef6a2 Jan Kiszka
    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
1272 c92ef6a2 Jan Kiszka
                          NULL, fwd);
1273 0752706d Markus Armbruster
    return 0;
1274 c92ef6a2 Jan Kiszka
1275 c92ef6a2 Jan Kiszka
 fail_syntax:
1276 fb12577c Markus Armbruster
    qemu_error("invalid guest forwarding rule '%s'\n", config_str);
1277 0752706d Markus Armbruster
    return -1;
1278 ad196a9d Jan Kiszka
}
1279 ad196a9d Jan Kiszka
1280 6dbe553f Jan Kiszka
void do_info_usernet(Monitor *mon)
1281 6dbe553f Jan Kiszka
{
1282 b1c99fcd Jan Kiszka
    SlirpState *s;
1283 9f8bd042 Jan Kiszka
1284 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(s, &slirp_stacks, entry) {
1285 b1c99fcd Jan Kiszka
        monitor_printf(mon, "VLAN %d (%s):\n", s->vc->vlan->id, s->vc->name);
1286 b1c99fcd Jan Kiszka
        slirp_connection_info(s->slirp, mon);
1287 9f8bd042 Jan Kiszka
    }
1288 6dbe553f Jan Kiszka
}
1289 6dbe553f Jan Kiszka
1290 63a01ef8 aliguori
#endif /* CONFIG_SLIRP */
1291 63a01ef8 aliguori
1292 63a01ef8 aliguori
#if defined(CONFIG_VDE)
1293 63a01ef8 aliguori
typedef struct VDEState {
1294 63a01ef8 aliguori
    VLANClientState *vc;
1295 63a01ef8 aliguori
    VDECONN *vde;
1296 63a01ef8 aliguori
} VDEState;
1297 63a01ef8 aliguori
1298 63a01ef8 aliguori
static void vde_to_qemu(void *opaque)
1299 63a01ef8 aliguori
{
1300 63a01ef8 aliguori
    VDEState *s = opaque;
1301 63a01ef8 aliguori
    uint8_t buf[4096];
1302 63a01ef8 aliguori
    int size;
1303 63a01ef8 aliguori
1304 cc63bb0f Paul Brook
    size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0);
1305 63a01ef8 aliguori
    if (size > 0) {
1306 63a01ef8 aliguori
        qemu_send_packet(s->vc, buf, size);
1307 63a01ef8 aliguori
    }
1308 63a01ef8 aliguori
}
1309 63a01ef8 aliguori
1310 4f1c942b Mark McLoughlin
static ssize_t vde_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
1311 63a01ef8 aliguori
{
1312 e3f5ec2b Mark McLoughlin
    VDEState *s = vc->opaque;
1313 068daedd Anthony Liguori
    ssize_t ret;
1314 4f1c942b Mark McLoughlin
1315 4f1c942b Mark McLoughlin
    do {
1316 4f1c942b Mark McLoughlin
      ret = vde_send(s->vde, (const char *)buf, size, 0);
1317 4f1c942b Mark McLoughlin
    } while (ret < 0 && errno == EINTR);
1318 4f1c942b Mark McLoughlin
1319 4f1c942b Mark McLoughlin
    return ret;
1320 63a01ef8 aliguori
}
1321 63a01ef8 aliguori
1322 b946a153 aliguori
static void vde_cleanup(VLANClientState *vc)
1323 b946a153 aliguori
{
1324 b946a153 aliguori
    VDEState *s = vc->opaque;
1325 b946a153 aliguori
    qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL);
1326 b946a153 aliguori
    vde_close(s->vde);
1327 b946a153 aliguori
    qemu_free(s);
1328 b946a153 aliguori
}
1329 b946a153 aliguori
1330 7a9f6e4a aliguori
static int net_vde_init(VLANState *vlan, const char *model,
1331 7a9f6e4a aliguori
                        const char *name, const char *sock,
1332 bf38c1a0 aliguori
                        int port, const char *group, int mode)
1333 63a01ef8 aliguori
{
1334 63a01ef8 aliguori
    VDEState *s;
1335 dd51058d Mark McLoughlin
    char *init_group = (char *)group;
1336 dd51058d Mark McLoughlin
    char *init_sock = (char *)sock;
1337 63a01ef8 aliguori
1338 63a01ef8 aliguori
    struct vde_open_args args = {
1339 63a01ef8 aliguori
        .port = port,
1340 63a01ef8 aliguori
        .group = init_group,
1341 63a01ef8 aliguori
        .mode = mode,
1342 63a01ef8 aliguori
    };
1343 63a01ef8 aliguori
1344 63a01ef8 aliguori
    s = qemu_mallocz(sizeof(VDEState));
1345 cc63bb0f Paul Brook
    s->vde = vde_open(init_sock, (char *)"QEMU", &args);
1346 63a01ef8 aliguori
    if (!s->vde){
1347 63a01ef8 aliguori
        free(s);
1348 63a01ef8 aliguori
        return -1;
1349 63a01ef8 aliguori
    }
1350 bb6e6364 Mark McLoughlin
    s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_VDE,
1351 bb6e6364 Mark McLoughlin
                                 vlan, NULL, model, name, NULL,
1352 70783b9c Mark McLoughlin
                                 vde_receive, NULL, NULL,
1353 283c7c63 Mark McLoughlin
                                 vde_cleanup, s);
1354 63a01ef8 aliguori
    qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
1355 7cb7434b aliguori
    snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
1356 63a01ef8 aliguori
             sock, vde_datafd(s->vde));
1357 63a01ef8 aliguori
    return 0;
1358 63a01ef8 aliguori
}
1359 63a01ef8 aliguori
#endif
1360 63a01ef8 aliguori
1361 63a01ef8 aliguori
/* network connection */
1362 63a01ef8 aliguori
typedef struct NetSocketState {
1363 63a01ef8 aliguori
    VLANClientState *vc;
1364 63a01ef8 aliguori
    int fd;
1365 63a01ef8 aliguori
    int state; /* 0 = getting length, 1 = getting data */
1366 abcd2baa aliguori
    unsigned int index;
1367 abcd2baa aliguori
    unsigned int packet_len;
1368 63a01ef8 aliguori
    uint8_t buf[4096];
1369 63a01ef8 aliguori
    struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
1370 63a01ef8 aliguori
} NetSocketState;
1371 63a01ef8 aliguori
1372 63a01ef8 aliguori
typedef struct NetSocketListenState {
1373 63a01ef8 aliguori
    VLANState *vlan;
1374 bf38c1a0 aliguori
    char *model;
1375 7a9f6e4a aliguori
    char *name;
1376 63a01ef8 aliguori
    int fd;
1377 63a01ef8 aliguori
} NetSocketListenState;
1378 63a01ef8 aliguori
1379 63a01ef8 aliguori
/* XXX: we consider we can send the whole packet without blocking */
1380 4f1c942b Mark McLoughlin
static ssize_t net_socket_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
1381 63a01ef8 aliguori
{
1382 e3f5ec2b Mark McLoughlin
    NetSocketState *s = vc->opaque;
1383 63a01ef8 aliguori
    uint32_t len;
1384 63a01ef8 aliguori
    len = htonl(size);
1385 63a01ef8 aliguori
1386 63a01ef8 aliguori
    send_all(s->fd, (const uint8_t *)&len, sizeof(len));
1387 4f1c942b Mark McLoughlin
    return send_all(s->fd, buf, size);
1388 63a01ef8 aliguori
}
1389 63a01ef8 aliguori
1390 4f1c942b Mark McLoughlin
static ssize_t net_socket_receive_dgram(VLANClientState *vc, const uint8_t *buf, size_t size)
1391 63a01ef8 aliguori
{
1392 e3f5ec2b Mark McLoughlin
    NetSocketState *s = vc->opaque;
1393 4f1c942b Mark McLoughlin
1394 70503264 Stefan Weil
    return sendto(s->fd, (const void *)buf, size, 0,
1395 4f1c942b Mark McLoughlin
                  (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
1396 63a01ef8 aliguori
}
1397 63a01ef8 aliguori
1398 63a01ef8 aliguori
static void net_socket_send(void *opaque)
1399 63a01ef8 aliguori
{
1400 63a01ef8 aliguori
    NetSocketState *s = opaque;
1401 abcd2baa aliguori
    int size, err;
1402 abcd2baa aliguori
    unsigned l;
1403 63a01ef8 aliguori
    uint8_t buf1[4096];
1404 63a01ef8 aliguori
    const uint8_t *buf;
1405 63a01ef8 aliguori
1406 c5b76b38 Blue Swirl
    size = recv(s->fd, (void *)buf1, sizeof(buf1), 0);
1407 63a01ef8 aliguori
    if (size < 0) {
1408 63a01ef8 aliguori
        err = socket_error();
1409 63a01ef8 aliguori
        if (err != EWOULDBLOCK)
1410 63a01ef8 aliguori
            goto eoc;
1411 63a01ef8 aliguori
    } else if (size == 0) {
1412 63a01ef8 aliguori
        /* end of connection */
1413 63a01ef8 aliguori
    eoc:
1414 63a01ef8 aliguori
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
1415 63a01ef8 aliguori
        closesocket(s->fd);
1416 63a01ef8 aliguori
        return;
1417 63a01ef8 aliguori
    }
1418 63a01ef8 aliguori
    buf = buf1;
1419 63a01ef8 aliguori
    while (size > 0) {
1420 63a01ef8 aliguori
        /* reassemble a packet from the network */
1421 63a01ef8 aliguori
        switch(s->state) {
1422 63a01ef8 aliguori
        case 0:
1423 63a01ef8 aliguori
            l = 4 - s->index;
1424 63a01ef8 aliguori
            if (l > size)
1425 63a01ef8 aliguori
                l = size;
1426 63a01ef8 aliguori
            memcpy(s->buf + s->index, buf, l);
1427 63a01ef8 aliguori
            buf += l;
1428 63a01ef8 aliguori
            size -= l;
1429 63a01ef8 aliguori
            s->index += l;
1430 63a01ef8 aliguori
            if (s->index == 4) {
1431 63a01ef8 aliguori
                /* got length */
1432 63a01ef8 aliguori
                s->packet_len = ntohl(*(uint32_t *)s->buf);
1433 63a01ef8 aliguori
                s->index = 0;
1434 63a01ef8 aliguori
                s->state = 1;
1435 63a01ef8 aliguori
            }
1436 63a01ef8 aliguori
            break;
1437 63a01ef8 aliguori
        case 1:
1438 63a01ef8 aliguori
            l = s->packet_len - s->index;
1439 63a01ef8 aliguori
            if (l > size)
1440 63a01ef8 aliguori
                l = size;
1441 abcd2baa aliguori
            if (s->index + l <= sizeof(s->buf)) {
1442 abcd2baa aliguori
                memcpy(s->buf + s->index, buf, l);
1443 abcd2baa aliguori
            } else {
1444 abcd2baa aliguori
                fprintf(stderr, "serious error: oversized packet received,"
1445 abcd2baa aliguori
                    "connection terminated.\n");
1446 abcd2baa aliguori
                s->state = 0;
1447 abcd2baa aliguori
                goto eoc;
1448 abcd2baa aliguori
            }
1449 abcd2baa aliguori
1450 63a01ef8 aliguori
            s->index += l;
1451 63a01ef8 aliguori
            buf += l;
1452 63a01ef8 aliguori
            size -= l;
1453 63a01ef8 aliguori
            if (s->index >= s->packet_len) {
1454 63a01ef8 aliguori
                qemu_send_packet(s->vc, s->buf, s->packet_len);
1455 63a01ef8 aliguori
                s->index = 0;
1456 63a01ef8 aliguori
                s->state = 0;
1457 63a01ef8 aliguori
            }
1458 63a01ef8 aliguori
            break;
1459 63a01ef8 aliguori
        }
1460 63a01ef8 aliguori
    }
1461 63a01ef8 aliguori
}
1462 63a01ef8 aliguori
1463 63a01ef8 aliguori
static void net_socket_send_dgram(void *opaque)
1464 63a01ef8 aliguori
{
1465 63a01ef8 aliguori
    NetSocketState *s = opaque;
1466 63a01ef8 aliguori
    int size;
1467 63a01ef8 aliguori
1468 c5b76b38 Blue Swirl
    size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
1469 63a01ef8 aliguori
    if (size < 0)
1470 63a01ef8 aliguori
        return;
1471 63a01ef8 aliguori
    if (size == 0) {
1472 63a01ef8 aliguori
        /* end of connection */
1473 63a01ef8 aliguori
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
1474 63a01ef8 aliguori
        return;
1475 63a01ef8 aliguori
    }
1476 63a01ef8 aliguori
    qemu_send_packet(s->vc, s->buf, size);
1477 63a01ef8 aliguori
}
1478 63a01ef8 aliguori
1479 63a01ef8 aliguori
static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
1480 63a01ef8 aliguori
{
1481 63a01ef8 aliguori
    struct ip_mreq imr;
1482 63a01ef8 aliguori
    int fd;
1483 63a01ef8 aliguori
    int val, ret;
1484 63a01ef8 aliguori
    if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
1485 63a01ef8 aliguori
        fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
1486 63a01ef8 aliguori
                inet_ntoa(mcastaddr->sin_addr),
1487 63a01ef8 aliguori
                (int)ntohl(mcastaddr->sin_addr.s_addr));
1488 63a01ef8 aliguori
        return -1;
1489 63a01ef8 aliguori
1490 63a01ef8 aliguori
    }
1491 63a01ef8 aliguori
    fd = socket(PF_INET, SOCK_DGRAM, 0);
1492 63a01ef8 aliguori
    if (fd < 0) {
1493 63a01ef8 aliguori
        perror("socket(PF_INET, SOCK_DGRAM)");
1494 63a01ef8 aliguori
        return -1;
1495 63a01ef8 aliguori
    }
1496 63a01ef8 aliguori
1497 63a01ef8 aliguori
    val = 1;
1498 63a01ef8 aliguori
    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1499 63a01ef8 aliguori
                   (const char *)&val, sizeof(val));
1500 63a01ef8 aliguori
    if (ret < 0) {
1501 63a01ef8 aliguori
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
1502 63a01ef8 aliguori
        goto fail;
1503 63a01ef8 aliguori
    }
1504 63a01ef8 aliguori
1505 63a01ef8 aliguori
    ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
1506 63a01ef8 aliguori
    if (ret < 0) {
1507 63a01ef8 aliguori
        perror("bind");
1508 63a01ef8 aliguori
        goto fail;
1509 63a01ef8 aliguori
    }
1510 63a01ef8 aliguori
1511 63a01ef8 aliguori
    /* Add host to multicast group */
1512 63a01ef8 aliguori
    imr.imr_multiaddr = mcastaddr->sin_addr;
1513 63a01ef8 aliguori
    imr.imr_interface.s_addr = htonl(INADDR_ANY);
1514 63a01ef8 aliguori
1515 63a01ef8 aliguori
    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1516 63a01ef8 aliguori
                     (const char *)&imr, sizeof(struct ip_mreq));
1517 63a01ef8 aliguori
    if (ret < 0) {
1518 63a01ef8 aliguori
        perror("setsockopt(IP_ADD_MEMBERSHIP)");
1519 63a01ef8 aliguori
        goto fail;
1520 63a01ef8 aliguori
    }
1521 63a01ef8 aliguori
1522 63a01ef8 aliguori
    /* Force mcast msgs to loopback (eg. several QEMUs in same host */
1523 63a01ef8 aliguori
    val = 1;
1524 63a01ef8 aliguori
    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
1525 63a01ef8 aliguori
                   (const char *)&val, sizeof(val));
1526 63a01ef8 aliguori
    if (ret < 0) {
1527 63a01ef8 aliguori
        perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
1528 63a01ef8 aliguori
        goto fail;
1529 63a01ef8 aliguori
    }
1530 63a01ef8 aliguori
1531 63a01ef8 aliguori
    socket_set_nonblock(fd);
1532 63a01ef8 aliguori
    return fd;
1533 63a01ef8 aliguori
fail:
1534 63a01ef8 aliguori
    if (fd >= 0)
1535 63a01ef8 aliguori
        closesocket(fd);
1536 63a01ef8 aliguori
    return -1;
1537 63a01ef8 aliguori
}
1538 63a01ef8 aliguori
1539 b946a153 aliguori
static void net_socket_cleanup(VLANClientState *vc)
1540 b946a153 aliguori
{
1541 b946a153 aliguori
    NetSocketState *s = vc->opaque;
1542 b946a153 aliguori
    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
1543 b946a153 aliguori
    close(s->fd);
1544 b946a153 aliguori
    qemu_free(s);
1545 b946a153 aliguori
}
1546 b946a153 aliguori
1547 7a9f6e4a aliguori
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
1548 7a9f6e4a aliguori
                                                const char *model,
1549 7a9f6e4a aliguori
                                                const char *name,
1550 bf38c1a0 aliguori
                                                int fd, int is_connected)
1551 63a01ef8 aliguori
{
1552 63a01ef8 aliguori
    struct sockaddr_in saddr;
1553 63a01ef8 aliguori
    int newfd;
1554 63a01ef8 aliguori
    socklen_t saddr_len;
1555 63a01ef8 aliguori
    NetSocketState *s;
1556 63a01ef8 aliguori
1557 63a01ef8 aliguori
    /* fd passed: multicast: "learn" dgram_dst address from bound address and save it
1558 63a01ef8 aliguori
     * Because this may be "shared" socket from a "master" process, datagrams would be recv()
1559 63a01ef8 aliguori
     * by ONLY ONE process: we must "clone" this dgram socket --jjo
1560 63a01ef8 aliguori
     */
1561 63a01ef8 aliguori
1562 63a01ef8 aliguori
    if (is_connected) {
1563 63a01ef8 aliguori
        if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
1564 63a01ef8 aliguori
            /* must be bound */
1565 63a01ef8 aliguori
            if (saddr.sin_addr.s_addr==0) {
1566 63a01ef8 aliguori
                fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
1567 63a01ef8 aliguori
                        fd);
1568 63a01ef8 aliguori
                return NULL;
1569 63a01ef8 aliguori
            }
1570 63a01ef8 aliguori
            /* clone dgram socket */
1571 63a01ef8 aliguori
            newfd = net_socket_mcast_create(&saddr);
1572 63a01ef8 aliguori
            if (newfd < 0) {
1573 63a01ef8 aliguori
                /* error already reported by net_socket_mcast_create() */
1574 63a01ef8 aliguori
                close(fd);
1575 63a01ef8 aliguori
                return NULL;
1576 63a01ef8 aliguori
            }
1577 63a01ef8 aliguori
            /* clone newfd to fd, close newfd */
1578 63a01ef8 aliguori
            dup2(newfd, fd);
1579 63a01ef8 aliguori
            close(newfd);
1580 63a01ef8 aliguori
1581 63a01ef8 aliguori
        } else {
1582 63a01ef8 aliguori
            fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
1583 63a01ef8 aliguori
                    fd, strerror(errno));
1584 63a01ef8 aliguori
            return NULL;
1585 63a01ef8 aliguori
        }
1586 63a01ef8 aliguori
    }
1587 63a01ef8 aliguori
1588 63a01ef8 aliguori
    s = qemu_mallocz(sizeof(NetSocketState));
1589 63a01ef8 aliguori
    s->fd = fd;
1590 63a01ef8 aliguori
1591 bb6e6364 Mark McLoughlin
    s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_SOCKET,
1592 bb6e6364 Mark McLoughlin
                                 vlan, NULL, model, name, NULL,
1593 70783b9c Mark McLoughlin
                                 net_socket_receive_dgram, NULL, NULL,
1594 283c7c63 Mark McLoughlin
                                 net_socket_cleanup, s);
1595 63a01ef8 aliguori
    qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
1596 63a01ef8 aliguori
1597 63a01ef8 aliguori
    /* mcast: save bound address as dst */
1598 63a01ef8 aliguori
    if (is_connected) s->dgram_dst=saddr;
1599 63a01ef8 aliguori
1600 63a01ef8 aliguori
    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
1601 63a01ef8 aliguori
            "socket: fd=%d (%s mcast=%s:%d)",
1602 63a01ef8 aliguori
            fd, is_connected? "cloned" : "",
1603 63a01ef8 aliguori
            inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
1604 63a01ef8 aliguori
    return s;
1605 63a01ef8 aliguori
}
1606 63a01ef8 aliguori
1607 63a01ef8 aliguori
static void net_socket_connect(void *opaque)
1608 63a01ef8 aliguori
{
1609 63a01ef8 aliguori
    NetSocketState *s = opaque;
1610 63a01ef8 aliguori
    qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
1611 63a01ef8 aliguori
}
1612 63a01ef8 aliguori
1613 7a9f6e4a aliguori
static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
1614 7a9f6e4a aliguori
                                                 const char *model,
1615 7a9f6e4a aliguori
                                                 const char *name,
1616 bf38c1a0 aliguori
                                                 int fd, int is_connected)
1617 63a01ef8 aliguori
{
1618 63a01ef8 aliguori
    NetSocketState *s;
1619 63a01ef8 aliguori
    s = qemu_mallocz(sizeof(NetSocketState));
1620 63a01ef8 aliguori
    s->fd = fd;
1621 bb6e6364 Mark McLoughlin
    s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_SOCKET,
1622 bb6e6364 Mark McLoughlin
                                 vlan, NULL, model, name, NULL,
1623 70783b9c Mark McLoughlin
                                 net_socket_receive, NULL, NULL,
1624 283c7c63 Mark McLoughlin
                                 net_socket_cleanup, s);
1625 63a01ef8 aliguori
    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
1626 63a01ef8 aliguori
             "socket: fd=%d", fd);
1627 63a01ef8 aliguori
    if (is_connected) {
1628 63a01ef8 aliguori
        net_socket_connect(s);
1629 63a01ef8 aliguori
    } else {
1630 63a01ef8 aliguori
        qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s);
1631 63a01ef8 aliguori
    }
1632 63a01ef8 aliguori
    return s;
1633 63a01ef8 aliguori
}
1634 63a01ef8 aliguori
1635 7a9f6e4a aliguori
static NetSocketState *net_socket_fd_init(VLANState *vlan,
1636 7a9f6e4a aliguori
                                          const char *model, const char *name,
1637 bf38c1a0 aliguori
                                          int fd, int is_connected)
1638 63a01ef8 aliguori
{
1639 acedcfbf Michael S. Tsirkin
    int so_type = -1, optlen=sizeof(so_type);
1640 63a01ef8 aliguori
1641 63a01ef8 aliguori
    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
1642 63a01ef8 aliguori
        (socklen_t *)&optlen)< 0) {
1643 63a01ef8 aliguori
        fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
1644 63a01ef8 aliguori
        return NULL;
1645 63a01ef8 aliguori
    }
1646 63a01ef8 aliguori
    switch(so_type) {
1647 63a01ef8 aliguori
    case SOCK_DGRAM:
1648 7a9f6e4a aliguori
        return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected);
1649 63a01ef8 aliguori
    case SOCK_STREAM:
1650 7a9f6e4a aliguori
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
1651 63a01ef8 aliguori
    default:
1652 63a01ef8 aliguori
        /* who knows ... this could be a eg. a pty, do warn and continue as stream */
1653 63a01ef8 aliguori
        fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd);
1654 7a9f6e4a aliguori
        return net_socket_fd_init_stream(vlan, model, name, fd, is_connected);
1655 63a01ef8 aliguori
    }
1656 63a01ef8 aliguori
    return NULL;
1657 63a01ef8 aliguori
}
1658 63a01ef8 aliguori
1659 63a01ef8 aliguori
static void net_socket_accept(void *opaque)
1660 63a01ef8 aliguori
{
1661 63a01ef8 aliguori
    NetSocketListenState *s = opaque;
1662 63a01ef8 aliguori
    NetSocketState *s1;
1663 63a01ef8 aliguori
    struct sockaddr_in saddr;
1664 63a01ef8 aliguori
    socklen_t len;
1665 63a01ef8 aliguori
    int fd;
1666 63a01ef8 aliguori
1667 63a01ef8 aliguori
    for(;;) {
1668 63a01ef8 aliguori
        len = sizeof(saddr);
1669 63a01ef8 aliguori
        fd = accept(s->fd, (struct sockaddr *)&saddr, &len);
1670 63a01ef8 aliguori
        if (fd < 0 && errno != EINTR) {
1671 63a01ef8 aliguori
            return;
1672 63a01ef8 aliguori
        } else if (fd >= 0) {
1673 63a01ef8 aliguori
            break;
1674 63a01ef8 aliguori
        }
1675 63a01ef8 aliguori
    }
1676 7a9f6e4a aliguori
    s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1);
1677 63a01ef8 aliguori
    if (!s1) {
1678 63a01ef8 aliguori
        closesocket(fd);
1679 63a01ef8 aliguori
    } else {
1680 63a01ef8 aliguori
        snprintf(s1->vc->info_str, sizeof(s1->vc->info_str),
1681 63a01ef8 aliguori
                 "socket: connection from %s:%d",
1682 63a01ef8 aliguori
                 inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
1683 63a01ef8 aliguori
    }
1684 63a01ef8 aliguori
}
1685 63a01ef8 aliguori
1686 7a9f6e4a aliguori
static int net_socket_listen_init(VLANState *vlan,
1687 7a9f6e4a aliguori
                                  const char *model,
1688 7a9f6e4a aliguori
                                  const char *name,
1689 bf38c1a0 aliguori
                                  const char *host_str)
1690 63a01ef8 aliguori
{
1691 63a01ef8 aliguori
    NetSocketListenState *s;
1692 63a01ef8 aliguori
    int fd, val, ret;
1693 63a01ef8 aliguori
    struct sockaddr_in saddr;
1694 63a01ef8 aliguori
1695 63a01ef8 aliguori
    if (parse_host_port(&saddr, host_str) < 0)
1696 63a01ef8 aliguori
        return -1;
1697 63a01ef8 aliguori
1698 63a01ef8 aliguori
    s = qemu_mallocz(sizeof(NetSocketListenState));
1699 63a01ef8 aliguori
1700 63a01ef8 aliguori
    fd = socket(PF_INET, SOCK_STREAM, 0);
1701 63a01ef8 aliguori
    if (fd < 0) {
1702 63a01ef8 aliguori
        perror("socket");
1703 63a01ef8 aliguori
        return -1;
1704 63a01ef8 aliguori
    }
1705 63a01ef8 aliguori
    socket_set_nonblock(fd);
1706 63a01ef8 aliguori
1707 63a01ef8 aliguori
    /* allow fast reuse */
1708 63a01ef8 aliguori
    val = 1;
1709 63a01ef8 aliguori
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
1710 63a01ef8 aliguori
1711 63a01ef8 aliguori
    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
1712 63a01ef8 aliguori
    if (ret < 0) {
1713 63a01ef8 aliguori
        perror("bind");
1714 63a01ef8 aliguori
        return -1;
1715 63a01ef8 aliguori
    }
1716 63a01ef8 aliguori
    ret = listen(fd, 0);
1717 63a01ef8 aliguori
    if (ret < 0) {
1718 63a01ef8 aliguori
        perror("listen");
1719 63a01ef8 aliguori
        return -1;
1720 63a01ef8 aliguori
    }
1721 63a01ef8 aliguori
    s->vlan = vlan;
1722 02374aa0 Mark McLoughlin
    s->model = qemu_strdup(model);
1723 02374aa0 Mark McLoughlin
    s->name = name ? qemu_strdup(name) : NULL;
1724 63a01ef8 aliguori
    s->fd = fd;
1725 63a01ef8 aliguori
    qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
1726 63a01ef8 aliguori
    return 0;
1727 63a01ef8 aliguori
}
1728 63a01ef8 aliguori
1729 7a9f6e4a aliguori
static int net_socket_connect_init(VLANState *vlan,
1730 7a9f6e4a aliguori
                                   const char *model,
1731 7a9f6e4a aliguori
                                   const char *name,
1732 bf38c1a0 aliguori
                                   const char *host_str)
1733 63a01ef8 aliguori
{
1734 63a01ef8 aliguori
    NetSocketState *s;
1735 63a01ef8 aliguori
    int fd, connected, ret, err;
1736 63a01ef8 aliguori
    struct sockaddr_in saddr;
1737 63a01ef8 aliguori
1738 63a01ef8 aliguori
    if (parse_host_port(&saddr, host_str) < 0)
1739 63a01ef8 aliguori
        return -1;
1740 63a01ef8 aliguori
1741 63a01ef8 aliguori
    fd = socket(PF_INET, SOCK_STREAM, 0);
1742 63a01ef8 aliguori
    if (fd < 0) {
1743 63a01ef8 aliguori
        perror("socket");
1744 63a01ef8 aliguori
        return -1;
1745 63a01ef8 aliguori
    }
1746 63a01ef8 aliguori
    socket_set_nonblock(fd);
1747 63a01ef8 aliguori
1748 63a01ef8 aliguori
    connected = 0;
1749 63a01ef8 aliguori
    for(;;) {
1750 63a01ef8 aliguori
        ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
1751 63a01ef8 aliguori
        if (ret < 0) {
1752 63a01ef8 aliguori
            err = socket_error();
1753 63a01ef8 aliguori
            if (err == EINTR || err == EWOULDBLOCK) {
1754 63a01ef8 aliguori
            } else if (err == EINPROGRESS) {
1755 63a01ef8 aliguori
                break;
1756 63a01ef8 aliguori
#ifdef _WIN32
1757 63a01ef8 aliguori
            } else if (err == WSAEALREADY) {
1758 63a01ef8 aliguori
                break;
1759 63a01ef8 aliguori
#endif
1760 63a01ef8 aliguori
            } else {
1761 63a01ef8 aliguori
                perror("connect");
1762 63a01ef8 aliguori
                closesocket(fd);
1763 63a01ef8 aliguori
                return -1;
1764 63a01ef8 aliguori
            }
1765 63a01ef8 aliguori
        } else {
1766 63a01ef8 aliguori
            connected = 1;
1767 63a01ef8 aliguori
            break;
1768 63a01ef8 aliguori
        }
1769 63a01ef8 aliguori
    }
1770 7a9f6e4a aliguori
    s = net_socket_fd_init(vlan, model, name, fd, connected);
1771 63a01ef8 aliguori
    if (!s)
1772 63a01ef8 aliguori
        return -1;
1773 63a01ef8 aliguori
    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
1774 63a01ef8 aliguori
             "socket: connect to %s:%d",
1775 63a01ef8 aliguori
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
1776 63a01ef8 aliguori
    return 0;
1777 63a01ef8 aliguori
}
1778 63a01ef8 aliguori
1779 7a9f6e4a aliguori
static int net_socket_mcast_init(VLANState *vlan,
1780 7a9f6e4a aliguori
                                 const char *model,
1781 7a9f6e4a aliguori
                                 const char *name,
1782 bf38c1a0 aliguori
                                 const char *host_str)
1783 63a01ef8 aliguori
{
1784 63a01ef8 aliguori
    NetSocketState *s;
1785 63a01ef8 aliguori
    int fd;
1786 63a01ef8 aliguori
    struct sockaddr_in saddr;
1787 63a01ef8 aliguori
1788 63a01ef8 aliguori
    if (parse_host_port(&saddr, host_str) < 0)
1789 63a01ef8 aliguori
        return -1;
1790 63a01ef8 aliguori
1791 63a01ef8 aliguori
1792 63a01ef8 aliguori
    fd = net_socket_mcast_create(&saddr);
1793 63a01ef8 aliguori
    if (fd < 0)
1794 63a01ef8 aliguori
        return -1;
1795 63a01ef8 aliguori
1796 7a9f6e4a aliguori
    s = net_socket_fd_init(vlan, model, name, fd, 0);
1797 63a01ef8 aliguori
    if (!s)
1798 63a01ef8 aliguori
        return -1;
1799 63a01ef8 aliguori
1800 63a01ef8 aliguori
    s->dgram_dst = saddr;
1801 63a01ef8 aliguori
1802 63a01ef8 aliguori
    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
1803 63a01ef8 aliguori
             "socket: mcast=%s:%d",
1804 63a01ef8 aliguori
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
1805 63a01ef8 aliguori
    return 0;
1806 63a01ef8 aliguori
1807 63a01ef8 aliguori
}
1808 63a01ef8 aliguori
1809 bb9ea79e aliguori
typedef struct DumpState {
1810 bb9ea79e aliguori
    VLANClientState *pcap_vc;
1811 bb9ea79e aliguori
    int fd;
1812 bb9ea79e aliguori
    int pcap_caplen;
1813 bb9ea79e aliguori
} DumpState;
1814 bb9ea79e aliguori
1815 bb9ea79e aliguori
#define PCAP_MAGIC 0xa1b2c3d4
1816 bb9ea79e aliguori
1817 bb9ea79e aliguori
struct pcap_file_hdr {
1818 bb9ea79e aliguori
    uint32_t magic;
1819 bb9ea79e aliguori
    uint16_t version_major;
1820 bb9ea79e aliguori
    uint16_t version_minor;
1821 bb9ea79e aliguori
    int32_t thiszone;
1822 bb9ea79e aliguori
    uint32_t sigfigs;
1823 bb9ea79e aliguori
    uint32_t snaplen;
1824 bb9ea79e aliguori
    uint32_t linktype;
1825 bb9ea79e aliguori
};
1826 bb9ea79e aliguori
1827 bb9ea79e aliguori
struct pcap_sf_pkthdr {
1828 bb9ea79e aliguori
    struct {
1829 bb9ea79e aliguori
        int32_t tv_sec;
1830 bb9ea79e aliguori
        int32_t tv_usec;
1831 bb9ea79e aliguori
    } ts;
1832 bb9ea79e aliguori
    uint32_t caplen;
1833 bb9ea79e aliguori
    uint32_t len;
1834 bb9ea79e aliguori
};
1835 bb9ea79e aliguori
1836 4f1c942b Mark McLoughlin
static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
1837 bb9ea79e aliguori
{
1838 e3f5ec2b Mark McLoughlin
    DumpState *s = vc->opaque;
1839 bb9ea79e aliguori
    struct pcap_sf_pkthdr hdr;
1840 bb9ea79e aliguori
    int64_t ts;
1841 bb9ea79e aliguori
    int caplen;
1842 bb9ea79e aliguori
1843 bb9ea79e aliguori
    /* Early return in case of previous error. */
1844 bb9ea79e aliguori
    if (s->fd < 0) {
1845 4f1c942b Mark McLoughlin
        return size;
1846 bb9ea79e aliguori
    }
1847 bb9ea79e aliguori
1848 6ee093c9 Juan Quintela
    ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec());
1849 bb9ea79e aliguori
    caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
1850 bb9ea79e aliguori
1851 37cb6fc3 Jan Kiszka
    hdr.ts.tv_sec = ts / 1000000;
1852 bb9ea79e aliguori
    hdr.ts.tv_usec = ts % 1000000;
1853 bb9ea79e aliguori
    hdr.caplen = caplen;
1854 bb9ea79e aliguori
    hdr.len = size;
1855 bb9ea79e aliguori
    if (write(s->fd, &hdr, sizeof(hdr)) != sizeof(hdr) ||
1856 bb9ea79e aliguori
        write(s->fd, buf, caplen) != caplen) {
1857 bb9ea79e aliguori
        qemu_log("-net dump write error - stop dump\n");
1858 bb9ea79e aliguori
        close(s->fd);
1859 bb9ea79e aliguori
        s->fd = -1;
1860 bb9ea79e aliguori
    }
1861 4f1c942b Mark McLoughlin
1862 4f1c942b Mark McLoughlin
    return size;
1863 bb9ea79e aliguori
}
1864 bb9ea79e aliguori
1865 bb9ea79e aliguori
static void net_dump_cleanup(VLANClientState *vc)
1866 bb9ea79e aliguori
{
1867 bb9ea79e aliguori
    DumpState *s = vc->opaque;
1868 bb9ea79e aliguori
1869 bb9ea79e aliguori
    close(s->fd);
1870 bb9ea79e aliguori
    qemu_free(s);
1871 bb9ea79e aliguori
}
1872 bb9ea79e aliguori
1873 fb12577c Markus Armbruster
static int net_dump_init(VLANState *vlan, const char *device,
1874 bb9ea79e aliguori
                         const char *name, const char *filename, int len)
1875 bb9ea79e aliguori
{
1876 bb9ea79e aliguori
    struct pcap_file_hdr hdr;
1877 bb9ea79e aliguori
    DumpState *s;
1878 bb9ea79e aliguori
1879 bb9ea79e aliguori
    s = qemu_malloc(sizeof(DumpState));
1880 bb9ea79e aliguori
1881 024431b3 Filip Navara
    s->fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
1882 bb9ea79e aliguori
    if (s->fd < 0) {
1883 fb12577c Markus Armbruster
        qemu_error("-net dump: can't open %s\n", filename);
1884 bb9ea79e aliguori
        return -1;
1885 bb9ea79e aliguori
    }
1886 bb9ea79e aliguori
1887 bb9ea79e aliguori
    s->pcap_caplen = len;
1888 bb9ea79e aliguori
1889 bb9ea79e aliguori
    hdr.magic = PCAP_MAGIC;
1890 bb9ea79e aliguori
    hdr.version_major = 2;
1891 bb9ea79e aliguori
    hdr.version_minor = 4;
1892 bb9ea79e aliguori
    hdr.thiszone = 0;
1893 bb9ea79e aliguori
    hdr.sigfigs = 0;
1894 bb9ea79e aliguori
    hdr.snaplen = s->pcap_caplen;
1895 bb9ea79e aliguori
    hdr.linktype = 1;
1896 bb9ea79e aliguori
1897 bb9ea79e aliguori
    if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
1898 fb12577c Markus Armbruster
        qemu_error("-net dump write error: %s\n", strerror(errno));
1899 bb9ea79e aliguori
        close(s->fd);
1900 bb9ea79e aliguori
        qemu_free(s);
1901 bb9ea79e aliguori
        return -1;
1902 bb9ea79e aliguori
    }
1903 bb9ea79e aliguori
1904 bb6e6364 Mark McLoughlin
    s->pcap_vc = qemu_new_vlan_client(NET_CLIENT_TYPE_DUMP,
1905 bb6e6364 Mark McLoughlin
                                      vlan, NULL, device, name, NULL,
1906 70783b9c Mark McLoughlin
                                      dump_receive, NULL, NULL,
1907 bb9ea79e aliguori
                                      net_dump_cleanup, s);
1908 bb9ea79e aliguori
    snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str),
1909 bb9ea79e aliguori
             "dump to %s (len=%d)", filename, len);
1910 bb9ea79e aliguori
    return 0;
1911 bb9ea79e aliguori
}
1912 bb9ea79e aliguori
1913 63a01ef8 aliguori
/* find or alloc a new VLAN */
1914 1a609520 Jan Kiszka
VLANState *qemu_find_vlan(int id, int allocate)
1915 63a01ef8 aliguori
{
1916 5610c3aa Mark McLoughlin
    VLANState *vlan;
1917 5610c3aa Mark McLoughlin
1918 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
1919 5610c3aa Mark McLoughlin
        if (vlan->id == id) {
1920 63a01ef8 aliguori
            return vlan;
1921 5610c3aa Mark McLoughlin
        }
1922 63a01ef8 aliguori
    }
1923 5610c3aa Mark McLoughlin
1924 1a609520 Jan Kiszka
    if (!allocate) {
1925 1a609520 Jan Kiszka
        return NULL;
1926 1a609520 Jan Kiszka
    }
1927 5610c3aa Mark McLoughlin
1928 63a01ef8 aliguori
    vlan = qemu_mallocz(sizeof(VLANState));
1929 63a01ef8 aliguori
    vlan->id = id;
1930 5610c3aa Mark McLoughlin
    QTAILQ_INIT(&vlan->clients);
1931 f7105843 Mark McLoughlin
1932 f7105843 Mark McLoughlin
    vlan->send_queue = qemu_new_net_queue(qemu_vlan_deliver_packet,
1933 f7105843 Mark McLoughlin
                                          qemu_vlan_deliver_packet_iov,
1934 f7105843 Mark McLoughlin
                                          vlan);
1935 5610c3aa Mark McLoughlin
1936 5610c3aa Mark McLoughlin
    QTAILQ_INSERT_TAIL(&vlans, vlan, next);
1937 5610c3aa Mark McLoughlin
1938 63a01ef8 aliguori
    return vlan;
1939 63a01ef8 aliguori
}
1940 63a01ef8 aliguori
1941 2ef924b4 Gerd Hoffmann
VLANClientState *qemu_find_netdev(const char *id)
1942 5869c4d5 Mark McLoughlin
{
1943 5869c4d5 Mark McLoughlin
    VLANClientState *vc;
1944 5869c4d5 Mark McLoughlin
1945 5869c4d5 Mark McLoughlin
    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
1946 5869c4d5 Mark McLoughlin
        if (!strcmp(vc->name, id)) {
1947 5869c4d5 Mark McLoughlin
            return vc;
1948 5869c4d5 Mark McLoughlin
        }
1949 5869c4d5 Mark McLoughlin
    }
1950 5869c4d5 Mark McLoughlin
1951 5869c4d5 Mark McLoughlin
    return NULL;
1952 5869c4d5 Mark McLoughlin
}
1953 5869c4d5 Mark McLoughlin
1954 7697079b aliguori
static int nic_get_free_idx(void)
1955 7697079b aliguori
{
1956 7697079b aliguori
    int index;
1957 7697079b aliguori
1958 7697079b aliguori
    for (index = 0; index < MAX_NICS; index++)
1959 7697079b aliguori
        if (!nd_table[index].used)
1960 7697079b aliguori
            return index;
1961 7697079b aliguori
    return -1;
1962 7697079b aliguori
}
1963 7697079b aliguori
1964 07caea31 Markus Armbruster
int qemu_show_nic_models(const char *arg, const char *const *models)
1965 07caea31 Markus Armbruster
{
1966 07caea31 Markus Armbruster
    int i;
1967 07caea31 Markus Armbruster
1968 07caea31 Markus Armbruster
    if (!arg || strcmp(arg, "?"))
1969 07caea31 Markus Armbruster
        return 0;
1970 07caea31 Markus Armbruster
1971 07caea31 Markus Armbruster
    fprintf(stderr, "qemu: Supported NIC models: ");
1972 07caea31 Markus Armbruster
    for (i = 0 ; models[i]; i++)
1973 07caea31 Markus Armbruster
        fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');
1974 07caea31 Markus Armbruster
    return 1;
1975 07caea31 Markus Armbruster
}
1976 07caea31 Markus Armbruster
1977 d07f22c5 aliguori
void qemu_check_nic_model(NICInfo *nd, const char *model)
1978 d07f22c5 aliguori
{
1979 d07f22c5 aliguori
    const char *models[2];
1980 d07f22c5 aliguori
1981 d07f22c5 aliguori
    models[0] = model;
1982 d07f22c5 aliguori
    models[1] = NULL;
1983 d07f22c5 aliguori
1984 07caea31 Markus Armbruster
    if (qemu_show_nic_models(nd->model, models))
1985 07caea31 Markus Armbruster
        exit(0);
1986 07caea31 Markus Armbruster
    if (qemu_find_nic_model(nd, models, model) < 0)
1987 07caea31 Markus Armbruster
        exit(1);
1988 d07f22c5 aliguori
}
1989 d07f22c5 aliguori
1990 07caea31 Markus Armbruster
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
1991 07caea31 Markus Armbruster
                        const char *default_model)
1992 d07f22c5 aliguori
{
1993 07caea31 Markus Armbruster
    int i;
1994 d07f22c5 aliguori
1995 d07f22c5 aliguori
    if (!nd->model)
1996 32a8e14a Mark McLoughlin
        nd->model = qemu_strdup(default_model);
1997 d07f22c5 aliguori
1998 07caea31 Markus Armbruster
    for (i = 0 ; models[i]; i++) {
1999 07caea31 Markus Armbruster
        if (strcmp(nd->model, models[i]) == 0)
2000 07caea31 Markus Armbruster
            return i;
2001 d07f22c5 aliguori
    }
2002 d07f22c5 aliguori
2003 07caea31 Markus Armbruster
    qemu_error("qemu: Unsupported NIC model: %s\n", nd->model);
2004 07caea31 Markus Armbruster
    return -1;
2005 d07f22c5 aliguori
}
2006 d07f22c5 aliguori
2007 5281d757 Mark McLoughlin
int net_handle_fd_param(Monitor *mon, const char *param)
2008 c1d6eed7 Mark McLoughlin
{
2009 c1d6eed7 Mark McLoughlin
    if (!qemu_isdigit(param[0])) {
2010 c1d6eed7 Mark McLoughlin
        int fd;
2011 c1d6eed7 Mark McLoughlin
2012 c1d6eed7 Mark McLoughlin
        fd = monitor_get_fd(mon, param);
2013 c1d6eed7 Mark McLoughlin
        if (fd == -1) {
2014 fb12577c Markus Armbruster
            qemu_error("No file descriptor named %s found", param);
2015 c1d6eed7 Mark McLoughlin
            return -1;
2016 c1d6eed7 Mark McLoughlin
        }
2017 c1d6eed7 Mark McLoughlin
2018 c1d6eed7 Mark McLoughlin
        return fd;
2019 c1d6eed7 Mark McLoughlin
    } else {
2020 c1d6eed7 Mark McLoughlin
        return strtol(param, NULL, 0);
2021 c1d6eed7 Mark McLoughlin
    }
2022 c1d6eed7 Mark McLoughlin
}
2023 c1d6eed7 Mark McLoughlin
2024 f6b134ac Mark McLoughlin
static int net_init_nic(QemuOpts *opts,
2025 f6b134ac Mark McLoughlin
                        Monitor *mon,
2026 f6b134ac Mark McLoughlin
                        const char *name,
2027 f6b134ac Mark McLoughlin
                        VLANState *vlan)
2028 f83c6e10 Mark McLoughlin
{
2029 f83c6e10 Mark McLoughlin
    int idx;
2030 f83c6e10 Mark McLoughlin
    NICInfo *nd;
2031 5869c4d5 Mark McLoughlin
    const char *netdev;
2032 f83c6e10 Mark McLoughlin
2033 f83c6e10 Mark McLoughlin
    idx = nic_get_free_idx();
2034 f83c6e10 Mark McLoughlin
    if (idx == -1 || nb_nics >= MAX_NICS) {
2035 f83c6e10 Mark McLoughlin
        qemu_error("Too Many NICs\n");
2036 f83c6e10 Mark McLoughlin
        return -1;
2037 f83c6e10 Mark McLoughlin
    }
2038 f83c6e10 Mark McLoughlin
2039 f83c6e10 Mark McLoughlin
    nd = &nd_table[idx];
2040 f83c6e10 Mark McLoughlin
2041 f83c6e10 Mark McLoughlin
    memset(nd, 0, sizeof(*nd));
2042 f83c6e10 Mark McLoughlin
2043 5869c4d5 Mark McLoughlin
    if ((netdev = qemu_opt_get(opts, "netdev"))) {
2044 5869c4d5 Mark McLoughlin
        nd->netdev = qemu_find_netdev(netdev);
2045 5869c4d5 Mark McLoughlin
        if (!nd->netdev) {
2046 5869c4d5 Mark McLoughlin
            qemu_error("netdev '%s' not found\n", netdev);
2047 5869c4d5 Mark McLoughlin
            return -1;
2048 5869c4d5 Mark McLoughlin
        }
2049 5869c4d5 Mark McLoughlin
    } else {
2050 5869c4d5 Mark McLoughlin
        assert(vlan);
2051 5869c4d5 Mark McLoughlin
        nd->vlan = vlan;
2052 5869c4d5 Mark McLoughlin
    }
2053 6d952ebe Mark McLoughlin
    if (name) {
2054 6d952ebe Mark McLoughlin
        nd->name = qemu_strdup(name);
2055 6d952ebe Mark McLoughlin
    }
2056 f83c6e10 Mark McLoughlin
    if (qemu_opt_get(opts, "model")) {
2057 f83c6e10 Mark McLoughlin
        nd->model = qemu_strdup(qemu_opt_get(opts, "model"));
2058 f83c6e10 Mark McLoughlin
    }
2059 f83c6e10 Mark McLoughlin
    if (qemu_opt_get(opts, "addr")) {
2060 f83c6e10 Mark McLoughlin
        nd->devaddr = qemu_strdup(qemu_opt_get(opts, "addr"));
2061 f83c6e10 Mark McLoughlin
    }
2062 f83c6e10 Mark McLoughlin
2063 f83c6e10 Mark McLoughlin
    nd->macaddr[0] = 0x52;
2064 f83c6e10 Mark McLoughlin
    nd->macaddr[1] = 0x54;
2065 f83c6e10 Mark McLoughlin
    nd->macaddr[2] = 0x00;
2066 f83c6e10 Mark McLoughlin
    nd->macaddr[3] = 0x12;
2067 f83c6e10 Mark McLoughlin
    nd->macaddr[4] = 0x34;
2068 f83c6e10 Mark McLoughlin
    nd->macaddr[5] = 0x56 + idx;
2069 f83c6e10 Mark McLoughlin
2070 f83c6e10 Mark McLoughlin
    if (qemu_opt_get(opts, "macaddr") &&
2071 f83c6e10 Mark McLoughlin
        parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) {
2072 f83c6e10 Mark McLoughlin
        qemu_error("invalid syntax for ethernet address\n");
2073 f83c6e10 Mark McLoughlin
        return -1;
2074 f83c6e10 Mark McLoughlin
    }
2075 f83c6e10 Mark McLoughlin
2076 f83c6e10 Mark McLoughlin
    nd->nvectors = qemu_opt_get_number(opts, "vectors", NIC_NVECTORS_UNSPECIFIED);
2077 f83c6e10 Mark McLoughlin
    if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
2078 f83c6e10 Mark McLoughlin
        (nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) {
2079 f83c6e10 Mark McLoughlin
        qemu_error("invalid # of vectors: %d\n", nd->nvectors);
2080 f83c6e10 Mark McLoughlin
        return -1;
2081 f83c6e10 Mark McLoughlin
    }
2082 f83c6e10 Mark McLoughlin
2083 f83c6e10 Mark McLoughlin
    nd->used = 1;
2084 5869c4d5 Mark McLoughlin
    if (vlan) {
2085 5869c4d5 Mark McLoughlin
        nd->vlan->nb_guest_devs++;
2086 5869c4d5 Mark McLoughlin
    }
2087 f83c6e10 Mark McLoughlin
    nb_nics++;
2088 f83c6e10 Mark McLoughlin
2089 f83c6e10 Mark McLoughlin
    return idx;
2090 f83c6e10 Mark McLoughlin
}
2091 f83c6e10 Mark McLoughlin
2092 a3a766e7 Juan Quintela
#if defined(CONFIG_SLIRP)
2093 ec302ffd Mark McLoughlin
static int net_init_slirp_configs(const char *name, const char *value, void *opaque)
2094 ec302ffd Mark McLoughlin
{
2095 ec302ffd Mark McLoughlin
    struct slirp_config_str *config;
2096 ec302ffd Mark McLoughlin
2097 ec302ffd Mark McLoughlin
    if (strcmp(name, "hostfwd") != 0 && strcmp(name, "guestfwd") != 0) {
2098 ec302ffd Mark McLoughlin
        return 0;
2099 ec302ffd Mark McLoughlin
    }
2100 ec302ffd Mark McLoughlin
2101 ec302ffd Mark McLoughlin
    config = qemu_mallocz(sizeof(*config));
2102 ec302ffd Mark McLoughlin
2103 ec302ffd Mark McLoughlin
    pstrcpy(config->str, sizeof(config->str), value);
2104 ec302ffd Mark McLoughlin
2105 ec302ffd Mark McLoughlin
    if (!strcmp(name, "hostfwd")) {
2106 ec302ffd Mark McLoughlin
        config->flags = SLIRP_CFG_HOSTFWD;
2107 ec302ffd Mark McLoughlin
    }
2108 ec302ffd Mark McLoughlin
2109 ec302ffd Mark McLoughlin
    config->next = slirp_configs;
2110 ec302ffd Mark McLoughlin
    slirp_configs = config;
2111 ec302ffd Mark McLoughlin
2112 ec302ffd Mark McLoughlin
    return 0;
2113 ec302ffd Mark McLoughlin
}
2114 ec302ffd Mark McLoughlin
2115 f6b134ac Mark McLoughlin
static int net_init_slirp(QemuOpts *opts,
2116 f6b134ac Mark McLoughlin
                          Monitor *mon,
2117 f6b134ac Mark McLoughlin
                          const char *name,
2118 f6b134ac Mark McLoughlin
                          VLANState *vlan)
2119 ec302ffd Mark McLoughlin
{
2120 ec302ffd Mark McLoughlin
    struct slirp_config_str *config;
2121 ec302ffd Mark McLoughlin
    const char *vhost;
2122 ec302ffd Mark McLoughlin
    const char *vhostname;
2123 ec302ffd Mark McLoughlin
    const char *vdhcp_start;
2124 ec302ffd Mark McLoughlin
    const char *vnamesrv;
2125 ec302ffd Mark McLoughlin
    const char *tftp_export;
2126 ec302ffd Mark McLoughlin
    const char *bootfile;
2127 ec302ffd Mark McLoughlin
    const char *smb_export;
2128 ec302ffd Mark McLoughlin
    const char *vsmbsrv;
2129 ec302ffd Mark McLoughlin
    char *vnet = NULL;
2130 ec302ffd Mark McLoughlin
    int restricted = 0;
2131 ec302ffd Mark McLoughlin
    int ret;
2132 ec302ffd Mark McLoughlin
2133 ec302ffd Mark McLoughlin
    vhost       = qemu_opt_get(opts, "host");
2134 ec302ffd Mark McLoughlin
    vhostname   = qemu_opt_get(opts, "hostname");
2135 ec302ffd Mark McLoughlin
    vdhcp_start = qemu_opt_get(opts, "dhcpstart");
2136 ec302ffd Mark McLoughlin
    vnamesrv    = qemu_opt_get(opts, "dns");
2137 ec302ffd Mark McLoughlin
    tftp_export = qemu_opt_get(opts, "tftp");
2138 ec302ffd Mark McLoughlin
    bootfile    = qemu_opt_get(opts, "bootfile");
2139 ec302ffd Mark McLoughlin
    smb_export  = qemu_opt_get(opts, "smb");
2140 ec302ffd Mark McLoughlin
    vsmbsrv     = qemu_opt_get(opts, "smbserver");
2141 ec302ffd Mark McLoughlin
2142 ec302ffd Mark McLoughlin
    if (qemu_opt_get(opts, "ip")) {
2143 ec302ffd Mark McLoughlin
        const char *ip = qemu_opt_get(opts, "ip");
2144 ec302ffd Mark McLoughlin
        int l = strlen(ip) + strlen("/24") + 1;
2145 ec302ffd Mark McLoughlin
2146 ec302ffd Mark McLoughlin
        vnet = qemu_malloc(l);
2147 ec302ffd Mark McLoughlin
2148 ec302ffd Mark McLoughlin
        /* emulate legacy ip= parameter */
2149 ec302ffd Mark McLoughlin
        pstrcpy(vnet, l, ip);
2150 ec302ffd Mark McLoughlin
        pstrcat(vnet, l, "/24");
2151 ec302ffd Mark McLoughlin
    }
2152 ec302ffd Mark McLoughlin
2153 ec302ffd Mark McLoughlin
    if (qemu_opt_get(opts, "net")) {
2154 ec302ffd Mark McLoughlin
        if (vnet) {
2155 ec302ffd Mark McLoughlin
            qemu_free(vnet);
2156 ec302ffd Mark McLoughlin
        }
2157 ec302ffd Mark McLoughlin
        vnet = qemu_strdup(qemu_opt_get(opts, "net"));
2158 ec302ffd Mark McLoughlin
    }
2159 ec302ffd Mark McLoughlin
2160 ec302ffd Mark McLoughlin
    if (qemu_opt_get(opts, "restrict") &&
2161 ec302ffd Mark McLoughlin
        qemu_opt_get(opts, "restrict")[0] == 'y') {
2162 ec302ffd Mark McLoughlin
        restricted = 1;
2163 ec302ffd Mark McLoughlin
    }
2164 ec302ffd Mark McLoughlin
2165 ec302ffd Mark McLoughlin
    qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0);
2166 ec302ffd Mark McLoughlin
2167 ec302ffd Mark McLoughlin
    ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
2168 ec302ffd Mark McLoughlin
                         vhostname, tftp_export, bootfile, vdhcp_start,
2169 ec302ffd Mark McLoughlin
                         vnamesrv, smb_export, vsmbsrv);
2170 ec302ffd Mark McLoughlin
2171 ec302ffd Mark McLoughlin
    while (slirp_configs) {
2172 ec302ffd Mark McLoughlin
        config = slirp_configs;
2173 ec302ffd Mark McLoughlin
        slirp_configs = config->next;
2174 ec302ffd Mark McLoughlin
        qemu_free(config);
2175 ec302ffd Mark McLoughlin
    }
2176 ec302ffd Mark McLoughlin
2177 f6b134ac Mark McLoughlin
    if (ret != -1 && vlan) {
2178 ec302ffd Mark McLoughlin
        vlan->nb_host_devs++;
2179 ec302ffd Mark McLoughlin
    }
2180 ec302ffd Mark McLoughlin
2181 ec302ffd Mark McLoughlin
    qemu_free(vnet);
2182 ec302ffd Mark McLoughlin
2183 ec302ffd Mark McLoughlin
    return ret;
2184 ec302ffd Mark McLoughlin
}
2185 a3a766e7 Juan Quintela
#endif /* CONFIG_SLIRP */
2186 ec302ffd Mark McLoughlin
2187 f6b134ac Mark McLoughlin
static int net_init_socket(QemuOpts *opts,
2188 f6b134ac Mark McLoughlin
                           Monitor *mon,
2189 f6b134ac Mark McLoughlin
                           const char *name,
2190 f6b134ac Mark McLoughlin
                           VLANState *vlan)
2191 88ce16ca Mark McLoughlin
{
2192 88ce16ca Mark McLoughlin
    if (qemu_opt_get(opts, "fd")) {
2193 88ce16ca Mark McLoughlin
        int fd;
2194 88ce16ca Mark McLoughlin
2195 88ce16ca Mark McLoughlin
        if (qemu_opt_get(opts, "listen") ||
2196 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
2197 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "mcast")) {
2198 88ce16ca Mark McLoughlin
            qemu_error("listen=, connect= and mcast= is invalid with fd=\n");
2199 88ce16ca Mark McLoughlin
            return -1;
2200 88ce16ca Mark McLoughlin
        }
2201 88ce16ca Mark McLoughlin
2202 88ce16ca Mark McLoughlin
        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
2203 88ce16ca Mark McLoughlin
        if (fd == -1) {
2204 88ce16ca Mark McLoughlin
            return -1;
2205 88ce16ca Mark McLoughlin
        }
2206 88ce16ca Mark McLoughlin
2207 88ce16ca Mark McLoughlin
        if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) {
2208 88ce16ca Mark McLoughlin
            close(fd);
2209 88ce16ca Mark McLoughlin
            return -1;
2210 88ce16ca Mark McLoughlin
        }
2211 88ce16ca Mark McLoughlin
    } else if (qemu_opt_get(opts, "listen")) {
2212 88ce16ca Mark McLoughlin
        const char *listen;
2213 88ce16ca Mark McLoughlin
2214 88ce16ca Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
2215 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
2216 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "mcast")) {
2217 88ce16ca Mark McLoughlin
            qemu_error("fd=, connect= and mcast= is invalid with listen=\n");
2218 88ce16ca Mark McLoughlin
            return -1;
2219 88ce16ca Mark McLoughlin
        }
2220 88ce16ca Mark McLoughlin
2221 88ce16ca Mark McLoughlin
        listen = qemu_opt_get(opts, "listen");
2222 88ce16ca Mark McLoughlin
2223 88ce16ca Mark McLoughlin
        if (net_socket_listen_init(vlan, "socket", name, listen) == -1) {
2224 88ce16ca Mark McLoughlin
            return -1;
2225 88ce16ca Mark McLoughlin
        }
2226 88ce16ca Mark McLoughlin
    } else if (qemu_opt_get(opts, "connect")) {
2227 88ce16ca Mark McLoughlin
        const char *connect;
2228 88ce16ca Mark McLoughlin
2229 88ce16ca Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
2230 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "listen") ||
2231 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "mcast")) {
2232 88ce16ca Mark McLoughlin
            qemu_error("fd=, listen= and mcast= is invalid with connect=\n");
2233 88ce16ca Mark McLoughlin
            return -1;
2234 88ce16ca Mark McLoughlin
        }
2235 88ce16ca Mark McLoughlin
2236 88ce16ca Mark McLoughlin
        connect = qemu_opt_get(opts, "connect");
2237 88ce16ca Mark McLoughlin
2238 88ce16ca Mark McLoughlin
        if (net_socket_connect_init(vlan, "socket", name, connect) == -1) {
2239 88ce16ca Mark McLoughlin
            return -1;
2240 88ce16ca Mark McLoughlin
        }
2241 88ce16ca Mark McLoughlin
    } else if (qemu_opt_get(opts, "mcast")) {
2242 88ce16ca Mark McLoughlin
        const char *mcast;
2243 88ce16ca Mark McLoughlin
2244 88ce16ca Mark McLoughlin
        if (qemu_opt_get(opts, "fd") ||
2245 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "connect") ||
2246 88ce16ca Mark McLoughlin
            qemu_opt_get(opts, "listen")) {
2247 88ce16ca Mark McLoughlin
            qemu_error("fd=, connect= and listen= is invalid with mcast=\n");
2248 88ce16ca Mark McLoughlin
            return -1;
2249 88ce16ca Mark McLoughlin
        }
2250 88ce16ca Mark McLoughlin
2251 88ce16ca Mark McLoughlin
        mcast = qemu_opt_get(opts, "mcast");
2252 88ce16ca Mark McLoughlin
2253 88ce16ca Mark McLoughlin
        if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) {
2254 88ce16ca Mark McLoughlin
            return -1;
2255 88ce16ca Mark McLoughlin
        }
2256 88ce16ca Mark McLoughlin
    } else {
2257 88ce16ca Mark McLoughlin
        qemu_error("-socket requires fd=, listen=, connect= or mcast=\n");
2258 88ce16ca Mark McLoughlin
        return -1;
2259 88ce16ca Mark McLoughlin
    }
2260 88ce16ca Mark McLoughlin
2261 f6b134ac Mark McLoughlin
    if (vlan) {
2262 f6b134ac Mark McLoughlin
        vlan->nb_host_devs++;
2263 f6b134ac Mark McLoughlin
    }
2264 88ce16ca Mark McLoughlin
2265 88ce16ca Mark McLoughlin
    return 0;
2266 88ce16ca Mark McLoughlin
}
2267 88ce16ca Mark McLoughlin
2268 dd51058d Mark McLoughlin
#ifdef CONFIG_VDE
2269 f6b134ac Mark McLoughlin
static int net_init_vde(QemuOpts *opts,
2270 f6b134ac Mark McLoughlin
                        Monitor *mon,
2271 f6b134ac Mark McLoughlin
                        const char *name,
2272 f6b134ac Mark McLoughlin
                        VLANState *vlan)
2273 dd51058d Mark McLoughlin
{
2274 dd51058d Mark McLoughlin
    const char *sock;
2275 dd51058d Mark McLoughlin
    const char *group;
2276 dd51058d Mark McLoughlin
    int port, mode;
2277 dd51058d Mark McLoughlin
2278 dd51058d Mark McLoughlin
    sock  = qemu_opt_get(opts, "sock");
2279 dd51058d Mark McLoughlin
    group = qemu_opt_get(opts, "group");
2280 dd51058d Mark McLoughlin
2281 dd51058d Mark McLoughlin
    port = qemu_opt_get_number(opts, "port", 0);
2282 dd51058d Mark McLoughlin
    mode = qemu_opt_get_number(opts, "mode", 0700);
2283 dd51058d Mark McLoughlin
2284 dd51058d Mark McLoughlin
    if (net_vde_init(vlan, "vde", name, sock, port, group, mode) == -1) {
2285 dd51058d Mark McLoughlin
        return -1;
2286 dd51058d Mark McLoughlin
    }
2287 dd51058d Mark McLoughlin
2288 f6b134ac Mark McLoughlin
    if (vlan) {
2289 f6b134ac Mark McLoughlin
        vlan->nb_host_devs++;
2290 f6b134ac Mark McLoughlin
    }
2291 dd51058d Mark McLoughlin
2292 dd51058d Mark McLoughlin
    return 0;
2293 dd51058d Mark McLoughlin
}
2294 dd51058d Mark McLoughlin
#endif
2295 dd51058d Mark McLoughlin
2296 f6b134ac Mark McLoughlin
static int net_init_dump(QemuOpts *opts,
2297 f6b134ac Mark McLoughlin
                         Monitor *mon,
2298 f6b134ac Mark McLoughlin
                         const char *name,
2299 f6b134ac Mark McLoughlin
                         VLANState *vlan)
2300 ed2955c2 Mark McLoughlin
{
2301 ed2955c2 Mark McLoughlin
    int len;
2302 ed2955c2 Mark McLoughlin
    const char *file;
2303 ed2955c2 Mark McLoughlin
    char def_file[128];
2304 ed2955c2 Mark McLoughlin
2305 f6b134ac Mark McLoughlin
    assert(vlan);
2306 ed2955c2 Mark McLoughlin
2307 ed2955c2 Mark McLoughlin
    file = qemu_opt_get(opts, "file");
2308 ed2955c2 Mark McLoughlin
    if (!file) {
2309 ed2955c2 Mark McLoughlin
        snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id);
2310 ed2955c2 Mark McLoughlin
        file = def_file;
2311 ed2955c2 Mark McLoughlin
    }
2312 ed2955c2 Mark McLoughlin
2313 ed2955c2 Mark McLoughlin
    len = qemu_opt_get_size(opts, "len", 65536);
2314 ed2955c2 Mark McLoughlin
2315 ed2955c2 Mark McLoughlin
    return net_dump_init(vlan, "dump", name, file, len);
2316 ed2955c2 Mark McLoughlin
}
2317 ed2955c2 Mark McLoughlin
2318 f83c6e10 Mark McLoughlin
#define NET_COMMON_PARAMS_DESC                     \
2319 f83c6e10 Mark McLoughlin
    {                                              \
2320 f83c6e10 Mark McLoughlin
        .name = "type",                            \
2321 f83c6e10 Mark McLoughlin
        .type = QEMU_OPT_STRING,                   \
2322 f83c6e10 Mark McLoughlin
        .help = "net client type (nic, tap etc.)", \
2323 f83c6e10 Mark McLoughlin
     }, {                                          \
2324 f83c6e10 Mark McLoughlin
        .name = "vlan",                            \
2325 f83c6e10 Mark McLoughlin
        .type = QEMU_OPT_NUMBER,                   \
2326 f83c6e10 Mark McLoughlin
        .help = "vlan number",                     \
2327 f83c6e10 Mark McLoughlin
     }, {                                          \
2328 f83c6e10 Mark McLoughlin
        .name = "name",                            \
2329 f83c6e10 Mark McLoughlin
        .type = QEMU_OPT_STRING,                   \
2330 f83c6e10 Mark McLoughlin
        .help = "identifier for monitor commands", \
2331 f83c6e10 Mark McLoughlin
     }
2332 f83c6e10 Mark McLoughlin
2333 6d952ebe Mark McLoughlin
typedef int (*net_client_init_func)(QemuOpts *opts,
2334 6d952ebe Mark McLoughlin
                                    Monitor *mon,
2335 f6b134ac Mark McLoughlin
                                    const char *name,
2336 f6b134ac Mark McLoughlin
                                    VLANState *vlan);
2337 f83c6e10 Mark McLoughlin
2338 f83c6e10 Mark McLoughlin
/* magic number, but compiler will warn if too small */
2339 f83c6e10 Mark McLoughlin
#define NET_MAX_DESC 20
2340 f83c6e10 Mark McLoughlin
2341 f83c6e10 Mark McLoughlin
static struct {
2342 f83c6e10 Mark McLoughlin
    const char *type;
2343 f83c6e10 Mark McLoughlin
    net_client_init_func init;
2344 f83c6e10 Mark McLoughlin
    QemuOptDesc desc[NET_MAX_DESC];
2345 f83c6e10 Mark McLoughlin
} net_client_types[] = {
2346 f83c6e10 Mark McLoughlin
    {
2347 f83c6e10 Mark McLoughlin
        .type = "none",
2348 f83c6e10 Mark McLoughlin
        .desc = {
2349 f83c6e10 Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2350 f83c6e10 Mark McLoughlin
            { /* end of list */ }
2351 f83c6e10 Mark McLoughlin
        },
2352 f83c6e10 Mark McLoughlin
    }, {
2353 f83c6e10 Mark McLoughlin
        .type = "nic",
2354 f83c6e10 Mark McLoughlin
        .init = net_init_nic,
2355 f83c6e10 Mark McLoughlin
        .desc = {
2356 f83c6e10 Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2357 f83c6e10 Mark McLoughlin
            {
2358 5869c4d5 Mark McLoughlin
                .name = "netdev",
2359 5869c4d5 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2360 5869c4d5 Mark McLoughlin
                .help = "id of -netdev to connect to",
2361 5869c4d5 Mark McLoughlin
            },
2362 5869c4d5 Mark McLoughlin
            {
2363 f83c6e10 Mark McLoughlin
                .name = "macaddr",
2364 f83c6e10 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2365 f83c6e10 Mark McLoughlin
                .help = "MAC address",
2366 f83c6e10 Mark McLoughlin
            }, {
2367 f83c6e10 Mark McLoughlin
                .name = "model",
2368 f83c6e10 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2369 f83c6e10 Mark McLoughlin
                .help = "device model (e1000, rtl8139, virtio etc.)",
2370 f83c6e10 Mark McLoughlin
            }, {
2371 f83c6e10 Mark McLoughlin
                .name = "addr",
2372 f83c6e10 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2373 f83c6e10 Mark McLoughlin
                .help = "PCI device address",
2374 f83c6e10 Mark McLoughlin
            }, {
2375 f83c6e10 Mark McLoughlin
                .name = "vectors",
2376 f83c6e10 Mark McLoughlin
                .type = QEMU_OPT_NUMBER,
2377 f83c6e10 Mark McLoughlin
                .help = "number of MSI-x vectors, 0 to disable MSI-X",
2378 f83c6e10 Mark McLoughlin
            },
2379 f83c6e10 Mark McLoughlin
            { /* end of list */ }
2380 f83c6e10 Mark McLoughlin
        },
2381 ec302ffd Mark McLoughlin
#ifdef CONFIG_SLIRP
2382 ec302ffd Mark McLoughlin
    }, {
2383 ec302ffd Mark McLoughlin
        .type = "user",
2384 ec302ffd Mark McLoughlin
        .init = net_init_slirp,
2385 ec302ffd Mark McLoughlin
        .desc = {
2386 ec302ffd Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2387 ec302ffd Mark McLoughlin
            {
2388 ec302ffd Mark McLoughlin
                .name = "hostname",
2389 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2390 ec302ffd Mark McLoughlin
                .help = "client hostname reported by the builtin DHCP server",
2391 ec302ffd Mark McLoughlin
            }, {
2392 ec302ffd Mark McLoughlin
                .name = "restrict",
2393 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2394 ec302ffd Mark McLoughlin
                .help = "isolate the guest from the host (y|yes|n|no)",
2395 ec302ffd Mark McLoughlin
            }, {
2396 ec302ffd Mark McLoughlin
                .name = "ip",
2397 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2398 ec302ffd Mark McLoughlin
                .help = "legacy parameter, use net= instead",
2399 ec302ffd Mark McLoughlin
            }, {
2400 ec302ffd Mark McLoughlin
                .name = "net",
2401 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2402 ec302ffd Mark McLoughlin
                .help = "IP address and optional netmask",
2403 ec302ffd Mark McLoughlin
            }, {
2404 ec302ffd Mark McLoughlin
                .name = "host",
2405 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2406 ec302ffd Mark McLoughlin
                .help = "guest-visible address of the host",
2407 ec302ffd Mark McLoughlin
            }, {
2408 ec302ffd Mark McLoughlin
                .name = "tftp",
2409 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2410 ec302ffd Mark McLoughlin
                .help = "root directory of the built-in TFTP server",
2411 ec302ffd Mark McLoughlin
            }, {
2412 ec302ffd Mark McLoughlin
                .name = "bootfile",
2413 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2414 ec302ffd Mark McLoughlin
                .help = "BOOTP filename, for use with tftp=",
2415 ec302ffd Mark McLoughlin
            }, {
2416 ec302ffd Mark McLoughlin
                .name = "dhcpstart",
2417 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2418 ec302ffd Mark McLoughlin
                .help = "the first of the 16 IPs the built-in DHCP server can assign",
2419 ec302ffd Mark McLoughlin
            }, {
2420 ec302ffd Mark McLoughlin
                .name = "dns",
2421 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2422 ec302ffd Mark McLoughlin
                .help = "guest-visible address of the virtual nameserver",
2423 ec302ffd Mark McLoughlin
            }, {
2424 ec302ffd Mark McLoughlin
                .name = "smb",
2425 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2426 ec302ffd Mark McLoughlin
                .help = "root directory of the built-in SMB server",
2427 ec302ffd Mark McLoughlin
            }, {
2428 ec302ffd Mark McLoughlin
                .name = "smbserver",
2429 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2430 ec302ffd Mark McLoughlin
                .help = "IP address of the built-in SMB server",
2431 ec302ffd Mark McLoughlin
            }, {
2432 ec302ffd Mark McLoughlin
                .name = "hostfwd",
2433 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2434 ec302ffd Mark McLoughlin
                .help = "guest port number to forward incoming TCP or UDP connections",
2435 ec302ffd Mark McLoughlin
            }, {
2436 ec302ffd Mark McLoughlin
                .name = "guestfwd",
2437 ec302ffd Mark McLoughlin
                .type = QEMU_OPT_STRING,
2438 ec302ffd Mark McLoughlin
                .help = "IP address and port to forward guest TCP connections",
2439 ec302ffd Mark McLoughlin
            },
2440 ec302ffd Mark McLoughlin
            { /* end of list */ }
2441 ec302ffd Mark McLoughlin
        },
2442 ec302ffd Mark McLoughlin
#endif
2443 8a1c5235 Mark McLoughlin
    }, {
2444 8a1c5235 Mark McLoughlin
        .type = "tap",
2445 a8ed73f7 Mark McLoughlin
        .init = net_init_tap,
2446 8a1c5235 Mark McLoughlin
        .desc = {
2447 8a1c5235 Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2448 8a1c5235 Mark McLoughlin
            {
2449 8a1c5235 Mark McLoughlin
                .name = "ifname",
2450 8a1c5235 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2451 8a1c5235 Mark McLoughlin
                .help = "interface name",
2452 8a1c5235 Mark McLoughlin
            },
2453 a8ed73f7 Mark McLoughlin
#ifndef _WIN32
2454 8a1c5235 Mark McLoughlin
            {
2455 8a1c5235 Mark McLoughlin
                .name = "fd",
2456 8a1c5235 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2457 8a1c5235 Mark McLoughlin
                .help = "file descriptor of an already opened tap",
2458 8a1c5235 Mark McLoughlin
            }, {
2459 8a1c5235 Mark McLoughlin
                .name = "script",
2460 8a1c5235 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2461 8a1c5235 Mark McLoughlin
                .help = "script to initialize the interface",
2462 8a1c5235 Mark McLoughlin
            }, {
2463 8a1c5235 Mark McLoughlin
                .name = "downscript",
2464 8a1c5235 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2465 8a1c5235 Mark McLoughlin
                .help = "script to shut down the interface",
2466 8a1c5235 Mark McLoughlin
            }, {
2467 8a1c5235 Mark McLoughlin
                .name = "sndbuf",
2468 8a1c5235 Mark McLoughlin
                .type = QEMU_OPT_SIZE,
2469 8a1c5235 Mark McLoughlin
                .help = "send buffer limit"
2470 baf74c95 Mark McLoughlin
            }, {
2471 baf74c95 Mark McLoughlin
                .name = "vnet_hdr",
2472 baf74c95 Mark McLoughlin
                .type = QEMU_OPT_BOOL,
2473 baf74c95 Mark McLoughlin
                .help = "enable the IFF_VNET_HDR flag on the tap interface"
2474 8a1c5235 Mark McLoughlin
            },
2475 a8ed73f7 Mark McLoughlin
#endif /* _WIN32 */
2476 8a1c5235 Mark McLoughlin
            { /* end of list */ }
2477 8a1c5235 Mark McLoughlin
        },
2478 88ce16ca Mark McLoughlin
    }, {
2479 88ce16ca Mark McLoughlin
        .type = "socket",
2480 88ce16ca Mark McLoughlin
        .init = net_init_socket,
2481 88ce16ca Mark McLoughlin
        .desc = {
2482 88ce16ca Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2483 88ce16ca Mark McLoughlin
            {
2484 88ce16ca Mark McLoughlin
                .name = "fd",
2485 88ce16ca Mark McLoughlin
                .type = QEMU_OPT_STRING,
2486 88ce16ca Mark McLoughlin
                .help = "file descriptor of an already opened socket",
2487 88ce16ca Mark McLoughlin
            }, {
2488 88ce16ca Mark McLoughlin
                .name = "listen",
2489 88ce16ca Mark McLoughlin
                .type = QEMU_OPT_STRING,
2490 88ce16ca Mark McLoughlin
                .help = "port number, and optional hostname, to listen on",
2491 88ce16ca Mark McLoughlin
            }, {
2492 88ce16ca Mark McLoughlin
                .name = "connect",
2493 88ce16ca Mark McLoughlin
                .type = QEMU_OPT_STRING,
2494 88ce16ca Mark McLoughlin
                .help = "port number, and optional hostname, to connect to",
2495 88ce16ca Mark McLoughlin
            }, {
2496 88ce16ca Mark McLoughlin
                .name = "mcast",
2497 88ce16ca Mark McLoughlin
                .type = QEMU_OPT_STRING,
2498 88ce16ca Mark McLoughlin
                .help = "UDP multicast address and port number",
2499 88ce16ca Mark McLoughlin
            },
2500 88ce16ca Mark McLoughlin
            { /* end of list */ }
2501 88ce16ca Mark McLoughlin
        },
2502 dd51058d Mark McLoughlin
#ifdef CONFIG_VDE
2503 dd51058d Mark McLoughlin
    }, {
2504 dd51058d Mark McLoughlin
        .type = "vde",
2505 dd51058d Mark McLoughlin
        .init = net_init_vde,
2506 dd51058d Mark McLoughlin
        .desc = {
2507 dd51058d Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2508 dd51058d Mark McLoughlin
            {
2509 dd51058d Mark McLoughlin
                .name = "sock",
2510 dd51058d Mark McLoughlin
                .type = QEMU_OPT_STRING,
2511 dd51058d Mark McLoughlin
                .help = "socket path",
2512 dd51058d Mark McLoughlin
            }, {
2513 dd51058d Mark McLoughlin
                .name = "port",
2514 dd51058d Mark McLoughlin
                .type = QEMU_OPT_NUMBER,
2515 dd51058d Mark McLoughlin
                .help = "port number",
2516 dd51058d Mark McLoughlin
            }, {
2517 dd51058d Mark McLoughlin
                .name = "group",
2518 dd51058d Mark McLoughlin
                .type = QEMU_OPT_STRING,
2519 dd51058d Mark McLoughlin
                .help = "group owner of socket",
2520 dd51058d Mark McLoughlin
            }, {
2521 dd51058d Mark McLoughlin
                .name = "mode",
2522 dd51058d Mark McLoughlin
                .type = QEMU_OPT_NUMBER,
2523 dd51058d Mark McLoughlin
                .help = "permissions for socket",
2524 dd51058d Mark McLoughlin
            },
2525 dd51058d Mark McLoughlin
            { /* end of list */ }
2526 dd51058d Mark McLoughlin
        },
2527 dd51058d Mark McLoughlin
#endif
2528 ed2955c2 Mark McLoughlin
    }, {
2529 ed2955c2 Mark McLoughlin
        .type = "dump",
2530 ed2955c2 Mark McLoughlin
        .init = net_init_dump,
2531 ed2955c2 Mark McLoughlin
        .desc = {
2532 ed2955c2 Mark McLoughlin
            NET_COMMON_PARAMS_DESC,
2533 ed2955c2 Mark McLoughlin
            {
2534 ed2955c2 Mark McLoughlin
                .name = "len",
2535 ed2955c2 Mark McLoughlin
                .type = QEMU_OPT_SIZE,
2536 ed2955c2 Mark McLoughlin
                .help = "per-packet size limit (64k default)",
2537 ed2955c2 Mark McLoughlin
            }, {
2538 ed2955c2 Mark McLoughlin
                .name = "file",
2539 ed2955c2 Mark McLoughlin
                .type = QEMU_OPT_STRING,
2540 ed2955c2 Mark McLoughlin
                .help = "dump file path (default is qemu-vlan0.pcap)",
2541 ed2955c2 Mark McLoughlin
            },
2542 ed2955c2 Mark McLoughlin
            { /* end of list */ }
2543 ed2955c2 Mark McLoughlin
        },
2544 f83c6e10 Mark McLoughlin
    },
2545 f83c6e10 Mark McLoughlin
    { /* end of list */ }
2546 f83c6e10 Mark McLoughlin
};
2547 f83c6e10 Mark McLoughlin
2548 f6b134ac Mark McLoughlin
int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
2549 f83c6e10 Mark McLoughlin
{
2550 6d952ebe Mark McLoughlin
    const char *name;
2551 f83c6e10 Mark McLoughlin
    const char *type;
2552 f83c6e10 Mark McLoughlin
    int i;
2553 f83c6e10 Mark McLoughlin
2554 f83c6e10 Mark McLoughlin
    type = qemu_opt_get(opts, "type");
2555 f83c6e10 Mark McLoughlin
    if (!type) {
2556 f83c6e10 Mark McLoughlin
        qemu_error("No type specified for -net\n");
2557 f83c6e10 Mark McLoughlin
        return -1;
2558 f83c6e10 Mark McLoughlin
    }
2559 f83c6e10 Mark McLoughlin
2560 f6b134ac Mark McLoughlin
    if (is_netdev) {
2561 f6b134ac Mark McLoughlin
        if (strcmp(type, "tap") != 0 &&
2562 f6b134ac Mark McLoughlin
#ifdef CONFIG_SLIRP
2563 f6b134ac Mark McLoughlin
            strcmp(type, "user") != 0 &&
2564 f6b134ac Mark McLoughlin
#endif
2565 f6b134ac Mark McLoughlin
#ifdef CONFIG_VDE
2566 f6b134ac Mark McLoughlin
            strcmp(type, "vde") != 0 &&
2567 f6b134ac Mark McLoughlin
#endif
2568 f6b134ac Mark McLoughlin
            strcmp(type, "socket") != 0) {
2569 f6b134ac Mark McLoughlin
            qemu_error("The '%s' network backend type is not valid with -netdev\n",
2570 f6b134ac Mark McLoughlin
                       type);
2571 f6b134ac Mark McLoughlin
            return -1;
2572 f6b134ac Mark McLoughlin
        }
2573 f6b134ac Mark McLoughlin
2574 f6b134ac Mark McLoughlin
        if (qemu_opt_get(opts, "vlan")) {
2575 f6b134ac Mark McLoughlin
            qemu_error("The 'vlan' parameter is not valid with -netdev\n");
2576 f6b134ac Mark McLoughlin
            return -1;
2577 f6b134ac Mark McLoughlin
        }
2578 f6b134ac Mark McLoughlin
        if (qemu_opt_get(opts, "name")) {
2579 f6b134ac Mark McLoughlin
            qemu_error("The 'name' parameter is not valid with -netdev\n");
2580 f6b134ac Mark McLoughlin
            return -1;
2581 f6b134ac Mark McLoughlin
        }
2582 f6b134ac Mark McLoughlin
        if (!qemu_opts_id(opts)) {
2583 f6b134ac Mark McLoughlin
            qemu_error("The id= parameter is required with -netdev\n");
2584 f6b134ac Mark McLoughlin
            return -1;
2585 f6b134ac Mark McLoughlin
        }
2586 f6b134ac Mark McLoughlin
    }
2587 f6b134ac Mark McLoughlin
2588 6d952ebe Mark McLoughlin
    name = qemu_opts_id(opts);
2589 6d952ebe Mark McLoughlin
    if (!name) {
2590 6d952ebe Mark McLoughlin
        name = qemu_opt_get(opts, "name");
2591 6d952ebe Mark McLoughlin
    }
2592 6d952ebe Mark McLoughlin
2593 f83c6e10 Mark McLoughlin
    for (i = 0; net_client_types[i].type != NULL; i++) {
2594 f83c6e10 Mark McLoughlin
        if (!strcmp(net_client_types[i].type, type)) {
2595 f6b134ac Mark McLoughlin
            VLANState *vlan = NULL;
2596 f6b134ac Mark McLoughlin
2597 f83c6e10 Mark McLoughlin
            if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
2598 f83c6e10 Mark McLoughlin
                return -1;
2599 f83c6e10 Mark McLoughlin
            }
2600 f83c6e10 Mark McLoughlin
2601 5869c4d5 Mark McLoughlin
            /* Do not add to a vlan if it's a -netdev or a nic with a
2602 5869c4d5 Mark McLoughlin
             * netdev= parameter. */
2603 5869c4d5 Mark McLoughlin
            if (!(is_netdev ||
2604 5869c4d5 Mark McLoughlin
                  (strcmp(type, "nic") == 0 && qemu_opt_get(opts, "netdev")))) {
2605 f6b134ac Mark McLoughlin
                vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
2606 f6b134ac Mark McLoughlin
            }
2607 f6b134ac Mark McLoughlin
2608 f83c6e10 Mark McLoughlin
            if (net_client_types[i].init) {
2609 f6b134ac Mark McLoughlin
                return net_client_types[i].init(opts, mon, name, vlan);
2610 f83c6e10 Mark McLoughlin
            } else {
2611 f83c6e10 Mark McLoughlin
                return 0;
2612 f83c6e10 Mark McLoughlin
            }
2613 f83c6e10 Mark McLoughlin
        }
2614 f83c6e10 Mark McLoughlin
    }
2615 f83c6e10 Mark McLoughlin
2616 f83c6e10 Mark McLoughlin
    qemu_error("Invalid -net type '%s'\n", type);
2617 f83c6e10 Mark McLoughlin
    return -1;
2618 f83c6e10 Mark McLoughlin
}
2619 f83c6e10 Mark McLoughlin
2620 8b13c4a7 aliguori
void net_client_uninit(NICInfo *nd)
2621 8b13c4a7 aliguori
{
2622 d80b9fc6 Mark McLoughlin
    if (nd->vlan) {
2623 d80b9fc6 Mark McLoughlin
        nd->vlan->nb_guest_devs--;
2624 d80b9fc6 Mark McLoughlin
    }
2625 8b13c4a7 aliguori
    nb_nics--;
2626 a9796703 Glauber Costa
2627 9203f520 Mark McLoughlin
    qemu_free(nd->model);
2628 9203f520 Mark McLoughlin
    qemu_free(nd->name);
2629 9203f520 Mark McLoughlin
    qemu_free(nd->devaddr);
2630 a9796703 Glauber Costa
2631 d2cffe30 Mark McLoughlin
    nd->used = 0;
2632 8b13c4a7 aliguori
}
2633 8b13c4a7 aliguori
2634 6f338c34 aliguori
static int net_host_check_device(const char *device)
2635 6f338c34 aliguori
{
2636 6f338c34 aliguori
    int i;
2637 bb9ea79e aliguori
    const char *valid_param_list[] = { "tap", "socket", "dump"
2638 6f338c34 aliguori
#ifdef CONFIG_SLIRP
2639 6f338c34 aliguori
                                       ,"user"
2640 6f338c34 aliguori
#endif
2641 6f338c34 aliguori
#ifdef CONFIG_VDE
2642 6f338c34 aliguori
                                       ,"vde"
2643 6f338c34 aliguori
#endif
2644 6f338c34 aliguori
    };
2645 6f338c34 aliguori
    for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) {
2646 6f338c34 aliguori
        if (!strncmp(valid_param_list[i], device,
2647 6f338c34 aliguori
                     strlen(valid_param_list[i])))
2648 6f338c34 aliguori
            return 1;
2649 6f338c34 aliguori
    }
2650 6f338c34 aliguori
2651 6f338c34 aliguori
    return 0;
2652 6f338c34 aliguori
}
2653 6f338c34 aliguori
2654 f18c16de Luiz Capitulino
void net_host_device_add(Monitor *mon, const QDict *qdict)
2655 6f338c34 aliguori
{
2656 f18c16de Luiz Capitulino
    const char *device = qdict_get_str(qdict, "device");
2657 7f1c9d20 Mark McLoughlin
    const char *opts_str = qdict_get_try_str(qdict, "opts");
2658 7f1c9d20 Mark McLoughlin
    QemuOpts *opts;
2659 f18c16de Luiz Capitulino
2660 6f338c34 aliguori
    if (!net_host_check_device(device)) {
2661 376253ec aliguori
        monitor_printf(mon, "invalid host network device %s\n", device);
2662 6f338c34 aliguori
        return;
2663 6f338c34 aliguori
    }
2664 7f1c9d20 Mark McLoughlin
2665 7f1c9d20 Mark McLoughlin
    opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
2666 7f1c9d20 Mark McLoughlin
    if (!opts) {
2667 7f1c9d20 Mark McLoughlin
        monitor_printf(mon, "parsing network options '%s' failed\n",
2668 7f1c9d20 Mark McLoughlin
                       opts_str ? opts_str : "");
2669 7f1c9d20 Mark McLoughlin
        return;
2670 7f1c9d20 Mark McLoughlin
    }
2671 7f1c9d20 Mark McLoughlin
2672 7f1c9d20 Mark McLoughlin
    qemu_opt_set(opts, "type", device);
2673 7f1c9d20 Mark McLoughlin
2674 f6b134ac Mark McLoughlin
    if (net_client_init(mon, opts, 0) < 0) {
2675 5c8be678 aliguori
        monitor_printf(mon, "adding host network device %s failed\n", device);
2676 5c8be678 aliguori
    }
2677 6f338c34 aliguori
}
2678 6f338c34 aliguori
2679 f18c16de Luiz Capitulino
void net_host_device_remove(Monitor *mon, const QDict *qdict)
2680 6f338c34 aliguori
{
2681 6f338c34 aliguori
    VLANClientState *vc;
2682 f18c16de Luiz Capitulino
    int vlan_id = qdict_get_int(qdict, "vlan_id");
2683 f18c16de Luiz Capitulino
    const char *device = qdict_get_str(qdict, "device");
2684 6f338c34 aliguori
2685 1a609520 Jan Kiszka
    vc = qemu_find_vlan_client_by_name(mon, vlan_id, device);
2686 6f338c34 aliguori
    if (!vc) {
2687 6f338c34 aliguori
        return;
2688 6f338c34 aliguori
    }
2689 e8f1f9db aliguori
    if (!net_host_check_device(vc->model)) {
2690 e8f1f9db aliguori
        monitor_printf(mon, "invalid host network device %s\n", device);
2691 e8f1f9db aliguori
        return;
2692 e8f1f9db aliguori
    }
2693 6f338c34 aliguori
    qemu_del_vlan_client(vc);
2694 6f338c34 aliguori
}
2695 6f338c34 aliguori
2696 406c8df3 Glauber Costa
void net_set_boot_mask(int net_boot_mask)
2697 406c8df3 Glauber Costa
{
2698 406c8df3 Glauber Costa
    int i;
2699 406c8df3 Glauber Costa
2700 406c8df3 Glauber Costa
    /* Only the first four NICs may be bootable */
2701 406c8df3 Glauber Costa
    net_boot_mask = net_boot_mask & 0xF;
2702 406c8df3 Glauber Costa
2703 406c8df3 Glauber Costa
    for (i = 0; i < nb_nics; i++) {
2704 406c8df3 Glauber Costa
        if (net_boot_mask & (1 << i)) {
2705 406c8df3 Glauber Costa
            nd_table[i].bootable = 1;
2706 406c8df3 Glauber Costa
            net_boot_mask &= ~(1 << i);
2707 406c8df3 Glauber Costa
        }
2708 406c8df3 Glauber Costa
    }
2709 406c8df3 Glauber Costa
2710 406c8df3 Glauber Costa
    if (net_boot_mask) {
2711 406c8df3 Glauber Costa
        fprintf(stderr, "Cannot boot from non-existent NIC\n");
2712 406c8df3 Glauber Costa
        exit(1);
2713 406c8df3 Glauber Costa
    }
2714 406c8df3 Glauber Costa
}
2715 406c8df3 Glauber Costa
2716 376253ec aliguori
void do_info_network(Monitor *mon)
2717 63a01ef8 aliguori
{
2718 63a01ef8 aliguori
    VLANState *vlan;
2719 63a01ef8 aliguori
2720 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
2721 5610c3aa Mark McLoughlin
        VLANClientState *vc;
2722 5610c3aa Mark McLoughlin
2723 376253ec aliguori
        monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
2724 5610c3aa Mark McLoughlin
2725 5610c3aa Mark McLoughlin
        QTAILQ_FOREACH(vc, &vlan->clients, next) {
2726 376253ec aliguori
            monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
2727 5610c3aa Mark McLoughlin
        }
2728 63a01ef8 aliguori
    }
2729 63a01ef8 aliguori
}
2730 63a01ef8 aliguori
2731 f18c16de Luiz Capitulino
void do_set_link(Monitor *mon, const QDict *qdict)
2732 436e5e53 aliguori
{
2733 436e5e53 aliguori
    VLANState *vlan;
2734 436e5e53 aliguori
    VLANClientState *vc = NULL;
2735 f18c16de Luiz Capitulino
    const char *name = qdict_get_str(qdict, "name");
2736 f18c16de Luiz Capitulino
    const char *up_or_down = qdict_get_str(qdict, "up_or_down");
2737 436e5e53 aliguori
2738 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
2739 5610c3aa Mark McLoughlin
        QTAILQ_FOREACH(vc, &vlan->clients, next) {
2740 5610c3aa Mark McLoughlin
            if (strcmp(vc->name, name) == 0) {
2741 dd5de373 edgar_igl
                goto done;
2742 5610c3aa Mark McLoughlin
            }
2743 5610c3aa Mark McLoughlin
        }
2744 5610c3aa Mark McLoughlin
    }
2745 dd5de373 edgar_igl
done:
2746 436e5e53 aliguori
2747 436e5e53 aliguori
    if (!vc) {
2748 7dc3fa09 Stefan Weil
        monitor_printf(mon, "could not find network device '%s'\n", name);
2749 c3cf0d3f Luiz Capitulino
        return;
2750 436e5e53 aliguori
    }
2751 436e5e53 aliguori
2752 436e5e53 aliguori
    if (strcmp(up_or_down, "up") == 0)
2753 436e5e53 aliguori
        vc->link_down = 0;
2754 436e5e53 aliguori
    else if (strcmp(up_or_down, "down") == 0)
2755 436e5e53 aliguori
        vc->link_down = 1;
2756 436e5e53 aliguori
    else
2757 376253ec aliguori
        monitor_printf(mon, "invalid link status '%s'; only 'up' or 'down' "
2758 376253ec aliguori
                       "valid\n", up_or_down);
2759 436e5e53 aliguori
2760 34b25ca7 aliguori
    if (vc->link_status_changed)
2761 34b25ca7 aliguori
        vc->link_status_changed(vc);
2762 436e5e53 aliguori
}
2763 436e5e53 aliguori
2764 63a01ef8 aliguori
void net_cleanup(void)
2765 63a01ef8 aliguori
{
2766 63a01ef8 aliguori
    VLANState *vlan;
2767 577c4af9 Mark McLoughlin
    VLANClientState *vc, *next_vc;
2768 63a01ef8 aliguori
2769 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
2770 5610c3aa Mark McLoughlin
        QTAILQ_FOREACH_SAFE(vc, &vlan->clients, next, next_vc) {
2771 b946a153 aliguori
            qemu_del_vlan_client(vc);
2772 63a01ef8 aliguori
        }
2773 63a01ef8 aliguori
    }
2774 577c4af9 Mark McLoughlin
2775 577c4af9 Mark McLoughlin
    QTAILQ_FOREACH_SAFE(vc, &non_vlan_clients, next, next_vc) {
2776 577c4af9 Mark McLoughlin
        qemu_del_vlan_client(vc);
2777 577c4af9 Mark McLoughlin
    }
2778 63a01ef8 aliguori
}
2779 63a01ef8 aliguori
2780 dc1c9fe8 Mark McLoughlin
static void net_check_clients(void)
2781 63a01ef8 aliguori
{
2782 63a01ef8 aliguori
    VLANState *vlan;
2783 63a01ef8 aliguori
2784 5610c3aa Mark McLoughlin
    QTAILQ_FOREACH(vlan, &vlans, next) {
2785 63a01ef8 aliguori
        if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
2786 63a01ef8 aliguori
            continue;
2787 63a01ef8 aliguori
        if (vlan->nb_guest_devs == 0)
2788 63a01ef8 aliguori
            fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
2789 63a01ef8 aliguori
        if (vlan->nb_host_devs == 0)
2790 63a01ef8 aliguori
            fprintf(stderr,
2791 63a01ef8 aliguori
                    "Warning: vlan %d is not connected to host network\n",
2792 63a01ef8 aliguori
                    vlan->id);
2793 63a01ef8 aliguori
    }
2794 63a01ef8 aliguori
}
2795 dc1c9fe8 Mark McLoughlin
2796 dc1c9fe8 Mark McLoughlin
static int net_init_client(QemuOpts *opts, void *dummy)
2797 dc1c9fe8 Mark McLoughlin
{
2798 c1671a08 Mark McLoughlin
    if (net_client_init(NULL, opts, 0) < 0)
2799 c1671a08 Mark McLoughlin
        return -1;
2800 c1671a08 Mark McLoughlin
    return 0;
2801 f6b134ac Mark McLoughlin
}
2802 f6b134ac Mark McLoughlin
2803 f6b134ac Mark McLoughlin
static int net_init_netdev(QemuOpts *opts, void *dummy)
2804 f6b134ac Mark McLoughlin
{
2805 f6b134ac Mark McLoughlin
    return net_client_init(NULL, opts, 1);
2806 dc1c9fe8 Mark McLoughlin
}
2807 dc1c9fe8 Mark McLoughlin
2808 dc1c9fe8 Mark McLoughlin
int net_init_clients(void)
2809 dc1c9fe8 Mark McLoughlin
{
2810 dc1c9fe8 Mark McLoughlin
    if (QTAILQ_EMPTY(&qemu_net_opts.head)) {
2811 dc1c9fe8 Mark McLoughlin
        /* if no clients, we use a default config */
2812 dc1c9fe8 Mark McLoughlin
        qemu_opts_set(&qemu_net_opts, NULL, "type", "nic");
2813 dc1c9fe8 Mark McLoughlin
#ifdef CONFIG_SLIRP
2814 dc1c9fe8 Mark McLoughlin
        qemu_opts_set(&qemu_net_opts, NULL, "type", "user");
2815 dc1c9fe8 Mark McLoughlin
#endif
2816 dc1c9fe8 Mark McLoughlin
    }
2817 dc1c9fe8 Mark McLoughlin
2818 5610c3aa Mark McLoughlin
    QTAILQ_INIT(&vlans);
2819 577c4af9 Mark McLoughlin
    QTAILQ_INIT(&non_vlan_clients);
2820 5610c3aa Mark McLoughlin
2821 f6b134ac Mark McLoughlin
    if (qemu_opts_foreach(&qemu_netdev_opts, net_init_netdev, NULL, 1) == -1)
2822 f6b134ac Mark McLoughlin
        return -1;
2823 f6b134ac Mark McLoughlin
2824 dc1c9fe8 Mark McLoughlin
    if (qemu_opts_foreach(&qemu_net_opts, net_init_client, NULL, 1) == -1) {
2825 dc1c9fe8 Mark McLoughlin
        return -1;
2826 dc1c9fe8 Mark McLoughlin
    }
2827 dc1c9fe8 Mark McLoughlin
2828 dc1c9fe8 Mark McLoughlin
    net_check_clients();
2829 dc1c9fe8 Mark McLoughlin
2830 dc1c9fe8 Mark McLoughlin
    return 0;
2831 dc1c9fe8 Mark McLoughlin
}
2832 dc1c9fe8 Mark McLoughlin
2833 7f161aae Mark McLoughlin
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
2834 dc1c9fe8 Mark McLoughlin
{
2835 a3a766e7 Juan Quintela
#if defined(CONFIG_SLIRP)
2836 dc1c9fe8 Mark McLoughlin
    /* handle legacy -net channel,port:chr */
2837 7f161aae Mark McLoughlin
    if (!strcmp(opts_list->name, "net") &&
2838 7f161aae Mark McLoughlin
        !strncmp(optarg, "channel,", strlen("channel,"))) {
2839 dc1c9fe8 Mark McLoughlin
        int ret;
2840 dc1c9fe8 Mark McLoughlin
2841 dc1c9fe8 Mark McLoughlin
        optarg += strlen("channel,");
2842 dc1c9fe8 Mark McLoughlin
2843 dc1c9fe8 Mark McLoughlin
        if (QTAILQ_EMPTY(&slirp_stacks)) {
2844 dc1c9fe8 Mark McLoughlin
            struct slirp_config_str *config;
2845 dc1c9fe8 Mark McLoughlin
2846 dc1c9fe8 Mark McLoughlin
            config = qemu_malloc(sizeof(*config));
2847 dc1c9fe8 Mark McLoughlin
            pstrcpy(config->str, sizeof(config->str), optarg);
2848 dc1c9fe8 Mark McLoughlin
            config->flags = SLIRP_CFG_LEGACY;
2849 dc1c9fe8 Mark McLoughlin
            config->next = slirp_configs;
2850 dc1c9fe8 Mark McLoughlin
            slirp_configs = config;
2851 dc1c9fe8 Mark McLoughlin
            ret = 0;
2852 dc1c9fe8 Mark McLoughlin
        } else {
2853 dc1c9fe8 Mark McLoughlin
            ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), optarg, 1);
2854 dc1c9fe8 Mark McLoughlin
        }
2855 dc1c9fe8 Mark McLoughlin
2856 dc1c9fe8 Mark McLoughlin
        return ret;
2857 dc1c9fe8 Mark McLoughlin
    }
2858 a3a766e7 Juan Quintela
#endif
2859 7f161aae Mark McLoughlin
    if (!qemu_opts_parse(opts_list, optarg, "type")) {
2860 dc1c9fe8 Mark McLoughlin
        return -1;
2861 dc1c9fe8 Mark McLoughlin
    }
2862 dc1c9fe8 Mark McLoughlin
2863 dc1c9fe8 Mark McLoughlin
    return 0;
2864 dc1c9fe8 Mark McLoughlin
}