1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
1 |
/*
|
2 |
* OpenConnect (SSL + DTLS) VPN client
|
|
3 |
*
|
|
2054
by David Woodhouse
Update copyright year |
4 |
* Copyright © 2008-2015 Intel Corporation.
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
5 |
*
|
6 |
* Author: David Woodhouse <dwmw2@infradead.org>
|
|
7 |
*
|
|
8 |
* This program is free software; you can redistribute it and/or
|
|
9 |
* modify it under the terms of the GNU Lesser General Public License
|
|
10 |
* version 2.1, as published by the Free Software Foundation.
|
|
11 |
*
|
|
12 |
* This program is distributed in the hope that it will be useful, but
|
|
13 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15 |
* Lesser General Public License for more details.
|
|
16 |
*/
|
|
17 |
||
1636
by David Woodhouse
Use autoheader. Ick. But the command lines were getting silly |
18 |
#include <config.h> |
19 |
||
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
20 |
#define WIN32_LEAN_AND_MEAN
|
21 |
#include <windows.h> |
|
22 |
#include <winioctl.h> |
|
2479
by David Woodhouse
Add TUNIDX for Windows vpnc-script |
23 |
#include <iphlpapi.h> |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
24 |
|
25 |
#include <errno.h> |
|
26 |
#include <stdio.h> |
|
27 |
||
28 |
#include <openconnect-internal.h> |
|
29 |
||
30 |
/*
|
|
31 |
* TAP-Windows support inspired by http://i3.cs.berkeley.edu/ with
|
|
32 |
* permission.
|
|
33 |
*/
|
|
34 |
#define _TAP_IOCTL(nr) CTL_CODE(FILE_DEVICE_UNKNOWN, nr, METHOD_BUFFERED, \
|
|
35 |
FILE_ANY_ACCESS)
|
|
36 |
||
37 |
#define TAP_IOCTL_GET_MAC _TAP_IOCTL(1)
|
|
38 |
#define TAP_IOCTL_GET_VERSION _TAP_IOCTL(2)
|
|
39 |
#define TAP_IOCTL_GET_MTU _TAP_IOCTL(3)
|
|
40 |
#define TAP_IOCTL_GET_INFO _TAP_IOCTL(4)
|
|
41 |
#define TAP_IOCTL_CONFIG_POINT_TO_POINT _TAP_IOCTL(5)
|
|
42 |
#define TAP_IOCTL_SET_MEDIA_STATUS _TAP_IOCTL(6)
|
|
43 |
#define TAP_IOCTL_CONFIG_DHCP_MASQ _TAP_IOCTL(7)
|
|
44 |
#define TAP_IOCTL_GET_LOG_LINE _TAP_IOCTL(8)
|
|
45 |
#define TAP_IOCTL_CONFIG_DHCP_SET_OPT _TAP_IOCTL(9)
|
|
46 |
#define TAP_IOCTL_CONFIG_TUN _TAP_IOCTL(10)
|
|
47 |
||
48 |
#define TAP_COMPONENT_ID "tap0901"
|
|
49 |
||
50 |
#define DEVTEMPLATE "\\\\.\\Global\\%s.tap"
|
|
51 |
||
52 |
#define NETDEV_GUID "{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
|
53 |
#define CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\"
|
|
54 |
||
55 |
#define ADAPTERS_KEY CONTROL_KEY "Class\\" NETDEV_GUID
|
|
56 |
#define CONNECTIONS_KEY CONTROL_KEY "Network\\" NETDEV_GUID
|
|
57 |
||
1433
by David Woodhouse
Clean up search_taps() function |
58 |
typedef intptr_t (tap_callback)(struct openconnect_info *vpninfo, char *idx, char *name); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
59 |
|
1433
by David Woodhouse
Clean up search_taps() function |
60 |
static intptr_t search_taps(struct openconnect_info *vpninfo, tap_callback *cb, int all) |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
61 |
{
|
62 |
LONG status; |
|
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
63 |
HKEY adapters_key, hkey; |
64 |
DWORD len, type; |
|
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
65 |
char buf[40]; |
66 |
wchar_t name[40]; |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
67 |
char keyname[strlen(CONNECTIONS_KEY) + sizeof(buf) + 1 + strlen("\\Connection")]; |
1433
by David Woodhouse
Clean up search_taps() function |
68 |
int i = 0, found = 0; |
1709
by David Woodhouse
Fix tun device matching with --interface on Windows |
69 |
intptr_t ret = -1; |
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
70 |
struct oc_text_buf *namebuf = buf_alloc(); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
71 |
|
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
72 |
status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ADAPTERS_KEY, 0, |
73 |
KEY_READ, &adapters_key); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
74 |
if (status) { |
1415
by David Woodhouse
Fix error printing when registry open fails |
75 |
vpn_progress(vpninfo, PRG_ERR, |
76 |
_("Error accessing registry key for network adapters\n")); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
77 |
return -EIO; |
78 |
}
|
|
1433
by David Woodhouse
Clean up search_taps() function |
79 |
while (1) { |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
80 |
len = sizeof(buf); |
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
81 |
status = RegEnumKeyExA(adapters_key, i++, buf, &len, |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
82 |
NULL, NULL, NULL, NULL); |
83 |
if (status) { |
|
84 |
if (status != ERROR_NO_MORE_ITEMS) |
|
1433
by David Woodhouse
Clean up search_taps() function |
85 |
ret = -1; |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
86 |
break; |
87 |
}
|
|
88 |
||
89 |
snprintf(keyname, sizeof(keyname), "%s\\%s", |
|
90 |
ADAPTERS_KEY, buf); |
|
91 |
||
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
92 |
status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyname, 0, |
93 |
KEY_QUERY_VALUE, &hkey); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
94 |
if (status) |
95 |
continue; |
|
96 |
||
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
97 |
len = sizeof(buf); |
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
98 |
status = RegQueryValueExA(hkey, "ComponentId", NULL, &type, |
99 |
(unsigned char *)buf, &len); |
|
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
100 |
if (status || type != REG_SZ || strcmp(buf, TAP_COMPONENT_ID)) { |
101 |
RegCloseKey(hkey); |
|
102 |
continue; |
|
103 |
}
|
|
104 |
||
105 |
len = sizeof(buf); |
|
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
106 |
status = RegQueryValueExA(hkey, "NetCfgInstanceId", NULL, |
107 |
&type, (unsigned char *)buf, &len); |
|
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
108 |
RegCloseKey(hkey); |
109 |
if (status || type != REG_SZ) |
|
110 |
continue; |
|
111 |
||
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
112 |
snprintf(keyname, sizeof(keyname), "%s\\%s\\Connection", |
113 |
CONNECTIONS_KEY, buf); |
|
114 |
||
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
115 |
status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyname, 0, |
116 |
KEY_QUERY_VALUE, &hkey); |
|
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
117 |
if (status) |
118 |
continue; |
|
119 |
||
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
120 |
len = sizeof(name); |
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
121 |
status = RegQueryValueExW(hkey, L"Name", NULL, &type, |
1678
by David Woodhouse
Use RegQueryValueEx() instead of RegGetValue() to support 32-bit Windows XP |
122 |
(unsigned char *)name, &len); |
123 |
RegCloseKey(hkey); |
|
124 |
if (status || type != REG_SZ) |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
125 |
continue; |
126 |
||
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
127 |
buf_truncate(namebuf); |
128 |
buf_append_from_utf16le(namebuf, name); |
|
129 |
if (buf_error(namebuf)) { |
|
130 |
ret = buf_free(namebuf); |
|
131 |
namebuf = NULL; |
|
132 |
break; |
|
133 |
}
|
|
134 |
||
1416
by David Woodhouse
Print error when no TAP interfaces found |
135 |
found++; |
136 |
||
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
137 |
if (vpninfo->ifname && strcmp(namebuf->data, vpninfo->ifname)) { |
1544
by Kevin Cernekee
Change most PRG_TRACE prints to PRG_DEBUG |
138 |
vpn_progress(vpninfo, PRG_DEBUG, |
1709
by David Woodhouse
Fix tun device matching with --interface on Windows |
139 |
_("Ignoring non-matching TAP interface \"%s\"\n"), |
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
140 |
namebuf->data); |
1432
by David Woodhouse
Move Windows interface name matching into search_taps() function |
141 |
continue; |
142 |
}
|
|
143 |
||
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
144 |
ret = cb(vpninfo, buf, namebuf->data); |
1433
by David Woodhouse
Clean up search_taps() function |
145 |
if (!all) |
146 |
break; |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
147 |
}
|
148 |
||
149 |
RegCloseKey(adapters_key); |
|
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
150 |
buf_free(namebuf); |
1416
by David Woodhouse
Print error when no TAP interfaces found |
151 |
|
152 |
if (!found) |
|
153 |
vpn_progress(vpninfo, PRG_ERR, |
|
154 |
_("No Windows-TAP adapters found. Is the driver installed?\n")); |
|
155 |
||
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
156 |
return ret; |
157 |
}
|
|
158 |
||
2479
by David Woodhouse
Add TUNIDX for Windows vpnc-script |
159 |
static int get_adapter_index(struct openconnect_info *vpninfo, char *guid) |
160 |
{
|
|
161 |
struct oc_text_buf *buf = buf_alloc(); |
|
162 |
IP_ADAPTER_INFO *adapter; |
|
163 |
void *adapters_buf; |
|
164 |
ULONG idx; |
|
165 |
DWORD status; |
|
166 |
int ret = -EINVAL; |
|
167 |
||
168 |
vpninfo->tun_idx = -1; |
|
169 |
||
170 |
buf_append_utf16le(buf, "\\device\\tcpip_"); |
|
171 |
buf_append_utf16le(buf, guid); |
|
172 |
if (buf_error(buf)) { |
|
173 |
/* If we didn't manage to malloc for this, we're never
|
|
174 |
* going to manage for GetAdaptersInfo(). Give up. */
|
|
175 |
return buf_free(buf); |
|
176 |
}
|
|
177 |
||
178 |
status = GetAdapterIndex((void *)buf->data, &idx); |
|
179 |
buf_free(buf); |
|
180 |
if (status == NO_ERROR) { |
|
181 |
vpninfo->tun_idx = idx; |
|
182 |
return 0; |
|
183 |
} else { |
|
184 |
char *errstr = openconnect__win32_strerror(status); |
|
185 |
vpn_progress(vpninfo, PRG_INFO, |
|
186 |
_("GetAdapterIndex() failed: %s\nFalling back to GetAdaptersInfo()\n"), |
|
187 |
errstr); |
|
188 |
free(errstr); |
|
189 |
}
|
|
190 |
idx = 0; |
|
191 |
status = GetAdaptersInfo(NULL, &idx); |
|
192 |
if (status != ERROR_BUFFER_OVERFLOW) |
|
193 |
return -EIO; |
|
194 |
adapters_buf = malloc(idx); |
|
195 |
if (!adapters_buf) |
|
196 |
return -ENOMEM; |
|
197 |
status = GetAdaptersInfo(adapters_buf, &idx); |
|
198 |
if (status != NO_ERROR) { |
|
199 |
char *errstr = openconnect__win32_strerror(status); |
|
200 |
vpn_progress(vpninfo, PRG_ERR, _("GetAdaptersInfo() failed: %s\n"), errstr); |
|
201 |
free(errstr); |
|
202 |
free(adapters_buf); |
|
203 |
return -EIO; |
|
204 |
}
|
|
205 |
||
206 |
for (adapter = adapters_buf; adapter; adapter = adapter->Next) { |
|
207 |
if (!strcmp(adapter->AdapterName, guid)) { |
|
208 |
vpninfo->tun_idx = adapter->Index; |
|
209 |
ret = 0; |
|
210 |
break; |
|
211 |
}
|
|
212 |
}
|
|
213 |
||
214 |
free(adapters_buf); |
|
215 |
return ret; |
|
216 |
}
|
|
217 |
||
1433
by David Woodhouse
Clean up search_taps() function |
218 |
static intptr_t open_tun(struct openconnect_info *vpninfo, char *guid, char *name) |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
219 |
{
|
220 |
char devname[80]; |
|
221 |
HANDLE tun_fh; |
|
222 |
ULONG data[3]; |
|
223 |
DWORD len; |
|
224 |
||
225 |
snprintf(devname, sizeof(devname), DEVTEMPLATE, guid); |
|
1697
by David Woodhouse
Handle non-ASCII tun device names under Windows |
226 |
tun_fh = CreateFileA(devname, GENERIC_WRITE|GENERIC_READ, 0, 0, |
227 |
OPEN_EXISTING, |
|
228 |
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, |
|
229 |
0); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
230 |
if (tun_fh == INVALID_HANDLE_VALUE) { |
231 |
vpn_progress(vpninfo, PRG_ERR, _("Failed to open %s\n"), |
|
232 |
devname); |
|
233 |
return -1; |
|
234 |
||
235 |
}
|
|
1698
by David Woodhouse
Print name of Windows tun device not devname |
236 |
vpn_progress(vpninfo, PRG_DEBUG, _("Opened tun device %s\n"), name); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
237 |
|
238 |
if (!DeviceIoControl(tun_fh, TAP_IOCTL_GET_VERSION, |
|
1792
by David Woodhouse
Fix DeviceIoControl() calls to make NDIS6 TAP-Windows driver happy |
239 |
data, sizeof(&data), data, sizeof(data), |
240 |
&len, NULL)) { |
|
1827
by David Woodhouse
Print error message strings on Windows |
241 |
char *errstr = openconnect__win32_strerror(GetLastError()); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
242 |
|
243 |
vpn_progress(vpninfo, PRG_ERR, |
|
1827
by David Woodhouse
Print error message strings on Windows |
244 |
_("Failed to obtain TAP driver version: %s\n"), errstr); |
245 |
free(errstr); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
246 |
return -1; |
247 |
}
|
|
248 |
if (data[0] < 9 || (data[0] == 9 && data[1] < 9)) { |
|
249 |
vpn_progress(vpninfo, PRG_ERR, |
|
250 |
_("Error: TAP-Windows driver v9.9 or greater is required (found %ld.%ld)\n"), |
|
251 |
data[0], data[1]); |
|
252 |
return -1; |
|
253 |
}
|
|
1544
by Kevin Cernekee
Change most PRG_TRACE prints to PRG_DEBUG |
254 |
vpn_progress(vpninfo, PRG_DEBUG, "TAP-Windows driver v%ld.%ld (%ld)\n", |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
255 |
data[0], data[1], data[2]); |
256 |
||
257 |
data[0] = inet_addr(vpninfo->ip_info.addr); |
|
2478
by David Woodhouse
Better attempt at handling TAP-Windows tun setup |
258 |
/* Set network and mask both to 0.0.0.0. It's not about routing;
|
259 |
* it just ensures that the TAP driver fakes ARP responses for
|
|
260 |
* *everything* we throw at it, and we can just configure them
|
|
261 |
* as on-link routes. */
|
|
262 |
data[1] = 0; |
|
263 |
data[2] = 0; |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
264 |
|
265 |
if (!DeviceIoControl(tun_fh, TAP_IOCTL_CONFIG_TUN, |
|
1792
by David Woodhouse
Fix DeviceIoControl() calls to make NDIS6 TAP-Windows driver happy |
266 |
data, sizeof(data), data, sizeof(data), |
267 |
&len, NULL)) { |
|
1827
by David Woodhouse
Print error message strings on Windows |
268 |
char *errstr = openconnect__win32_strerror(GetLastError()); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
269 |
|
270 |
vpn_progress(vpninfo, PRG_ERR, |
|
1827
by David Woodhouse
Print error message strings on Windows |
271 |
_("Failed to set TAP IP addresses: %s\n"), errstr); |
272 |
free(errstr); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
273 |
return -1; |
274 |
}
|
|
275 |
||
276 |
data[0] = 1; |
|
277 |
if (!DeviceIoControl(tun_fh, TAP_IOCTL_SET_MEDIA_STATUS, |
|
1792
by David Woodhouse
Fix DeviceIoControl() calls to make NDIS6 TAP-Windows driver happy |
278 |
data, sizeof(data[0]), data, sizeof(data[0]), |
279 |
&len, NULL)) { |
|
1827
by David Woodhouse
Print error message strings on Windows |
280 |
char *errstr = openconnect__win32_strerror(GetLastError()); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
281 |
|
282 |
vpn_progress(vpninfo, PRG_ERR, |
|
1827
by David Woodhouse
Print error message strings on Windows |
283 |
_("Failed to set TAP media status: %s\n"), errstr); |
284 |
free(errstr); |
|
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
285 |
return -1; |
286 |
}
|
|
287 |
if (!vpninfo->ifname) |
|
288 |
vpninfo->ifname = strdup(name); |
|
289 |
||
2479
by David Woodhouse
Add TUNIDX for Windows vpnc-script |
290 |
get_adapter_index(vpninfo, guid); |
291 |
||
1434
by David Woodhouse
Make openconnect_setup_tun_fd() work on Windows |
292 |
return (intptr_t)tun_fh; |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
293 |
}
|
294 |
||
1434
by David Woodhouse
Make openconnect_setup_tun_fd() work on Windows |
295 |
intptr_t os_setup_tun(struct openconnect_info *vpninfo) |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
296 |
{
|
1434
by David Woodhouse
Make openconnect_setup_tun_fd() work on Windows |
297 |
return search_taps(vpninfo, open_tun, 0); |
1392
by David Woodhouse
Add basic support for opening Windows TAP driver |
298 |
}
|
1423
by David Woodhouse
Factor out os_read_tun() from tun_mainloop() |
299 |
|
1503
by David Woodhouse
Fix Windows tun read handling |
300 |
int os_read_tun(struct openconnect_info *vpninfo, struct pkt *pkt) |
1423
by David Woodhouse
Factor out os_read_tun() from tun_mainloop() |
301 |
{
|
302 |
DWORD pkt_size; |
|
303 |
||
1503
by David Woodhouse
Fix Windows tun read handling |
304 |
reread: |
305 |
if (!vpninfo->tun_rd_pending && |
|
306 |
!ReadFile(vpninfo->tun_fh, pkt->data, pkt->len, &pkt_size, |
|
307 |
&vpninfo->tun_rd_overlap)) { |
|
308 |
DWORD err = GetLastError(); |
|
309 |
||
310 |
if (err == ERROR_IO_PENDING) |
|
311 |
vpninfo->tun_rd_pending = 1; |
|
1840
by David Woodhouse
Handle ERROR_OPERATION_ABORTED on Windows TAP device |
312 |
else if (err == ERROR_OPERATION_ABORTED) { |
313 |
vpninfo->quit_reason = "TAP device aborted"; |
|
314 |
vpn_progress(vpninfo, PRG_ERR, |
|
315 |
_("TAP device aborted connectivity. Disconnecting.\n")); |
|
316 |
return -1; |
|
317 |
} else { |
|
1827
by David Woodhouse
Print error message strings on Windows |
318 |
char *errstr = openconnect__win32_strerror(err); |
1503
by David Woodhouse
Fix Windows tun read handling |
319 |
vpn_progress(vpninfo, PRG_ERR, |
1827
by David Woodhouse
Print error message strings on Windows |
320 |
_("Failed to read from TAP device: %s\n"), |
321 |
errstr); |
|
322 |
free(errstr); |
|
323 |
}
|
|
1503
by David Woodhouse
Fix Windows tun read handling |
324 |
return -1; |
325 |
} else if (!GetOverlappedResult(vpninfo->tun_fh, |
|
326 |
&vpninfo->tun_rd_overlap, &pkt_size, |
|
327 |
FALSE)) { |
|
328 |
DWORD err = GetLastError(); |
|
329 |
||
330 |
if (err != ERROR_IO_INCOMPLETE) { |
|
1827
by David Woodhouse
Print error message strings on Windows |
331 |
char *errstr = openconnect__win32_strerror(err); |
1503
by David Woodhouse
Fix Windows tun read handling |
332 |
vpninfo->tun_rd_pending = 0; |
333 |
vpn_progress(vpninfo, PRG_ERR, |
|
1827
by David Woodhouse
Print error message strings on Windows |
334 |
_("Failed to complete read from TAP device: %s\n"), |
335 |
errstr); |
|
336 |
free(errstr); |
|
1503
by David Woodhouse
Fix Windows tun read handling |
337 |
goto reread; |
338 |
}
|
|
339 |
return -1; |
|
1423
by David Woodhouse
Factor out os_read_tun() from tun_mainloop() |
340 |
}
|
341 |
||
1503
by David Woodhouse
Fix Windows tun read handling |
342 |
/* Either a straight ReadFile() or a subsequent GetOverlappedResult()
|
343 |
succeeded... */
|
|
344 |
vpninfo->tun_rd_pending = 0; |
|
1423
by David Woodhouse
Factor out os_read_tun() from tun_mainloop() |
345 |
pkt->len = pkt_size; |
346 |
return 0; |
|
347 |
}
|
|
1424
by David Woodhouse
Factor out os_write_tun() from tun_mainloop() |
348 |
|
349 |
int os_write_tun(struct openconnect_info *vpninfo, struct pkt *pkt) |
|
350 |
{
|
|
351 |
DWORD pkt_size = 0; |
|
352 |
DWORD err; |
|
1827
by David Woodhouse
Print error message strings on Windows |
353 |
char *errstr; |
1424
by David Woodhouse
Factor out os_write_tun() from tun_mainloop() |
354 |
|
355 |
if (WriteFile(vpninfo->tun_fh, pkt->data, pkt->len, &pkt_size, &vpninfo->tun_wr_overlap)) { |
|
356 |
vpn_progress(vpninfo, PRG_TRACE, |
|
357 |
_("Wrote %ld bytes to tun\n"), pkt_size); |
|
358 |
return 0; |
|
359 |
}
|
|
360 |
||
361 |
err = GetLastError(); |
|
362 |
if (err == ERROR_IO_PENDING) { |
|
363 |
/* Theoretically we should let the mainloop handle this blocking,
|
|
364 |
but that's non-trivial and it doesn't ever seem to happen in
|
|
365 |
practice anyway. */
|
|
366 |
vpn_progress(vpninfo, PRG_TRACE, |
|
367 |
_("Waiting for tun write...\n")); |
|
368 |
if (GetOverlappedResult(vpninfo->tun_fh, &vpninfo->tun_wr_overlap, &pkt_size, TRUE)) { |
|
369 |
vpn_progress(vpninfo, PRG_TRACE, |
|
370 |
_("Wrote %ld bytes to tun after waiting\n"), pkt_size); |
|
371 |
return 0; |
|
372 |
}
|
|
373 |
err = GetLastError(); |
|
374 |
}
|
|
1827
by David Woodhouse
Print error message strings on Windows |
375 |
errstr = openconnect__win32_strerror(err); |
1424
by David Woodhouse
Factor out os_write_tun() from tun_mainloop() |
376 |
vpn_progress(vpninfo, PRG_ERR, |
1827
by David Woodhouse
Print error message strings on Windows |
377 |
_("Failed to write to TAP device: %s\n"), errstr); |
378 |
free(errstr); |
|
1424
by David Woodhouse
Factor out os_write_tun() from tun_mainloop() |
379 |
return -1; |
380 |
}
|
|
1426
by David Woodhouse
Split out os_shutdown_tun() for Windows vs. sane platforms |
381 |
|
382 |
void os_shutdown_tun(struct openconnect_info *vpninfo) |
|
383 |
{
|
|
384 |
script_config_tun(vpninfo, "disconnect"); |
|
385 |
CloseHandle(vpninfo->tun_fh); |
|
386 |
vpninfo->tun_fh = NULL; |
|
387 |
CloseHandle(vpninfo->tun_rd_overlap.hEvent); |
|
388 |
vpninfo->tun_rd_overlap.hEvent = NULL; |
|
389 |
}
|
|
1427
by David Woodhouse
Move Windows openconnect_setup_tun_fd() to tun-win32.c |
390 |
|
1434
by David Woodhouse
Make openconnect_setup_tun_fd() work on Windows |
391 |
int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, intptr_t tun_fd) |
1427
by David Woodhouse
Move Windows openconnect_setup_tun_fd() to tun-win32.c |
392 |
{
|
1434
by David Woodhouse
Make openconnect_setup_tun_fd() work on Windows |
393 |
vpninfo->tun_fh = (HANDLE)tun_fd; |
394 |
vpninfo->tun_rd_overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
395 |
monitor_read_fd(vpninfo, tun); |
|
396 |
||
1427
by David Woodhouse
Move Windows openconnect_setup_tun_fd() to tun-win32.c |
397 |
return 0; |
398 |
}
|
|
1435
by David Woodhouse
Add openconnect_setup_tun_script() stub for Windows |
399 |
|
1805
by David Woodhouse
Bump library soname and add 'const' to lots of char * arguments |
400 |
int openconnect_setup_tun_script(struct openconnect_info *vpninfo, |
401 |
const char *tun_script) |
|
1435
by David Woodhouse
Add openconnect_setup_tun_script() stub for Windows |
402 |
{
|
403 |
vpn_progress(vpninfo, PRG_ERR, |
|
404 |
_("Spawning tunnel scripts is not yet supported on Windows\n")); |
|
405 |
return -1; |
|
406 |
}
|