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.2 by pcg, Tue Oct 14 03:22:09 2003 UTC vs.
Revision 1.3 by pcg, Wed Oct 15 00:25:15 2003 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 Marc Lehmann <ocg@goof.com>
4 Copyright (C) 2002-2003 Ivo Timmermans <ivo@o2w.nl>,
5 2002-2003 Guus Sliepen <guus@sliepen.eu.org>
4 6
5 This program is free software; you can redistribute it and/or modify 7 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 8 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or 9 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version. 10 (at your option) any later version.
21// and the default cipedrvr uses a different MAC address than we do, 23// and the default cipedrvr uses a different MAC address than we do,
22// so this module tries to fix mac addresses in packets and arp packets. 24// so this module tries to fix mac addresses in packets and arp packets.
23// this is probably not very fast, but neither is cygwin nor poll. 25// this is probably not very fast, but neither is cygwin nor poll.
24// 26//
25// http://cipe-win32.sourceforge.net/ 27// http://cipe-win32.sourceforge.net/
28// a newer driver is available as part of the openvpn package:
29// http://openvpn.sf.net/
26 30
27#include "config.h" 31#include "config.h"
28 32
29#include <stdio.h> 33#include <stdio.h>
30#include <errno.h> 34#include <errno.h>
36#include <cstring> 40#include <cstring>
37 41
38#include "conf.h" 42#include "conf.h"
39#include "util.h" 43#include "util.h"
40 44
45#include <w32api/windows.h>
46#include <w32api/winioctl.h>
47
48#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
49
50#define USERMODEDEVICEDIR "\\\\.\\"
51#define USERDEVICEDIR "\\??\\"
52#define TAPSUFFIX ".tap"
53
54#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
55
56#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
57#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
58#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
59
60static HANDLE device_handle = INVALID_HANDLE_VALUE;
61
62static const char *
63wstrerror (int err)
64{
65 static char buf[1024];
66
67 if (!FormatMessage
68 (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
69 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
70 {
71 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
72 };
73
74 if ((char *newline = strchr (buf, '\r')))
75 *newline = '\0';
76
77 return buf;
78}
79
41const char * 80const char *
42tap_device::info () 81tap_device::info ()
43{ 82{
44 return _("broken cygwin cipe device"); 83 return _("cygwin cipe/openvpn tap device");
45} 84}
46 85
47tap_device::tap_device () 86tap_device::tap_device ()
48{ 87{
49 if ((fd = open (conf.ifname, O_RDWR)) < 0) 88 HKEY key, key2;
50 { 89 int i;
51 slog (L_CRIT, _("could not open %s: %s"), conf.ifname, strerror (errno)); 90
52 exit (1); 91 char regpath[1024];
92 char adapterid[1024];
93 char adaptername[1024];
94 char tapname[1024];
95 long len;
96
97 bool found = false;
98
99 int sock, err;
100
101 /* Open registry and look for network adapters */
102
103 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
53 } 104 {
105 slog (L_ERR, _("Unable to read registry: %s"),
106 wstrerror (GetLastError ()));
107 return false;
108 }
109
110 for (i = 0;; i++)
111 {
112 len = sizeof (adapterid);
113 if (RegEnumKeyEx (key, i, adapterid, &len, 0, 0, 0, NULL))
114 break;
115
116 /* Find out more about this adapter */
117
118 snprintf (regpath, sizeof (regpath), "%s\\%s\\Connection",
119 REG_CONTROL_NET, adapterid);
120
121 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
122 continue;
123
124 len = sizeof (adaptername);
125 err = RegQueryValueEx (key2, "Name", 0, 0, adaptername, &len);
126
127 RegCloseKey (key2);
128
129 if (err)
130 continue;
131
132 if (strcmp (conf.ifname, adapterid))
133 continue;
134
135 found = true;
136 break;
137
138 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX,
139 adapterid);
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,
141 0);
142 if (device_handle != INVALID_HANDLE_VALUE)
143 {
144 found = true;
145 break;
146 }
147 }
148
149 RegCloseKey (key);
150
151 if (!found)
152 {
153 slog (L_ERR, _("No Windows tap device found!"));
154 return false;
155 }
156
157 if (!device)
158 device = xstrdup (adapterid);
159
160 if (!iface)
161 iface = xstrdup (adaptername);
162
163 /* Try to open the corresponding tap device */
164
165 if (device_handle == INVALID_HANDLE_VALUE)
166 {
167 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX,
168 device);
169 device_handle =
170 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
171 OPEN_EXISTING,
172 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
173 }
174
175 if (device_handle == INVALID_HANDLE_VALUE)
176 {
177 slog (L_ERR, _("%s (%s) is not a usable Windows tap device: %s"),
178 device, iface, wstrerror (GetLastError ()));
179 return false;
180 }
181
182 /* Get MAC address from tap device */
183
184 if (!DeviceIoControl
185 (device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof (mymac.x), mymac.x,
186 sizeof (mymac.x), &len, 0))
187 {
188 slog (L_ERR,
189 _
190 ("Could not get MAC address from Windows tap device %s (%s): %s"),
191 device, iface, wstrerror (GetLastError ()));
192 return false;
193 }
194
195 if (routing_mode == RMODE_ROUTER)
196 {
197 overwrite_mac = 1;
198 }
199
200 /* Create a listening socket */
201
202 err = getaddrinfo (NULL, myport, &hint, &ai);
203
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);
239
240 if (!thread)
241 {
242 slog (L_ERR, _("System call `%s' failed: %s"), "CreateThread",
243 wstrerror (GetLastError ()));
244 return false;
245 }
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
54} 265}
55 266
56tap_device::~tap_device () 267tap_device::~tap_device ()
57{ 268{
58 close (fd); 269 close (fd);
66 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 277 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU);
67 278
68 if (pkt->len <= 0) 279 if (pkt->len <= 0)
69 { 280 {
70 slog (L_ERR, _("error while reading from %s %s: %s"), 281 slog (L_ERR, _("error while reading from %s %s: %s"),
71 info (), conf.ifname, strerror (errno)); 282 info (), conf.ifname, strerror (errno));
72 free (pkt); 283 free (pkt);
73 return 0; 284 return 0;
74 } 285 }
75 286
76 id2mac (THISNODE->id, &((*pkt)[6])); 287 id2mac (THISNODE->id, &((*pkt)[6]));
77 288
78 if (pkt->is_arp ()) 289 if (pkt->is_arp ())
79 { 290 {
80 if ((*pkt)[22] == 0x08) id2mac (THISNODE->id, &((*pkt)[22])); 291 if ((*pkt)[22] == 0x08)
81 if ((*pkt)[32] == 0x08) id2mac (THISNODE->id, &((*pkt)[32])); 292 id2mac (THISNODE->id, &((*pkt)[22]));
293 if ((*pkt)[32] == 0x08)
294 id2mac (THISNODE->id, &((*pkt)[32]));
82 } 295 }
83 296
84 return pkt; 297 return pkt;
85} 298}
86 299
87void 300void
88tap_device::send (tap_packet *pkt) 301tap_device::send (tap_packet * pkt)
89{ 302{
90 (*pkt)[ 6] = 0x08; (*pkt)[ 7] = 0x00; (*pkt)[ 8] = 0x58; 303 (*pkt)[6] = 0x08;
91 (*pkt)[ 9] = 0x00; (*pkt)[10] = 0x00; (*pkt)[11] = 0x01; 304 (*pkt)[7] = 0x00;
305 (*pkt)[8] = 0x58;
306 (*pkt)[9] = 0x00;
307 (*pkt)[10] = 0x00;
308 (*pkt)[11] = 0x01;
92 309
93 if (pkt->is_arp ()) 310 if (pkt->is_arp ())
94 { 311 {
95 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 312 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
96 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 313 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac));
97 314
98 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 315 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
99 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 316 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac));
100 } 317 }
101 318
102 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 319 if (write (fd, &((*pkt)[0]), pkt->len) < 0)
103 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 320 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname,
104 strerror (errno)); 321 strerror (errno));
105} 322}
323
324#if 0
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 {
345 if (GetLastError () == ERROR_IO_PENDING)
346 {
347 WaitForSingleObject (overlapped.hEvent, INFINITE);
348 if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE))
349 continue;
350 }
351 else
352 {
353 slog (L_ERR, _("Error while reading from %s %s: %s"),
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 {
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}
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