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