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.9 by pcg, Thu Mar 3 16:54:34 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. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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,
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;
61 63
62static const char * 64static const char *
63wstrerror (int err) 65wstrerror (int err)
64{ 66{
65 static char buf[1024]; 67 static char buf[1024];
69 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL)) 71 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
70 { 72 {
71 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf)); 73 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
72 }; 74 };
73 75
76 char *nl;
74 if ((char *newline = strchr (buf, '\r'))) 77 if ((nl = strchr (buf, '\r')))
75 *newline = '\0'; 78 *nl = '\0';
76 79
77 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 }
78} 119}
79 120
80const char * 121const char *
81tap_device::info () 122tap_device::info ()
82{ 123{
88 HKEY key, key2; 129 HKEY key, key2;
89 int i; 130 int i;
90 131
91 char regpath[1024]; 132 char regpath[1024];
92 char adapterid[1024]; 133 char adapterid[1024];
93 char adaptername[1024]; 134 BYTE adaptername[1024];
94 char tapname[1024]; 135 char tapname[1024];
95 long len; 136 DWORD len;
96 137
97 bool found = false; 138 bool found = false;
98 139
99 int sock, err; 140 int sock, err;
100 141
101 /* Open registry and look for network adapters */ 142 /* Open registry and look for network adapters */
102 143
103 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key)) 144 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
104 { 145 {
105 slog (L_ERR, _("Unable to read registry: %s"), 146 slog (L_ERR, _("WIN32 TAP: unable to read registry: %s"),
106 wstrerror (GetLastError ())); 147 wstrerror (GetLastError ()));
107 return false; 148 exit (EXIT_FAILURE);
108 } 149 }
109 150
110 for (i = 0;; i++) 151 for (i = 0;; i++)
111 { 152 {
112 len = sizeof (adapterid); 153 len = sizeof (adapterid);
127 RegCloseKey (key2); 168 RegCloseKey (key2);
128 169
129 if (err) 170 if (err)
130 continue; 171 continue;
131 172
173 if (conf.ifname)
174 {
132 if (strcmp (conf.ifname, adapterid)) 175 if (strcmp (conf.ifname, adapterid))
133 continue; 176 continue;
134 177 }
178 else
179 {
135 found = true; 180 found = true;
136 break; 181 break;
182 }
137 183
138 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, 184 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
139 adapterid); 185 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, 186 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
141 0);
142 if (device_handle != INVALID_HANDLE_VALUE) 187 if (device_handle != INVALID_HANDLE_VALUE)
143 { 188 {
144 found = true; 189 found = true;
145 break; 190 break;
146 } 191 }
148 193
149 RegCloseKey (key); 194 RegCloseKey (key);
150 195
151 if (!found) 196 if (!found)
152 { 197 {
153 slog (L_ERR, _("No Windows tap device found!")); 198 slog (L_ERR, _("WIN32 TAP: no windows tap device found!"));
154 return false; 199 exit (EXIT_FAILURE);
155 } 200 }
156
157 if (!device)
158 device = xstrdup (adapterid);
159
160 if (!iface)
161 iface = xstrdup (adaptername);
162 201
163 /* Try to open the corresponding tap device */ 202 /* Try to open the corresponding tap device */
164 203
165 if (device_handle == INVALID_HANDLE_VALUE) 204 if (device_handle == INVALID_HANDLE_VALUE)
166 { 205 {
167 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, 206 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
168 device);
169 device_handle = 207 device_handle =
170 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, 208 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
171 OPEN_EXISTING, 209 OPEN_EXISTING,
172 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); 210 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
173 } 211 }
174 212
175 if (device_handle == INVALID_HANDLE_VALUE) 213 if (device_handle == INVALID_HANDLE_VALUE)
176 { 214 {
177 slog (L_ERR, _("%s (%s) is not a usable Windows tap device: %s"), 215 slog (L_ERR, _("WIN32 TAP: %s is not a usable windows tap device %s: %s"),
178 device, iface, wstrerror (GetLastError ())); 216 adaptername, tapname, wstrerror (GetLastError ()));
179 return false; 217 exit (EXIT_FAILURE);
180 } 218 }
219
220 strcpy (ifrname, (char *)tapname);
181 221
182 /* Get MAC address from tap device */ 222 /* Get MAC address from tap device */
183 223
184 if (!DeviceIoControl 224 if (!DeviceIoControl (device_handle, TAP_IOCTL_GET_MAC,
185 (device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof (mymac.x), mymac.x, 225 &local_mac, sizeof (local_mac), &local_mac, sizeof (local_mac),
186 sizeof (mymac.x), &len, 0)) 226 &len, 0))
187 { 227 {
188 slog (L_ERR, 228 slog (L_ERR,
189 _
190 ("Could not get MAC address from Windows tap device %s (%s): %s"), 229 _("WIN32 TAP: could not get MAC address from windows tap device %s: %s"),
191 device, iface, wstrerror (GetLastError ())); 230 adaptername, wstrerror (GetLastError ()));
192 return false; 231 exit (EXIT_FAILURE);
193 }
194
195 if (routing_mode == RMODE_ROUTER)
196 { 232 }
197 overwrite_mac = 1;
198 }
199 233
200 /* Create a listening socket */ 234 pipe (iopipe);
235 fd = iopipe[0];
236 pipe_handle = (HANDLE) get_osfhandle (iopipe[1]);
201 237
202 err = getaddrinfo (NULL, myport, &hint, &ai); 238 send_event = CreateEvent (NULL, FALSE, FALSE, NULL);
203 239
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); 240 thread = CreateThread (NULL, 0, read_thread, NULL, 0, NULL);
239 241
240 if (!thread) 242 /* try to set driver media status to 'connected' */
241 { 243 ULONG status = TRUE;
242 slog (L_ERR, _("System call `%s' failed: %s"), "CreateThread", 244 DeviceIoControl (device_handle, TAP_IOCTL_SET_MEDIA_STATUS,
243 wstrerror (GetLastError ())); 245 &status, sizeof (status),
244 return false; 246 &status, sizeof (status), &len, NULL);
245 } 247 // 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} 248}
266 249
267tap_device::~tap_device () 250tap_device::~tap_device ()
268{ 251{
269 close (fd); 252 close (iopipe[0]);
253 close (iopipe[1]);
254 CloseHandle (device_handle);
255 CloseHandle (send_event);
270} 256}
271 257
272tap_packet * 258tap_packet *
273tap_device::recv () 259tap_device::recv ()
274{ 260{
275 tap_packet *pkt = new tap_packet; 261 tap_packet *pkt = new tap_packet;
276 262
277 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 263 if (sizeof (u32) != read (iopipe[0], &pkt->len, sizeof (u32)))
278
279 if (pkt->len <= 0)
280 { 264 {
281 slog (L_ERR, _("error while reading from %s %s: %s"), 265 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt length"));
282 info (), conf.ifname, strerror (errno)); 266 delete pkt;
283 free (pkt);
284 return 0; 267 return 0;
285 } 268 }
286 269
270 if (pkt->len != read (iopipe[0], &((*pkt)[0]), pkt->len))
271 {
272 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt"));
273 delete pkt;
274 return 0;
275 }
276
287 id2mac (THISNODE->id, &((*pkt)[6])); 277 id2mac (THISNODE->id, &((*pkt)[6]));
288 278
289 if (pkt->is_arp ()) 279 if (pkt->is_arp ())
290 { 280 {
291 if ((*pkt)[22] == 0x08) 281 if (!memcmp (&(*pkt)[22], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[22]));
292 id2mac (THISNODE->id, &((*pkt)[22])); 282 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 } 283 }
296 284
297 return pkt; 285 return pkt;
298} 286}
299 287
300void 288void
301tap_device::send (tap_packet * pkt) 289tap_device::send (tap_packet * pkt)
302{ 290{
303 (*pkt)[6] = 0x08; 291 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 292
310 if (pkt->is_arp ()) 293 if (pkt->is_arp ())
311 { 294 {
312 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 295 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
313 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 296 memcpy (&(*pkt)[22], &local_mac, sizeof (mac));
314 297
315 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 298 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
316 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 299 memcpy (&(*pkt)[32], &local_mac, sizeof (mac));
317 } 300 }
318 301
319 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 302 DWORD dlen;
320 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 303 OVERLAPPED overlapped;
321 strerror (errno)); 304 overlapped.hEvent = send_event;
322}
323 305
324#if 0 306 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 { 307 {
345 if (GetLastError () == ERROR_IO_PENDING) 308 if (GetLastError () == ERROR_IO_PENDING)
346 {
347 WaitForSingleObject (overlapped.hEvent, INFINITE);
348 if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE)) 309 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
349 continue;
350 }
351 else 310 else
352 { 311 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"), 312 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 { 313 }
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} 314}
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