|
|
1.1 root 1: /*
2: * QEMU System Emulator
3: *
4: * Copyright (c) 2003-2008 Fabrice Bellard
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24:
25: #include "net/tap.h"
26:
27: #include <sys/stat.h>
28: #include <sys/ethernet.h>
29: #include <sys/sockio.h>
30: #include <netinet/arp.h>
31: #include <netinet/in.h>
32: #include <netinet/in_systm.h>
33: #include <netinet/ip.h>
34: #include <netinet/ip_icmp.h> // must come after ip.h
35: #include <netinet/udp.h>
36: #include <netinet/tcp.h>
37: #include <net/if.h>
38: #include <syslog.h>
39: #include <stropts.h>
40:
41: ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
42: {
43: struct strbuf sbuf;
44: int f = 0;
45:
46: sbuf.maxlen = maxlen;
47: sbuf.buf = (char *)buf;
48:
49: return getmsg(tapfd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
50: }
51:
52: #define TUNNEWPPA (('T'<<16) | 0x0001)
53: /*
54: * Allocate TAP device, returns opened fd.
55: * Stores dev name in the first arg(must be large enough).
56: */
57: static int tap_alloc(char *dev, size_t dev_size)
58: {
59: int tap_fd, if_fd, ppa = -1;
60: static int ip_fd = 0;
61: char *ptr;
62:
63: static int arp_fd = 0;
64: int ip_muxid, arp_muxid;
65: struct strioctl strioc_if, strioc_ppa;
66: int link_type = I_PLINK;;
67: struct lifreq ifr;
68: char actual_name[32] = "";
69:
70: memset(&ifr, 0x0, sizeof(ifr));
71:
72: if( *dev ){
73: ptr = dev;
74: while( *ptr && !qemu_isdigit((int)*ptr) ) ptr++;
75: ppa = atoi(ptr);
76: }
77:
78: /* Check if IP device was opened */
79: if( ip_fd )
80: close(ip_fd);
81:
82: TFR(ip_fd = open("/dev/udp", O_RDWR, 0));
83: if (ip_fd < 0) {
84: syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
85: return -1;
86: }
87:
88: TFR(tap_fd = open("/dev/tap", O_RDWR, 0));
89: if (tap_fd < 0) {
90: syslog(LOG_ERR, "Can't open /dev/tap");
91: return -1;
92: }
93:
94: /* Assign a new PPA and get its unit number. */
95: strioc_ppa.ic_cmd = TUNNEWPPA;
96: strioc_ppa.ic_timout = 0;
97: strioc_ppa.ic_len = sizeof(ppa);
98: strioc_ppa.ic_dp = (char *)&ppa;
99: if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
100: syslog (LOG_ERR, "Can't assign new interface");
101:
102: TFR(if_fd = open("/dev/tap", O_RDWR, 0));
103: if (if_fd < 0) {
104: syslog(LOG_ERR, "Can't open /dev/tap (2)");
105: return -1;
106: }
107: if(ioctl(if_fd, I_PUSH, "ip") < 0){
108: syslog(LOG_ERR, "Can't push IP module");
109: return -1;
110: }
111:
112: if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
113: syslog(LOG_ERR, "Can't get flags\n");
114:
115: snprintf (actual_name, 32, "tap%d", ppa);
116: pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
117:
118: ifr.lifr_ppa = ppa;
119: /* Assign ppa according to the unit number returned by tun device */
120:
121: if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
122: syslog (LOG_ERR, "Can't set PPA %d", ppa);
123: if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
124: syslog (LOG_ERR, "Can't get flags\n");
125: /* Push arp module to if_fd */
126: if (ioctl (if_fd, I_PUSH, "arp") < 0)
127: syslog (LOG_ERR, "Can't push ARP module (2)");
128:
129: /* Push arp module to ip_fd */
130: if (ioctl (ip_fd, I_POP, NULL) < 0)
131: syslog (LOG_ERR, "I_POP failed\n");
132: if (ioctl (ip_fd, I_PUSH, "arp") < 0)
133: syslog (LOG_ERR, "Can't push ARP module (3)\n");
134: /* Open arp_fd */
135: TFR(arp_fd = open ("/dev/tap", O_RDWR, 0));
136: if (arp_fd < 0)
137: syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
138:
139: /* Set ifname to arp */
140: strioc_if.ic_cmd = SIOCSLIFNAME;
141: strioc_if.ic_timout = 0;
142: strioc_if.ic_len = sizeof(ifr);
143: strioc_if.ic_dp = (char *)𝔦
144: if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
145: syslog (LOG_ERR, "Can't set ifname to arp\n");
146: }
147:
148: if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
149: syslog(LOG_ERR, "Can't link TAP device to IP");
150: return -1;
151: }
152:
153: if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
154: syslog (LOG_ERR, "Can't link TAP device to ARP");
155:
156: close (if_fd);
157:
158: memset(&ifr, 0x0, sizeof(ifr));
159: pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
160: ifr.lifr_ip_muxid = ip_muxid;
161: ifr.lifr_arp_muxid = arp_muxid;
162:
163: if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
164: {
165: ioctl (ip_fd, I_PUNLINK , arp_muxid);
166: ioctl (ip_fd, I_PUNLINK, ip_muxid);
167: syslog (LOG_ERR, "Can't set multiplexor id");
168: }
169:
170: snprintf(dev, dev_size, "tap%d", ppa);
171: return tap_fd;
172: }
173:
174: int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
175: {
176: char dev[10]="";
177: int fd;
178: if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){
179: fprintf(stderr, "Cannot allocate TAP device\n");
180: return -1;
181: }
182: pstrcpy(ifname, ifname_size, dev);
183: if (*vnet_hdr) {
184: /* Solaris doesn't have IFF_VNET_HDR */
185: *vnet_hdr = 0;
186:
187: if (vnet_hdr_required && !*vnet_hdr) {
188: qemu_error("vnet_hdr=1 requested, but no kernel "
189: "support for IFF_VNET_HDR available");
190: close(fd);
191: return -1;
192: }
193: }
194: fcntl(fd, F_SETFL, O_NONBLOCK);
195: return fd;
196: }
197:
198: int tap_set_sndbuf(int fd, QemuOpts *opts)
199: {
200: return 0;
201: }
202:
203: int tap_probe_vnet_hdr(int fd)
204: {
205: return 0;
206: }
207:
208: int tap_probe_has_ufo(int fd)
209: {
210: return 0;
211: }
212:
213: void tap_fd_set_offload(int fd, int csum, int tso4,
214: int tso6, int ecn, int ufo)
215: {
216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.