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.2 by pcg, Tue Oct 14 03:22:09 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>,
5 2002-2003 Guus Sliepen <guus@sliepen.eu.org>
4 6
7 This file is part of GVPE.
8
5 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
6 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
7 the Free Software Foundation; either version 2 of the License, or 11 Free Software Foundation; either version 3 of the License, or (at your
8 (at your option) any later version. 12 option) any later version.
9 13
10 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
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 GNU General Public License for more details. 17 Public License for more details.
14 18
15 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
16 along with this program; if not, write to the Free Software 20 with this program; if not, see <http://www.gnu.org/licenses/>.
17 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.
18*/ 32*/
19 33
20// 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,
21// 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,
22// 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.
23// this is probably not very fast, but neither is cygwin nor poll. 37// this is probably not very fast, but neither is cygwin nor poll.
24// 38//
25// http://cipe-win32.sourceforge.net/ 39// http://cipe-win32.sourceforge.net/
40// a newer driver is available as part of the openvpn package:
41// http://openvpn.sf.net/
26 42
27#include "config.h" 43#include "config.h"
28 44
29#include <stdio.h> 45#include <cstdio>
46#include <cstring>
47#include <cstdlib>
30#include <errno.h> 48#include <errno.h>
31#include <sys/types.h> 49#include <sys/types.h>
32#include <sys/stat.h> 50#include <sys/stat.h>
33#include <fcntl.h> 51#include <fcntl.h>
34#include <unistd.h> 52#include <unistd.h>
35#include <syslog.h>
36#include <cstring>
37 53
38#include "conf.h" 54#include "conf.h"
39#include "util.h" 55#include "util.h"
40 56
57#include <io.h>
58#include <w32api/windows.h>
59#include <w32api/winioctl.h>
60
61#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
62
63#define USERMODEDEVICEDIR "\\\\.\\"
64#define USERDEVICEDIR "\\??\\"
65#define TAPSUFFIX ".tap"
66
67#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
68
69#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
70#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
71#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
72#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(7, METHOD_BUFFERED)
73
74static const char *
75wstrerror (int err)
76{
77 static char buf[1024];
78
79 if (!FormatMessage
80 (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
81 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
82 {
83 strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
84 };
85
86 char *nl;
87 if ((nl = strchr (buf, '\r')))
88 *nl = '\0';
89
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 }
129}
130
41const char * 131const char *
42tap_device::info () 132tap_device::info ()
43{ 133{
44 return _("broken cygwin cipe device"); 134 return _("cygwin cipe/openvpn tap device");
135}
136
137const char *
138tap_device::if_up ()
139{
140 return "";
45} 141}
46 142
47tap_device::tap_device () 143tap_device::tap_device ()
48{ 144{
49 if ((fd = open (conf.ifname, O_RDWR)) < 0) 145 HKEY key, key2;
50 { 146 int i;
51 slog (L_CRIT, _("could not open %s: %s"), conf.ifname, strerror (errno)); 147
52 exit (1); 148 char regpath[1024];
149 char adapterid[1024];
150 BYTE adaptername[1024];
151 char tapname[1024];
152 DWORD len;
153
154 bool found = false;
155
156 int sock, err;
157
158 /* Open registry and look for network adapters */
159
160 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
53 } 161 {
162 slog (L_ERR, _("WIN32 TAP: unable to read registry: %s"),
163 wstrerror (GetLastError ()));
164 exit (EXIT_FAILURE);
165 }
166
167 for (i = 0;; i++)
168 {
169 len = sizeof (adapterid);
170 if (RegEnumKeyEx (key, i, adapterid, &len, 0, 0, 0, NULL))
171 break;
172
173 /* Find out more about this adapter */
174
175 snprintf (regpath, sizeof (regpath), "%s\\%s\\Connection",
176 REG_CONTROL_NET, adapterid);
177
178 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
179 continue;
180
181 len = sizeof (adaptername);
182 err = RegQueryValueEx (key2, "Name", 0, 0, adaptername, &len);
183
184 RegCloseKey (key2);
185
186 if (err)
187 continue;
188
189 if (conf.ifname)
190 {
191 if (strcmp (conf.ifname, adapterid))
192 continue;
193 }
194 else
195 {
196 found = true;
197 break;
198 }
199
200 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
201 device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
202 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
203 if (device_handle != INVALID_HANDLE_VALUE)
204 {
205 found = true;
206 break;
207 }
208 }
209
210 RegCloseKey (key);
211
212 if (!found)
213 {
214 slog (L_ERR, _("WIN32 TAP: no windows tap device found!"));
215 exit (EXIT_FAILURE);
216 }
217
218 /* Try to open the corresponding tap device */
219
220 if (device_handle == INVALID_HANDLE_VALUE)
221 {
222 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
223 device_handle =
224 CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
225 OPEN_EXISTING,
226 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
227 }
228
229 if (device_handle == INVALID_HANDLE_VALUE)
230 {
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"),
246 adaptername, wstrerror (GetLastError ()));
247 exit (EXIT_FAILURE);
248 }
249
250 pipe (iopipe);
251 fd = iopipe[0];
252 pipe_handle = (HANDLE) get_osfhandle (iopipe[1]);
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
54} 264}
55 265
56tap_device::~tap_device () 266tap_device::~tap_device ()
57{ 267{
58 close (fd); 268 close (iopipe[0]);
269 close (iopipe[1]);
270 CloseHandle (device_handle);
271 CloseHandle (send_event);
59} 272}
60 273
61tap_packet * 274tap_packet *
62tap_device::recv () 275tap_device::recv ()
63{ 276{
64 tap_packet *pkt = new tap_packet; 277 tap_packet *pkt = new tap_packet;
65 278
66 pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); 279 if (sizeof (u32) != read (iopipe[0], &pkt->len, sizeof (u32)))
67
68 if (pkt->len <= 0)
69 { 280 {
70 slog (L_ERR, _("error while reading from %s %s: %s"), 281 slog (L_ERR, _("WIN32 TAP: i/o thread delivered incomplete pkt length"));
71 info (), conf.ifname, strerror (errno)); 282 delete pkt;
72 free (pkt);
73 return 0; 283 return 0;
74 } 284 }
75 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
76 id2mac (THISNODE->id, &((*pkt)[6])); 293 id2mac (THISNODE->id, &((*pkt)[6]));
77 294
78 if (pkt->is_arp ()) 295 if (pkt->is_arp ())
79 { 296 {
80 if ((*pkt)[22] == 0x08) id2mac (THISNODE->id, &((*pkt)[22])); 297 if (!memcmp (&(*pkt)[22], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[22]));
81 if ((*pkt)[32] == 0x08) id2mac (THISNODE->id, &((*pkt)[32])); 298 if (!memcmp (&(*pkt)[32], &local_mac, sizeof (mac))) id2mac (THISNODE->id, &((*pkt)[32]));
82 } 299 }
83 300
84 return pkt; 301 return pkt;
85} 302}
86 303
87void 304void
88tap_device::send (tap_packet *pkt) 305tap_device::send (tap_packet * pkt)
89{ 306{
90 (*pkt)[ 6] = 0x08; (*pkt)[ 7] = 0x00; (*pkt)[ 8] = 0x58; 307 memcpy (&(*pkt)[6], &local_mac, sizeof (mac));
91 (*pkt)[ 9] = 0x00; (*pkt)[10] = 0x00; (*pkt)[11] = 0x01;
92 308
93 if (pkt->is_arp ()) 309 if (pkt->is_arp ())
94 { 310 {
95 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id) 311 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
96 memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac)); 312 memcpy (&(*pkt)[22], &local_mac, sizeof (mac));
97 313
98 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id) 314 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
99 memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac)); 315 memcpy (&(*pkt)[32], &local_mac, sizeof (mac));
316 }
317
318 DWORD dlen;
319 OVERLAPPED overlapped;
320 overlapped.hEvent = send_event;
321
322 if (!WriteFile (device_handle, &((*pkt)[0]), pkt->len, &dlen, &overlapped))
100 } 323 {
101 324 if (GetLastError () == ERROR_IO_PENDING)
102 if (write (fd, &((*pkt)[0]), pkt->len) < 0) 325 GetOverlappedResult (device_handle, &overlapped, &dlen, TRUE);
326 else
103 slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname, 327 slog (L_ERR, _("WIN32 TAP: can't write to %s %s: %s"), info (), conf.ifname,
104 strerror (errno)); 328 wstrerror (GetLastError ()));
329 }
105} 330}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines