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.1 by pcg, Sat Mar 1 15:53:03 2003 UTC vs.
Revision 1.5 by pcg, Wed Oct 15 01:38:24 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;
61static mac my_mac;
62
63static const char *
64wstrerror (int err)
65{
66 static char buf[1024];
67
68 if (!FormatMessage
69 (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
70 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
71 {
72 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
73 };
74
75 if ((char *newline = strchr (buf, '\r')))
76 *newline = '\0';
77
78 return buf;
79}
80
81const char *
82tap_device::info ()
83{
84 return _("cygwin cipe/openvpn tap device");
85}
86
41tap_device::tap_device () 87tap_device::tap_device ()
42{ 88{
43 if ((fd = open (conf.ifname, O_RDWR)) < 0) 89 HKEY key, key2;
90 int i;
91
92 char regpath[1024];
93 char adapterid[1024];
94 char adaptername[1024];
95 char tapname[1024];
96 long len;
97
98 bool found = false;
99
100 int sock, err;
101
102 /* Open registry and look for network adapters */
103
104 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
105 {
106 slog (L_ERR, _("Unable to read registry: %s"),
107 wstrerror (GetLastError ()));
108 return false;
44 { 109 }
45 slog (L_CRIT, _("could not open %s: %s"), conf.ifname, strerror (errno)); 110
111 for (i = 0;; i++)
112 {
113 len = sizeof (adapterid);
114 if (RegEnumKeyEx (key, i, adapterid, &len, 0, 0, 0, NULL))
115 break;
116
117 /* Find out more about this adapter */
118
119 snprintf (regpath, sizeof (regpath), "%s\\%s\\Connection",
120 REG_CONTROL_NET, adapterid);
121
122 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
123 continue;
124
125 len = sizeof (adaptername);
126 err = RegQueryValueEx (key2, "Name", 0, 0, adaptername, &len);
127
128 RegCloseKey (key2);
129
130 if (err)
131 continue;
132
133 if (conf.ifname)
134 {
135 if (strcmp (conf.ifname, adapterid))
136 continue;
137 }
138 else
139 {
140 found = true;
141 break;
142 }
143
144 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
145 device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
146 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
147 if (device_handle != INVALID_HANDLE_VALUE)
148 {
149 found = true;
150 break;
151 }
152 }
153
154 RegCloseKey (key);
155
156 if (!found)
157 {
158 slog (L_ERR, _("No Windows tap device found!"));
159 exit (1);
160 }
161
162 strcpy (ifrname, adaptername);
163
164 /* Try to open the corresponding tap device */
165
166 if (device_handle == INVALID_HANDLE_VALUE)
167 {
168 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, 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 is not a usable Windows tap device: %s"),
178 adaptername, wstrerror (GetLastError ()));
179 exit (1);
180 }
181
182 fd = cygwin_attach_handle_to_fd (tapname, -1, device_handle, 1, GENERIC_WRITE | GENERIC_READ);
183
184 /* Get MAC address from tap device */
185
186 if (!DeviceIoControl
187 (device_handle, TAP_IOCTL_GET_MAC, &mac, sizeof (mac), &mac, sizeof (mac), &len, 0))
188 {
189 slog (L_ERR,
190 _("Could not get MAC address from Windows tap device %s: %s"),
191 adaptername, wstrerror (GetLastError ()));
46 exit (1); 192 exit (1);
47 } 193 }
48} 194}
49 195
50tap_device::~tap_device () 196tap_device::~tap_device ()
60 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 206 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU);
61 207
62 if (pkt->len <= 0) 208 if (pkt->len <= 0)
63 { 209 {
64 slog (L_ERR, _("error while reading from %s %s: %s"), 210 slog (L_ERR, _("error while reading from %s %s: %s"),
65 info (), conf.ifname, strerror (errno)); 211 info (), conf.ifname, strerror (errno));
66 free (pkt); 212 free (pkt);
67 return 0; 213 return 0;
68 } 214 }
69 215
70 id2mac (THISNODE->id, &((*pkt)[6])); 216 id2mac (THISNODE->id, &((*pkt)[6]));
71 217
72 if (pkt->is_arp ()) 218 if (pkt->is_arp ())
73 { 219 {
74 if ((*pkt)[22] == 0x08) id2mac (THISNODE->id, &((*pkt)[22])); 220 if ((*pkt)[22] == 0x08)
75 if ((*pkt)[32] == 0x08) id2mac (THISNODE->id, &((*pkt)[32])); 221 id2mac (THISNODE->id, &((*pkt)[22]));
222 if ((*pkt)[32] == 0x08)
223 id2mac (THISNODE->id, &((*pkt)[32]));
76 } 224 }
77 225
78 return pkt; 226 return pkt;
79} 227}
80 228
81void 229void
82tap_device::send (tap_packet *pkt) 230tap_device::send (tap_packet * pkt)
83{ 231{
84 (*pkt)[ 6] = 0x08; (*pkt)[ 7] = 0x00; (*pkt)[ 8] = 0x58; 232 (*pkt)[6] = 0x08;
85 (*pkt)[ 9] = 0x00; (*pkt)[10] = 0x00; (*pkt)[11] = 0x01; 233 (*pkt)[7] = 0x00;
234 (*pkt)[8] = 0x58;
235 (*pkt)[9] = 0x00;
236 (*pkt)[10] = 0x00;
237 (*pkt)[11] = 0x01;
86 238
87 if (pkt->is_arp ()) 239 if (pkt->is_arp ())
88 { 240 {
89 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 241 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
90 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 242 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac));
91 243
92 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 244 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
93 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 245 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac));
94 } 246 }
95 247
96 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 248 if (write (fd, &((*pkt)[0]), pkt->len) < 0)
97 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 249 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname,
98 strerror (errno)); 250 strerror (errno));
99} 251}
252
253#if 0
254
255slog (L_DEBUG, _indent: Standard input:377: Error:Stmt nesting error.
256("Tap reader running"));
257
258 /* Read from tap device and send to parent */
259
260overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
261
262for indent
263: Standard input: 320: Error:Stmt nesting error.(;;
264 )
265{
266 overlapped.Offset = 0;
267 overlapped.OffsetHigh = 0;
268 ResetEvent (overlapped.hEvent);
269
270 status = ReadFile (device_handle, buf, sizeof (buf), &len, &overlapped);
271
272 if (!status)
273 {
274 if (GetLastError () == ERROR_IO_PENDING)
275 {
276 WaitForSingleObject (overlapped.hEvent, INFINITE);
277 if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE))
278 continue;
279 }
280 else
281 {
282 slog (L_ERR, _("Error while reading from %s %s: %s"),
283 device_info, device, strerror (errno));
284 return -1;
285 }
286 }
287
288 if (send (sock, buf, len, 0) <= 0)
289 return -1;
290}
291}
292
293void
294close_device (void)
295{
296 cp ();
297
298 CloseHandle (device_handle);
299}
300
301bool
302read_packet (vpn_packet_t * packet)
303{
304 int lenin;
305
306 cp ();
307
308 if ((lenin = recv (device_fd, packet->data, MTU, 0)) <= 0)
309 {
310 slog (L_ERR, _("Error while reading from %s %s: %s"), device_info,
311 device, strerror (errno));
312 return false;
313 }
314
315 packet->len = lenin;
316
317 device_total_in += packet->len;
318
319 ifdebug (TRAFFIC) slog (L_DEBUG, _("Read packet of %d bytes from %s"),
320 packet->len, device_info);
321
322 return true;
323}
324
325bool
326write_packet (vpn_packet_t * packet)
327{
328 long lenout;
329 OVERLAPPED overlapped = { 0 };
330
331 cp ();
332
333 ifdebug (TRAFFIC) slog (L_DEBUG, _("Writing packet of %d bytes to %s"),
334 packet->len, device_info);
335
336 if (!WriteFile
337 (device_handle, packet->data, packet->len, &lenout, &overlapped))
338 {
339 slog (L_ERR, _("Error while writing to %s %s: %s"), device_info,
340 device, wstrerror (GetLastError ()));
341 return false;
342 }
343
344 device_total_out += packet->len;
345
346 return true;
347}
348
349void
350dump_device_stats (void)
351{
352 cp ();
353
354 slog (L_DEBUG, _("Statistics for %s %s:"), device_info, device);
355 slog (L_DEBUG, _(" total bytes in: %10d"), device_total_in);
356 slog (L_DEBUG, _(" total bytes out: %10d"), device_total_out);
357}
358#endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines