ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/device-cygwin.C
(Generate patch)

Comparing gvpe/src/device-cygwin.C (file contents):
Revision 1.3 by pcg, Wed Oct 15 00:25:15 2003 UTC vs.
Revision 1.12 by pcg, Thu Aug 7 17:54:26 2008 UTC

1/* 1/*
2 device-cygwin.C -- Stub for Cygwin environment 2 device-cygwin.C -- Stub for Cygwin environment
3 Copyright (C) 2003 Marc Lehmann <ocg@goof.com> 3 Copyright (C) 2003-2008 Marc Lehmann <ocg@goof.com>
4 Copyright (C) 2002-2003 Ivo Timmermans <ivo@o2w.nl>, 4 Copyright (C) 2002-2003 Ivo Timmermans <ivo@o2w.nl>,
5 2002-2003 Guus Sliepen <guus@sliepen.eu.org> 5 2002-2003 Guus Sliepen <guus@sliepen.eu.org>
6 6
7 This file is part of GVPE.
8
7 This program is free software; you can redistribute it and/or modify 9 GVPE is free software; you can redistribute it and/or modify it
8 it under the terms of the GNU General Public License as published by 10 under the terms of the GNU General Public License as published by the
9 the Free Software Foundation; either version 2 of the License, or 11 Free Software Foundation; either version 3 of the License, or (at your
10 (at your option) any later version. 12 option) any later version.
11 13
12 This program is distributed in the hope that it will be useful, 14 This program is distributed in the hope that it will be useful, but
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 GNU General Public License for more details. 17 Public License for more details.
16 18
17 You should have received a copy of the GNU General Public License 19 You should have received a copy of the GNU General Public License along
18 along with this program; if not, write to the Free Software 20 with this program; if not, see <http://www.gnu.org/licenses/>.
19 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21
22 Additional permission under GNU GPL version 3 section 7
23
24 If you modify this Program, or any covered work, by linking or
25 combining it with the OpenSSL project's OpenSSL library (or a modified
26 version of that library), containing parts covered by the terms of the
27 OpenSSL or SSLeay licenses, the licensors of this Program grant you
28 additional permission to convey the resulting work. Corresponding
29 Source for a non-source form of such a combination shall include the
30 source code for the parts of OpenSSL used as well as that of the
31 covered work.
20*/ 32*/
21 33
22// unfortunately, there is be no way to set MAC addresses under windows, 34// unfortunately, there is be no way to set MAC addresses under windows,
23// and the default cipedrvr uses a different MAC address than we do, 35// and the default cipedrvr uses a different MAC address than we do,
24// so this module tries to fix mac addresses in packets and arp packets. 36// so this module tries to fix mac addresses in packets and arp packets.
28// a newer driver is available as part of the openvpn package: 40// a newer driver is available as part of the openvpn package:
29// http://openvpn.sf.net/ 41// http://openvpn.sf.net/
30 42
31#include "config.h" 43#include "config.h"
32 44
33#include <stdio.h> 45#include <cstdio>
46#include <cstring>
47#include <cstdlib>
34#include <errno.h> 48#include <errno.h>
35#include <sys/types.h> 49#include <sys/types.h>
36#include <sys/stat.h> 50#include <sys/stat.h>
37#include <fcntl.h> 51#include <fcntl.h>
38#include <unistd.h> 52#include <unistd.h>
39#include <syslog.h>
40#include <cstring>
41 53
42#include "conf.h" 54#include "conf.h"
43#include "util.h" 55#include "util.h"
44 56
57#include <io.h>
45#include <w32api/windows.h> 58#include <w32api/windows.h>
46#include <w32api/winioctl.h> 59#include <w32api/winioctl.h>
47 60
48#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 61#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
49 62
51#define USERDEVICEDIR "\\??\\" 64#define USERDEVICEDIR "\\??\\"
52#define TAPSUFFIX ".tap" 65#define TAPSUFFIX ".tap"
53 66
54#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS) 67#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
55 68
56#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED) 69#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
57#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED) 70#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
58#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED) 71#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
59 72#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(7, METHOD_BUFFERED)
60static HANDLE device_handle = INVALID_HANDLE_VALUE;
61 73
62static const char * 74static const char *
63wstrerror (int err) 75wstrerror (int err)
64{ 76{
65 static char buf[1024]; 77 static char buf[1024];
69 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL)) 81 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
70 { 82 {
71 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf)); 83 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
72 }; 84 };
73 85
86 char *nl;
74 if ((char *newline = strchr (buf, '\r'))) 87 if ((nl = strchr (buf, '\r')))
75 *newline = '\0'; 88 *nl = '\0';
76 89
77 return buf; 90 return buf;
91}
92
93static HANDLE device_handle = INVALID_HANDLE_VALUE;
94static mac local_mac;
95static tap_packet *rcv_pkt;
96static int iopipe[2];
97static HANDLE pipe_handle, send_event, thread;
98
99static DWORD WINAPI
100read_thread(void *)
101{
102 static OVERLAPPED overlapped;
103 static DWORD dlen;
104 static u32 len;
105 static u8 data[MAX_MTU];
106
107 overlapped.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
108
109 for (;;)
110 {
111 if (!ReadFile (device_handle, data, MAX_MTU, &dlen, &overlapped))
112 {
113 if (GetLastError () == ERROR_IO_PENDING)
114 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
115 else
116 {
117 slog (L_ERR, "WIN32 TAP: ReadFile returned error: %s", wstrerror (GetLastError ()));
118 exit (EXIT_FAILURE);
119 }
120 }
121
122 if (dlen > 0)
123 {
124 len = dlen;
125 WriteFile (pipe_handle, &len, sizeof (len), &dlen, NULL);
126 WriteFile (pipe_handle, data, len, &dlen, NULL);
127 }
128 }
78} 129}
79 130
80const char * 131const char *
81tap_device::info () 132tap_device::info ()
82{ 133{
83 return _("cygwin cipe/openvpn tap device"); 134 return _("cygwin cipe/openvpn tap device");
84} 135}
85 136
137const char *
138tap_device::if_up ()
139{
140 return "";
141}
142
86tap_device::tap_device () 143tap_device::tap_device ()
87{ 144{
88 HKEY key, key2; 145 HKEY key, key2;
89 int i; 146 int i;
90 147
91 char regpath[1024]; 148 char regpath[1024];
92 char adapterid[1024]; 149 char adapterid[1024];
93 char adaptername[1024]; 150 BYTE adaptername[1024];
94 char tapname[1024]; 151 char tapname[1024];
95 long len; 152 DWORD len;
96 153
97 bool found = false; 154 bool found = false;
98 155
99 int sock, err; 156 int sock, err;
100 157
101 /* Open registry and look for network adapters */ 158 /* Open registry and look for network adapters */
102 159
103 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key)) 160 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
104 { 161 {
105 slog (L_ERR, _("Unable to read registry: %s"), 162 slog (L_ERR, _("WIN32 TAP: unable to read registry: %s"),
106 wstrerror (GetLastError ())); 163 wstrerror (GetLastError ()));
107 return false; 164 exit (EXIT_FAILURE);
108 } 165 }
109 166
110 for (i = 0;; i++) 167 for (i = 0;; i++)
111 { 168 {
112 len = sizeof (adapterid); 169 len = sizeof (adapterid);
127 RegCloseKey (key2); 184 RegCloseKey (key2);
128 185
129 if (err) 186 if (err)
130 continue; 187 continue;
131 188
189 if (conf.ifname)
190 {
132 if (strcmp (conf.ifname, adapterid)) 191 if (strcmp (conf.ifname, adapterid))
133 continue; 192 continue;
134 193 }
194 else
195 {
135 found = true; 196 found = true;
136 break; 197 break;
198 }
137 199
138 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, 200 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
139 adapterid); 201 device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
140 device_handle = CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, indent: Standard input: 237: Error:Stmt nesting error.FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 202 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
141 0);
142 if (device_handle != INVALID_HANDLE_VALUE) 203 if (device_handle != INVALID_HANDLE_VALUE)
143 { 204 {
144 found = true; 205 found = true;
145 break; 206 break;
146 } 207 }
148 209
149 RegCloseKey (key); 210 RegCloseKey (key);
150 211
151 if (!found) 212 if (!found)
152 { 213 {
153 slog (L_ERR, _("No Windows tap device found!")); 214 slog (L_ERR, _("WIN32 TAP: no windows tap device found!"));
154 return false; 215 exit (EXIT_FAILURE);
155 } 216 }
156
157 if (!device)
158 device = xstrdup (adapterid);
159
160 if (!iface)
161 iface = xstrdup (adaptername);
162 217
163 /* Try to open the corresponding tap device */ 218 /* Try to open the corresponding tap device */
164 219
165 if (device_handle == INVALID_HANDLE_VALUE) 220 if (device_handle == INVALID_HANDLE_VALUE)
166 { 221 {
167 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, 222 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
168 device);
169 device_handle = 223 device_handle =
170 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, 224 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
171 OPEN_EXISTING, 225 OPEN_EXISTING,
172 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); 226 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
173 } 227 }
174 228
175 if (device_handle == INVALID_HANDLE_VALUE) 229 if (device_handle == INVALID_HANDLE_VALUE)
176 { 230 {
177 slog (L_ERR, _("%s (%s) is not a usable Windows tap device: %s"), 231 slog (L_ERR, _("WIN32 TAP: %s is not a usable windows tap device %s: %s"),
178 device, iface, wstrerror (GetLastError ())); 232 adaptername, tapname, wstrerror (GetLastError ()));
179 return false; 233 exit (EXIT_FAILURE);
180 } 234 }
235
236 strcpy (ifrname, (char *)tapname);
181 237
182 /* Get MAC address from tap device */ 238 /* Get MAC address from tap device */
183 239
184 if (!DeviceIoControl 240 if (!DeviceIoControl (device_handle, TAP_IOCTL_GET_MAC,
185 (device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof (mymac.x), mymac.x, 241 &local_mac, sizeof (local_mac), &local_mac, sizeof (local_mac),
186 sizeof (mymac.x), &len, 0)) 242 &len, 0))
187 { 243 {
188 slog (L_ERR, 244 slog (L_ERR,
189 _
190 ("Could not get MAC address from Windows tap device %s (%s): %s"), 245 _("WIN32 TAP: could not get MAC address from windows tap device %s: %s"),
191 device, iface, wstrerror (GetLastError ())); 246 adaptername, wstrerror (GetLastError ()));
192 return false; 247 exit (EXIT_FAILURE);
193 }
194
195 if (routing_mode == RMODE_ROUTER)
196 { 248 }
197 overwrite_mac = 1;
198 }
199 249
200 /* Create a listening socket */ 250 pipe (iopipe);
251 fd = iopipe[0];
252 pipe_handle = (HANDLE) get_osfhandle (iopipe[1]);
201 253
202 err = getaddrinfo (NULL, myport, &hint, &ai); 254 send_event = CreateEvent (NULL, FALSE, FALSE, NULL);
203 255
204 if (err || !ai)
205 {
206 slog (L_ERR, _("System call `%s' failed: %s"), "getaddrinfo",
207 gai_strerror (errno));
208 return false;
209 }
210
211 sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
212
213 if (sock < 0)
214 {
215 slog (L_ERR, _("System call `%s' failed: %s"), "socket",
216 strerror (errno));
217 return false;
218 }
219
220 if (bind (sock, ai->ai_addr, ai->ai_addrlen))
221 {
222 slog (L_ERR, _("System call `%s' failed: %s"), "bind",
223 strerror (errno));
224 return false;
225 }
226
227 freeaddrinfo (ai);
228
229 if (listen (sock, 1))
230 {
231 slog (L_ERR, _("System call `%s' failed: %s"), "listen",
232 strerror (errno));
233 return false;
234 }
235
236 /* Start the tap reader */
237
238 thread = CreateThread (NULL, 0, tapreader, NULL, 0, NULL); 256 thread = CreateThread (NULL, 0, read_thread, NULL, 0, NULL);
239 257
240 if (!thread) 258 /* try to set driver media status to 'connected' */
241 { 259 ULONG status = TRUE;
242 slog (L_ERR, _("System call `%s' failed: %s"), "CreateThread", 260 DeviceIoControl (device_handle, TAP_IOCTL_SET_MEDIA_STATUS,
243 wstrerror (GetLastError ())); 261 &status, sizeof (status),
244 return false; 262 &status, sizeof (status), &len, NULL);
245 } 263 // ignore error here on purpose
246
247 /* Wait for the tap reader to connect back to us */
248
249 if ((device_fd = accept (sock, NULL, 0)) == -1)
250 {
251 slog (L_ERR, _("System call `%s' failed: %s"), "accept",
252 strerror (errno));
253 return false;
254 }
255
256 closesocket (sock);
257
258 device_info = _("Windows tap device");
259
260 slog (L_INFO, _("%s (%s) is a %s"), device, iface, device_info);
261
262 return true;
263}
264
265} 264}
266 265
267tap_device::~tap_device () 266tap_device::~tap_device ()
268{ 267{
269 close (fd); 268 close (iopipe[0]);
269 close (iopipe[1]);
270 CloseHandle (device_handle);
271 CloseHandle (send_event);
270} 272}
271 273
272tap_packet * 274tap_packet *
273tap_device::recv () 275tap_device::recv ()
274{ 276{
275 tap_packet *pkt = new tap_packet; 277 tap_packet *pkt = new tap_packet;
276 278
277 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 279 if (sizeof (u32) != read (iopipe[0], &pkt->len, sizeof (u32)))
278
279 if (pkt->len <= 0)
280 { 280 {
281 slog (L_ERR, _("error while reading from %s %s: %s"), 281 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt length"));
282 info (), conf.ifname, strerror (errno)); 282 delete pkt;
283 free (pkt);
284 return 0; 283 return 0;
285 } 284 }
286 285
286 if (pkt->len != read (iopipe[0], &((*pkt)[0]), pkt->len))
287 {
288 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt"));
289 delete pkt;
290 return 0;
291 }
292
287 id2mac (THISNODE->id, &((*pkt)[6])); 293 id2mac (THISNODE->id, &((*pkt)[6]));
288 294
289 if (pkt->is_arp ()) 295 if (pkt->is_arp ())
290 { 296 {
291 if ((*pkt)[22] == 0x08) 297 if (!memcmp (&(*pkt)[22], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[22]));
292 id2mac (THISNODE->id, &((*pkt)[22])); 298 if (!memcmp (&(*pkt)[32], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[32]));
293 if ((*pkt)[32] == 0x08)
294 id2mac (THISNODE->id, &((*pkt)[32]));
295 } 299 }
296 300
297 return pkt; 301 return pkt;
298} 302}
299 303
300void 304void
301tap_device::send (tap_packet * pkt) 305tap_device::send (tap_packet * pkt)
302{ 306{
303 (*pkt)[6] = 0x08; 307 memcpy (&(*pkt)[6], &local_mac, sizeof (mac));
304 (*pkt)[7] = 0x00;
305 (*pkt)[8] = 0x58;
306 (*pkt)[9] = 0x00;
307 (*pkt)[10] = 0x00;
308 (*pkt)[11] = 0x01;
309 308
310 if (pkt->is_arp ()) 309 if (pkt->is_arp ())
311 { 310 {
312 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 311 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
313 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 312 memcpy (&(*pkt)[22], &local_mac, sizeof (mac));
314 313
315 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 314 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
316 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 315 memcpy (&(*pkt)[32], &local_mac, sizeof (mac));
317 } 316 }
318 317
319 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 318 DWORD dlen;
320 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 319 OVERLAPPED overlapped;
321 strerror (errno)); 320 overlapped.hEvent = send_event;
322}
323 321
324#if 0 322 if (!WriteFile (device_handle, &((*pkt)[0]), pkt->len, &dlen, &overlapped))
325
326slog (L_DEBUG, _indent: Standard input:377: Error:Stmt nesting error.
327("Tap reader running"));
328
329 /* Read from tap device and send to parent */
330
331overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
332
333for indent
334: Standard input: 320: Error:Stmt nesting error.(;;
335 )
336{
337 overlapped.Offset = 0;
338 overlapped.OffsetHigh = 0;
339 ResetEvent (overlapped.hEvent);
340
341 status = ReadFile (device_handle, buf, sizeof (buf), &len, &overlapped);
342
343 if (!status)
344 { 323 {
345 if (GetLastError () == ERROR_IO_PENDING) 324 if (GetLastError () == ERROR_IO_PENDING)
346 {
347 WaitForSingleObject (overlapped.hEvent, INFINITE);
348 if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE)) 325 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
349 continue;
350 }
351 else 326 else
352 { 327 slog (L_ERR, _("WIN32 TAP: can't write to %s %s: %s"), info (), conf.ifname,
353 slog (L_ERR, _("Error while reading from %s %s: %s"), 328 wstrerror (GetLastError ()));
354 device_info, device, strerror (errno));
355 return -1;
356 }
357 }
358
359 if (send (sock, buf, len, 0) <= 0)
360 return -1;
361}
362}
363
364void
365close_device (void)
366{
367 cp ();
368
369 CloseHandle (device_handle);
370}
371
372bool
373read_packet (vpn_packet_t * packet)
374{
375 int lenin;
376
377 cp ();
378
379 if ((lenin = recv (device_fd, packet->data, MTU, 0)) <= 0)
380 { 329 }
381 slog (L_ERR, _("Error while reading from %s %s: %s"), device_info,
382 device, strerror (errno));
383 return false;
384 }
385
386 packet->len = lenin;
387
388 device_total_in += packet->len;
389
390 ifdebug (TRAFFIC) slog (L_DEBUG, _("Read packet of %d bytes from %s"),
391 packet->len, device_info);
392
393 return true;
394} 330}
395
396bool
397write_packet (vpn_packet_t * packet)
398{
399 long lenout;
400 OVERLAPPED overlapped = { 0 };
401
402 cp ();
403
404 ifdebug (TRAFFIC) slog (L_DEBUG, _("Writing packet of %d bytes to %s"),
405 packet->len, device_info);
406
407 if (!WriteFile
408 (device_handle, packet->data, packet->len, &lenout, &overlapped))
409 {
410 slog (L_ERR, _("Error while writing to %s %s: %s"), device_info,
411 device, wstrerror (GetLastError ()));
412 return false;
413 }
414
415 device_total_out += packet->len;
416
417 return true;
418}
419
420void
421dump_device_stats (void)
422{
423 cp ();
424
425 slog (L_DEBUG, _("Statistics for %s %s:"), device_info, device);
426 slog (L_DEBUG, _(" total bytes in: %10d"), device_total_in);
427 slog (L_DEBUG, _(" total bytes out: %10d"), device_total_out);
428}
429#endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines