Statistics
| Branch: | Revision:

root / net.c @ f40070c3

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