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