Statistics
| Branch: | Revision:

root / net.c @ d54908a5

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