Statistics
| Branch: | Revision:

root / net.c @ a3a766e7

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