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