ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/device-cygwin.C
Revision: 1.5
Committed: Wed Oct 15 01:38:24 2003 UTC (20 years, 7 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +4 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2     device-cygwin.C -- Stub for Cygwin environment
3     Copyright (C) 2003 Marc Lehmann <ocg@goof.com>
4 pcg 1.3 Copyright (C) 2002-2003 Ivo Timmermans <ivo@o2w.nl>,
5     2002-2003 Guus Sliepen <guus@sliepen.eu.org>
6 pcg 1.1
7     This program is free software; you can redistribute it and/or modify
8     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
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     // 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,
24     // so this module tries to fix mac addresses in packets and arp packets.
25     // this is probably not very fast, but neither is cygwin nor poll.
26     //
27     // http://cipe-win32.sourceforge.net/
28 pcg 1.3 // a newer driver is available as part of the openvpn package:
29     // http://openvpn.sf.net/
30 pcg 1.1
31     #include "config.h"
32    
33     #include <stdio.h>
34     #include <errno.h>
35     #include <sys/types.h>
36     #include <sys/stat.h>
37     #include <fcntl.h>
38     #include <unistd.h>
39     #include <syslog.h>
40     #include <cstring>
41    
42     #include "conf.h"
43     #include "util.h"
44    
45 pcg 1.3 #include <w32api/windows.h>
46     #include <w32api/winioctl.h>
47    
48     #define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
49    
50     #define USERMODEDEVICEDIR "\\\\.\\"
51     #define USERDEVICEDIR "\\??\\"
52     #define TAPSUFFIX ".tap"
53    
54     #define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
55    
56     #define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
57     #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
58     #define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
59    
60     static HANDLE device_handle = INVALID_HANDLE_VALUE;
61 pcg 1.4 static mac my_mac;
62 pcg 1.3
63     static const char *
64     wstrerror (int err)
65     {
66     static char buf[1024];
67    
68     if (!FormatMessage
69     (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
70     MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof (buf), NULL))
71     {
72     strncpy (buf, _("(unable to format errormessage)"), sizeof (buf));
73     };
74    
75     if ((char *newline = strchr (buf, '\r')))
76     *newline = '\0';
77    
78     return buf;
79     }
80    
81 pcg 1.2 const char *
82     tap_device::info ()
83     {
84 pcg 1.3 return _("cygwin cipe/openvpn tap device");
85 pcg 1.2 }
86    
87 pcg 1.1 tap_device::tap_device ()
88     {
89 pcg 1.3 HKEY key, key2;
90     int i;
91    
92     char regpath[1024];
93     char adapterid[1024];
94     char adaptername[1024];
95     char tapname[1024];
96     long len;
97    
98     bool found = false;
99    
100     int sock, err;
101    
102     /* Open registry and look for network adapters */
103    
104     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key))
105     {
106     slog (L_ERR, _("Unable to read registry: %s"),
107     wstrerror (GetLastError ()));
108     return false;
109     }
110    
111     for (i = 0;; i++)
112 pcg 1.1 {
113 pcg 1.3 len = sizeof (adapterid);
114     if (RegEnumKeyEx (key, i, adapterid, &len, 0, 0, 0, NULL))
115     break;
116    
117     /* Find out more about this adapter */
118    
119     snprintf (regpath, sizeof (regpath), "%s\\%s\\Connection",
120     REG_CONTROL_NET, adapterid);
121    
122     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
123     continue;
124    
125     len = sizeof (adaptername);
126     err = RegQueryValueEx (key2, "Name", 0, 0, adaptername, &len);
127    
128     RegCloseKey (key2);
129    
130     if (err)
131     continue;
132    
133 pcg 1.4 if (conf.ifname)
134     {
135     if (strcmp (conf.ifname, adapterid))
136     continue;
137     }
138     else
139     {
140     found = true;
141     break;
142     }
143    
144     snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
145     device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
146     OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
147 pcg 1.3 if (device_handle != INVALID_HANDLE_VALUE)
148     {
149     found = true;
150     break;
151     }
152 pcg 1.1 }
153 pcg 1.3
154     RegCloseKey (key);
155    
156     if (!found)
157     {
158     slog (L_ERR, _("No Windows tap device found!"));
159 pcg 1.4 exit (1);
160 pcg 1.3 }
161    
162 pcg 1.4 strcpy (ifrname, adaptername);
163 pcg 1.3
164     /* Try to open the corresponding tap device */
165    
166     if (device_handle == INVALID_HANDLE_VALUE)
167     {
168 pcg 1.4 snprintf (tapname, sizeof (tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
169 pcg 1.3 device_handle =
170     CreateFile (tapname, GENERIC_WRITE | GENERIC_READ, 0, 0,
171     OPEN_EXISTING,
172     FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
173     }
174    
175     if (device_handle == INVALID_HANDLE_VALUE)
176     {
177 pcg 1.5 slog (L_ERR, _("%s is not a usable Windows tap device: %s"),
178     adaptername, wstrerror (GetLastError ()));
179 pcg 1.4 exit (1);
180 pcg 1.3 }
181    
182 pcg 1.4 fd = cygwin_attach_handle_to_fd (tapname, -1, device_handle, 1, GENERIC_WRITE | GENERIC_READ);
183    
184 pcg 1.3 /* Get MAC address from tap device */
185    
186     if (!DeviceIoControl
187 pcg 1.4 (device_handle, TAP_IOCTL_GET_MAC, &mac, sizeof (mac), &mac, sizeof (mac), &len, 0))
188 pcg 1.3 {
189     slog (L_ERR,
190 pcg 1.5 _("Could not get MAC address from Windows tap device %s: %s"),
191     adaptername, wstrerror (GetLastError ()));
192 pcg 1.4 exit (1);
193 pcg 1.3 }
194 pcg 1.1 }
195    
196     tap_device::~tap_device ()
197     {
198     close (fd);
199     }
200    
201     tap_packet *
202     tap_device::recv ()
203     {
204     tap_packet *pkt = new tap_packet;
205    
206     pkt->len = read (fd, &((*pkt)[0]), MAX_MTU);
207    
208     if (pkt->len <= 0)
209     {
210     slog (L_ERR, _("error while reading from %s %s: %s"),
211 pcg 1.3 info (), conf.ifname, strerror (errno));
212 pcg 1.1 free (pkt);
213     return 0;
214     }
215    
216     id2mac (THISNODE->id, &((*pkt)[6]));
217    
218     if (pkt->is_arp ())
219     {
220 pcg 1.3 if ((*pkt)[22] == 0x08)
221     id2mac (THISNODE->id, &((*pkt)[22]));
222     if ((*pkt)[32] == 0x08)
223     id2mac (THISNODE->id, &((*pkt)[32]));
224 pcg 1.1 }
225    
226     return pkt;
227     }
228    
229     void
230 pcg 1.3 tap_device::send (tap_packet * pkt)
231 pcg 1.1 {
232 pcg 1.3 (*pkt)[6] = 0x08;
233     (*pkt)[7] = 0x00;
234     (*pkt)[8] = 0x58;
235     (*pkt)[9] = 0x00;
236     (*pkt)[10] = 0x00;
237     (*pkt)[11] = 0x01;
238 pcg 1.1
239     if (pkt->is_arp ())
240     {
241 pcg 1.3 if ((*pkt)[22] == 0xfe && (*pkt)[27] == THISNODE->id)
242     memcpy (&(*pkt)[22], &(*pkt)[6], sizeof (mac));
243 pcg 1.1
244 pcg 1.3 if ((*pkt)[32] == 0xfe && (*pkt)[37] == THISNODE->id)
245     memcpy (&(*pkt)[32], &(*pkt)[6], sizeof (mac));
246 pcg 1.1 }
247    
248     if (write (fd, &((*pkt)[0]), pkt->len) < 0)
249     slog (L_ERR, _("can't write to %s %s: %s"), info (), conf.ifname,
250 pcg 1.3 strerror (errno));
251     }
252    
253     #if 0
254    
255     slog (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    
260     overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
261    
262     for 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     {
274     if (GetLastError () == ERROR_IO_PENDING)
275     {
276     WaitForSingleObject (overlapped.hEvent, INFINITE);
277     if (!GetOverlappedResult (device_handle, &overlapped, &len, FALSE))
278     continue;
279     }
280     else
281     {
282     slog (L_ERR, _("Error while reading from %s %s: %s"),
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    
293     void
294     close_device (void)
295     {
296     cp ();
297    
298     CloseHandle (device_handle);
299     }
300    
301     bool
302     read_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     {
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     }
324    
325     bool
326     write_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    
349     void
350     dump_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 pcg 1.1 }
358 pcg 1.3 #endif