Statistics
| Branch: | Revision:

root / net.c @ 72cf2d4f

History | View | Annotate | Download (79.9 kB)

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