Statistics
| Branch: | Revision:

root / net.c @ 273a2142

History | View | Annotate | Download (79.3 kB)

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