Revision c28b1c10
b/Makefile | ||
---|---|---|
89 | 89 |
net-obj-y = net.o |
90 | 90 |
net-nested-y = queue.o checksum.o |
91 | 91 |
net-nested-$(CONFIG_POSIX) += tap.o |
92 |
net-nested-$(CONFIG_LINUX) += tap-linux.o |
|
92 | 93 |
net-nested-$(CONFIG_WIN32) += tap-win32.o |
93 | 94 |
net-nested-$(CONFIG_BSD) += tap-bsd.o |
94 | 95 |
net-nested-$(CONFIG_SOLARIS) += tap-solaris.o |
b/net/tap-linux.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU System Emulator |
|
3 |
* |
|
4 |
* Copyright (c) 2003-2008 Fabrice Bellard |
|
5 |
* Copyright (c) 2009 Red Hat, Inc. |
|
6 |
* |
|
7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
8 |
* of this software and associated documentation files (the "Software"), to deal |
|
9 |
* in the Software without restriction, including without limitation the rights |
|
10 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
11 |
* copies of the Software, and to permit persons to whom the Software is |
|
12 |
* furnished to do so, subject to the following conditions: |
|
13 |
* |
|
14 |
* The above copyright notice and this permission notice shall be included in |
|
15 |
* all copies or substantial portions of the Software. |
|
16 |
* |
|
17 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
18 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
19 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
20 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
21 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
22 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
23 |
* THE SOFTWARE. |
|
24 |
*/ |
|
25 |
|
|
26 |
#include "net/tap.h" |
|
27 |
#include "net/tap-linux.h" |
|
28 |
|
|
29 |
#include <net/if.h> |
|
30 |
#include <sys/ioctl.h> |
|
31 |
|
|
32 |
#include "sysemu.h" |
|
33 |
#include "qemu-common.h" |
|
34 |
|
|
35 |
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) |
|
36 |
{ |
|
37 |
struct ifreq ifr; |
|
38 |
int fd, ret; |
|
39 |
|
|
40 |
TFR(fd = open("/dev/net/tun", O_RDWR)); |
|
41 |
if (fd < 0) { |
|
42 |
fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n"); |
|
43 |
return -1; |
|
44 |
} |
|
45 |
memset(&ifr, 0, sizeof(ifr)); |
|
46 |
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
|
47 |
|
|
48 |
if (*vnet_hdr) { |
|
49 |
unsigned int features; |
|
50 |
|
|
51 |
if (ioctl(fd, TUNGETFEATURES, &features) == 0 && |
|
52 |
features & IFF_VNET_HDR) { |
|
53 |
*vnet_hdr = 1; |
|
54 |
ifr.ifr_flags |= IFF_VNET_HDR; |
|
55 |
} |
|
56 |
|
|
57 |
if (vnet_hdr_required && !*vnet_hdr) { |
|
58 |
qemu_error("vnet_hdr=1 requested, but no kernel " |
|
59 |
"support for IFF_VNET_HDR available"); |
|
60 |
close(fd); |
|
61 |
return -1; |
|
62 |
} |
|
63 |
} |
|
64 |
|
|
65 |
if (ifname[0] != '\0') |
|
66 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); |
|
67 |
else |
|
68 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); |
|
69 |
ret = ioctl(fd, TUNSETIFF, (void *) &ifr); |
|
70 |
if (ret != 0) { |
|
71 |
fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); |
|
72 |
close(fd); |
|
73 |
return -1; |
|
74 |
} |
|
75 |
pstrcpy(ifname, ifname_size, ifr.ifr_name); |
|
76 |
fcntl(fd, F_SETFL, O_NONBLOCK); |
|
77 |
return fd; |
|
78 |
} |
b/net/tap.c | ||
---|---|---|
38 | 38 |
#include "qemu-char.h" |
39 | 39 |
#include "qemu-common.h" |
40 | 40 |
|
41 |
#ifdef __linux__ |
|
42 | 41 |
#include "net/tap-linux.h" |
43 |
#endif |
|
44 | 42 |
|
45 | 43 |
/* Maximum GSO packet size (64k) plus plenty of room for |
46 | 44 |
* the ethernet and virtio_net headers |
... | ... | |
347 | 345 |
return s; |
348 | 346 |
} |
349 | 347 |
|
350 |
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) |
|
351 |
{ |
|
352 |
struct ifreq ifr; |
|
353 |
int fd, ret; |
|
354 |
|
|
355 |
TFR(fd = open("/dev/net/tun", O_RDWR)); |
|
356 |
if (fd < 0) { |
|
357 |
fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n"); |
|
358 |
return -1; |
|
359 |
} |
|
360 |
memset(&ifr, 0, sizeof(ifr)); |
|
361 |
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
|
362 |
|
|
363 |
if (*vnet_hdr) { |
|
364 |
unsigned int features; |
|
365 |
|
|
366 |
if (ioctl(fd, TUNGETFEATURES, &features) == 0 && |
|
367 |
features & IFF_VNET_HDR) { |
|
368 |
*vnet_hdr = 1; |
|
369 |
ifr.ifr_flags |= IFF_VNET_HDR; |
|
370 |
} |
|
371 |
|
|
372 |
if (vnet_hdr_required && !*vnet_hdr) { |
|
373 |
qemu_error("vnet_hdr=1 requested, but no kernel " |
|
374 |
"support for IFF_VNET_HDR available"); |
|
375 |
close(fd); |
|
376 |
return -1; |
|
377 |
} |
|
378 |
} |
|
379 |
|
|
380 |
if (ifname[0] != '\0') |
|
381 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); |
|
382 |
else |
|
383 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); |
|
384 |
ret = ioctl(fd, TUNSETIFF, (void *) &ifr); |
|
385 |
if (ret != 0) { |
|
386 |
fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); |
|
387 |
close(fd); |
|
388 |
return -1; |
|
389 |
} |
|
390 |
pstrcpy(ifname, ifname_size, ifr.ifr_name); |
|
391 |
fcntl(fd, F_SETFL, O_NONBLOCK); |
|
392 |
return fd; |
|
393 |
} |
|
394 |
|
|
395 | 348 |
static int launch_script(const char *setup_script, const char *ifname, int fd) |
396 | 349 |
{ |
397 | 350 |
sigset_t oldmask, mask; |
Also available in: Unified diff