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.5 by pcg, Wed Oct 15 01:38:24 2003 UTC vs.
Revision 1.11 by pcg, Tue Apr 26 00:55:56 2005 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-2005 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
8 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or 11 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version. 12 (at your 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,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 but 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
15 GNU General Public License for more details. 17 GNU General 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
18 along with this program; if not, write to the Free Software 20 along with gvpe; if not, write to the Free Software
19 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/ 22*/
21 23
22// unfortunately, there is be no way to set MAC addresses under windows, 24// 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, 25// 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. 26// 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: 30// a newer driver is available as part of the openvpn package:
29// http://openvpn.sf.net/ 31// http://openvpn.sf.net/
30 32
31#include "config.h" 33#include "config.h"
32 34
33#include <stdio.h> 35#include <cstdio>
36#include <cstring>
37#include <cstdlib>
34#include <errno.h> 38#include <errno.h>
35#include <sys/types.h> 39#include <sys/types.h>
36#include <sys/stat.h> 40#include <sys/stat.h>
37#include <fcntl.h> 41#include <fcntl.h>
38#include <unistd.h> 42#include <unistd.h>
39#include <syslog.h>
40#include <cstring>
41 43
42#include "conf.h" 44#include "conf.h"
43#include "util.h" 45#include "util.h"
44 46
47#include <io.h>
45#include <w32api/windows.h> 48#include <w32api/windows.h>
46#include <w32api/winioctl.h> 49#include <w32api/winioctl.h>
47 50
48#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 51#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
49 52
51#define USERDEVICEDIR "\\??\\" 54#define USERDEVICEDIR "\\??\\"
52#define TAPSUFFIX ".tap" 55#define TAPSUFFIX ".tap"
53 56
54#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS) 57#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
55 58
56#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED) 59#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
57#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED) 60#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
58#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED) 61#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
59 62#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(7, METHOD_BUFFERED)
60static HANDLE device_handle = INVALID_HANDLE_VALUE;
61static mac my_mac;
62 63
63static const char * 64static const char *
64wstrerror (int err) 65wstrerror (int err)
65{ 66{
66 static char buf[1024]; 67 static char buf[1024];
70 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL)) 71 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
71 { 72 {
72 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf)); 73 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
73 }; 74 };
74 75
76 char *nl;
75 if ((char *newline = strchr (buf, '\r'))) 77 if ((nl = strchr (buf, '\r')))
76 *newline = '\0'; 78 *nl = '\0';
77 79
78 return buf; 80 return buf;
81}
82
83static HANDLE device_handle = INVALID_HANDLE_VALUE;
84static mac local_mac;
85static tap_packet *rcv_pkt;
86static int iopipe[2];
87static HANDLE pipe_handle, send_event, thread;
88
89static DWORD WINAPI
90read_thread(void *)
91{
92 static OVERLAPPED overlapped;
93 static DWORD dlen;
94 static u32 len;
95 static u8 data[MAX_MTU];
96
97 overlapped.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
98
99 for (;;)
100 {
101 if (!ReadFile (device_handle, data, MAX_MTU, &dlen, &overlapped))
102 {
103 if (GetLastError () == ERROR_IO_PENDING)
104 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
105 else
106 {
107 slog (L_ERR, "WIN32 TAP: ReadFile returned error: %s", wstrerror (GetLastError ()));
108 exit (EXIT_FAILURE);
109 }
110 }
111
112 if (dlen > 0)
113 {
114 len = dlen;
115 WriteFile (pipe_handle, &len, sizeof (len), &dlen, NULL);
116 WriteFile (pipe_handle, data, len, &dlen, NULL);
117 }
118 }
79} 119}
80 120
81const char * 121const char *
82tap_device::info () 122tap_device::info ()
83{ 123{
84 return _("cygwin cipe/openvpn tap device"); 124 return _("cygwin cipe/openvpn tap device");
85} 125}
86 126
127const char *
128tap_device::if_up ()
129{
130 return "";
131}
132
87tap_device::tap_device () 133tap_device::tap_device ()
88{ 134{
89 HKEY key, key2; 135 HKEY key, key2;
90 int i; 136 int i;
91 137
92 char regpath[1024]; 138 char regpath[1024];
93 char adapterid[1024]; 139 char adapterid[1024];
94 char adaptername[1024]; 140 BYTE adaptername[1024];
95 char tapname[1024]; 141 char tapname[1024];
96 long len; 142 DWORD len;
97 143
98 bool found = false; 144 bool found = false;
99 145
100 int sock, err; 146 int sock, err;
101 147
102 /* Open registry and look for network adapters */ 148 /* Open registry and look for network adapters */
103 149
104 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key)) 150 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
105 { 151 {
106 slog (L_ERR, _("Unable to read registry: %s"), 152 slog (L_ERR, _("WIN32 TAP: unable to read registry: %s"),
107 wstrerror (GetLastError ())); 153 wstrerror (GetLastError ()));
108 return false; 154 exit (EXIT_FAILURE);
109 } 155 }
110 156
111 for (i = 0;; i++) 157 for (i = 0;; i++)
112 { 158 {
113 len = sizeof (adapterid); 159 len = sizeof (adapterid);
153 199
154 RegCloseKey (key); 200 RegCloseKey (key);
155 201
156 if (!found) 202 if (!found)
157 { 203 {
158 slog (L_ERR, _("No Windows tap device found!")); 204 slog (L_ERR, _("WIN32 TAP: no windows tap device found!"));
159 exit (1); 205 exit (EXIT_FAILURE);
160 } 206 }
161
162 strcpy (ifrname, adaptername);
163 207
164 /* Try to open the corresponding tap device */ 208 /* Try to open the corresponding tap device */
165 209
166 if (device_handle == INVALID_HANDLE_VALUE) 210 if (device_handle == INVALID_HANDLE_VALUE)
167 { 211 {
168 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device); 212 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
169 device_handle = 213 device_handle =
170 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, 214 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
171 OPEN_EXISTING, 215 OPEN_EXISTING,
172 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); 216 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
173 } 217 }
174 218
175 if (device_handle == INVALID_HANDLE_VALUE) 219 if (device_handle == INVALID_HANDLE_VALUE)
176 { 220 {
177 slog (L_ERR, _("%s is not a usable Windows tap device: %s"), 221 slog (L_ERR, _("WIN32 TAP: %s is not a usable windows tap device %s: %s"),
222 adaptername, tapname, wstrerror (GetLastError ()));
223 exit (EXIT_FAILURE);
224 }
225
226 strcpy (ifrname, (char *)tapname);
227
228 /* Get MAC address from tap device */
229
230 if (!DeviceIoControl (device_handle, TAP_IOCTL_GET_MAC,
231 &local_mac, sizeof (local_mac), &local_mac, sizeof (local_mac),
232 &len, 0))
233 {
234 slog (L_ERR,
235 _("WIN32 TAP: could not get MAC address from windows tap device %s: %s"),
178 adaptername, wstrerror (GetLastError ())); 236 adaptername, wstrerror (GetLastError ()));
179 exit (1); 237 exit (EXIT_FAILURE);
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 { 238 }
189 slog (L_ERR, 239
190 _("Could not get MAC address from Windows tap device %s: %s"), 240 pipe (iopipe);
191 adaptername, wstrerror (GetLastError ())); 241 fd = iopipe[0];
192 exit (1); 242 pipe_handle = (HANDLE) get_osfhandle (iopipe[1]);
193 } 243
244 send_event = CreateEvent (NULL, FALSE, FALSE, NULL);
245
246 thread = CreateThread (NULL, 0, read_thread, NULL, 0, NULL);
247
248 /* try to set driver media status to 'connected' */
249 ULONG status = TRUE;
250 DeviceIoControl (device_handle, TAP_IOCTL_SET_MEDIA_STATUS,
251 &status, sizeof (status),
252 &status, sizeof (status), &len, NULL);
253 // ignore error here on purpose
194} 254}
195 255
196tap_device::~tap_device () 256tap_device::~tap_device ()
197{ 257{
198 close (fd); 258 close (iopipe[0]);
259 close (iopipe[1]);
260 CloseHandle (device_handle);
261 CloseHandle (send_event);
199} 262}
200 263
201tap_packet * 264tap_packet *
202tap_device::recv () 265tap_device::recv ()
203{ 266{
204 tap_packet *pkt = new tap_packet; 267 tap_packet *pkt = new tap_packet;
205 268
206 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 269 if (sizeof (u32) != read (iopipe[0], &pkt->len, sizeof (u32)))
207
208 if (pkt->len <= 0)
209 { 270 {
210 slog (L_ERR, _("error while reading from %s %s: %s"), 271 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt length"));
211 info (), conf.ifname, strerror (errno)); 272 delete pkt;
212 free (pkt);
213 return 0; 273 return 0;
214 } 274 }
215 275
276 if (pkt->len != read (iopipe[0], &((*pkt)[0]), pkt->len))
277 {
278 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt"));
279 delete pkt;
280 return 0;
281 }
282
216 id2mac (THISNODE->id, &((*pkt)[6])); 283 id2mac (THISNODE->id, &((*pkt)[6]));
217 284
218 if (pkt->is_arp ()) 285 if (pkt->is_arp ())
219 { 286 {
220 if ((*pkt)[22] == 0x08) 287 if (!memcmp (&(*pkt)[22], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[22]));
221 id2mac (THISNODE->id, &((*pkt)[22])); 288 if (!memcmp (&(*pkt)[32], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[32]));
222 if ((*pkt)[32] == 0x08)
223 id2mac (THISNODE->id, &((*pkt)[32]));
224 } 289 }
225 290
226 return pkt; 291 return pkt;
227} 292}
228 293
229void 294void
230tap_device::send (tap_packet * pkt) 295tap_device::send (tap_packet * pkt)
231{ 296{
232 (*pkt)[6] = 0x08; 297 memcpy (&(*pkt)[6], &local_mac, sizeof (mac));
233 (*pkt)[7] = 0x00;
234 (*pkt)[8] = 0x58;
235 (*pkt)[9] = 0x00;
236 (*pkt)[10] = 0x00;
237 (*pkt)[11] = 0x01;
238 298
239 if (pkt->is_arp ()) 299 if (pkt->is_arp ())
240 { 300 {
241 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 301 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
242 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 302 memcpy (&(*pkt)[22], &local_mac, sizeof (mac));
243 303
244 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 304 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
245 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 305 memcpy (&(*pkt)[32], &local_mac, sizeof (mac));
246 } 306 }
247 307
248 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 308 DWORD dlen;
249 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 309 OVERLAPPED overlapped;
250 strerror (errno)); 310 overlapped.hEvent = send_event;
251}
252 311
253#if 0 312 if (!WriteFile (device_handle, &((*pkt)[0]), pkt->len, &dlen, &overlapped))
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 { 313 {
274 if (GetLastError () == ERROR_IO_PENDING) 314 if (GetLastError () == ERROR_IO_PENDING)
275 {
276 WaitForSingleObject (overlapped.hEvent, INFINITE);
277 if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE)) 315 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
278 continue;
279 }
280 else 316 else
281 { 317 slog (L_ERR, _("WIN32 TAP: can't write to %s %s: %s"), info (), conf.ifname,
282 slog (L_ERR, _("Error while reading from %s %s: %s"), 318 wstrerror (GetLastError ()));
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 { 319 }
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} 320}
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