1 /*
2 (C) 2007-09 - Luca Deri <deri@ntop.org>
3 */
4
5 #include "n2n.h"
6 #include "n2n_win32.h"
7
8 /* ***************************************************** */
9
initWin32()10 void initWin32() {
11 WSADATA wsaData;
12 int err;
13
14 err = WSAStartup(MAKEWORD(2, 2), &wsaData );
15 if( err != 0 ) {
16 /* Tell the user that we could not find a usable */
17 /* WinSock DLL. */
18 printf("FATAL ERROR: unable to initialise Winsock 2.x.");
19 exit(EXIT_FAILURE);
20 }
21 }
22
23 struct win_adapter_info {
24 HANDLE handle;
25 char adapterid[1024];
26 char adaptername[1024];
27 };
28
29 /* ***************************************************** */
30
open_tap_device(const char * adapterid)31 static HANDLE open_tap_device(const char *adapterid) {
32 char tapname[1024];
33 _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
34
35 return(CreateFile(tapname, GENERIC_WRITE | GENERIC_READ,
36 0, /* Don't let other processes share or open
37 the resource until the handle's been closed */
38 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0));
39 }
40
41 /* ***************************************************** */
42
iterate_win_network_adapters(int (* callback)(struct win_adapter_info *,struct tuntap_dev *),void * userdata)43 static void iterate_win_network_adapters(
44 int (*callback)(struct win_adapter_info*, struct tuntap_dev *),
45 void *userdata) {
46 HKEY key, key2;
47 char regpath[1024];
48 long len, rc;
49 int found = 0;
50 int err, i;
51 struct win_adapter_info adapter;
52
53 /* Open registry and look for network adapters */
54 if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) {
55 printf("Unable to read registry: [rc=%d]\n", rc);
56 exit(EXIT_FAILURE);
57 /* MSVC Note: If you keep getting rc=2 errors, make sure you set:
58 Project -> Properties -> Configuration Properties -> General -> Character set
59 to: "Use Multi-Byte Character Set"
60 */
61 }
62
63 for (i = 0; ; i++) {
64 len = sizeof(adapter.adapterid);
65 if(RegEnumKeyEx(key, i, (LPTSTR)adapter.adapterid, &len, 0, 0, 0, NULL))
66 break;
67
68 /* Find out more about this adapter */
69
70 _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapter.adapterid);
71 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2))
72 continue;
73
74 len = sizeof(adapter.adaptername);
75 err = RegQueryValueEx(key2, "Name", 0, 0, adapter.adaptername, &len);
76
77 RegCloseKey(key2);
78
79 if(err)
80 continue;
81
82
83 adapter.handle = open_tap_device(adapter.adapterid);
84
85 if(adapter.handle != INVALID_HANDLE_VALUE) {
86 /* Valid device, use the callback */
87 if(!callback(&adapter, userdata))
88 break;
89 else
90 CloseHandle(adapter.handle);
91 /* continue */
92 }
93 }
94
95 RegCloseKey(key);
96 }
97
98 /* ***************************************************** */
99
print_adapter_callback(struct win_adapter_info * adapter,struct tuntap_dev * device)100 static int print_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) {
101 printf(" %s - %s\n", adapter->adapterid, adapter->adaptername);
102
103 /* continue */
104 return(1);
105 }
106
win_print_available_adapters()107 void win_print_available_adapters() {
108 iterate_win_network_adapters(print_adapter_callback, NULL);
109 }
110
111 /* ***************************************************** */
112
lookup_adapter_info_reg(const char * target_adapter,char * regpath,size_t regpath_size)113 static int lookup_adapter_info_reg(const char *target_adapter, char *regpath, size_t regpath_size) {
114 HKEY key, key2;
115 long len, rc;
116 char index[16];
117 int err, i;
118 char adapter_name[N2N_IFNAMSIZ];
119 int rv = 0;
120
121 if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_INFO_KEY, 0, KEY_READ, &key))) {
122 printf("Unable to read registry: %s, [rc=%d]\n", ADAPTER_INFO_KEY, rc);
123 exit(EXIT_FAILURE);
124 }
125
126 for(i = 0; ; i++) {
127 len = sizeof(index);
128 if(RegEnumKeyEx(key, i, (LPTSTR)index, &len, 0, 0, 0, NULL))
129 break;
130
131 _snprintf(regpath, regpath_size, "%s\\%s", ADAPTER_INFO_KEY, index);
132 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2))
133 continue;
134
135 len = sizeof(adapter_name);
136 err = RegQueryValueEx(key2, "NetCfgInstanceId", 0, 0, adapter_name, &len);
137
138 RegCloseKey(key2);
139
140 if(err)
141 continue;
142
143 if(!strcmp(adapter_name, target_adapter)) {
144 rv = 1;
145 break;
146 }
147 }
148
149 RegCloseKey(key);
150 return(rv);
151 }
152
153 /* ***************************************************** */
154
set_interface_mac(struct tuntap_dev * device,const char * mac_str)155 static void set_interface_mac(struct tuntap_dev *device, const char *mac_str) {
156 char cmd[256];
157 char mac_buf[18];
158 char adapter_info_reg[1024];
159
160 uint64_t mac = 0;
161 uint8_t *ptr = (uint8_t*)&mac;
162
163 if(strlen(mac_str) != 17) {
164 printf("Invalid MAC: %s\n", mac_str);
165 exit(EXIT_FAILURE);
166 }
167
168 /* Remove the colons */
169 for(int i=0; i<6; i++) {
170 mac_buf[i*2] = mac_str[2*i + i];
171 mac_buf[i*2+1] = mac_str[2*i + i + 1];
172 }
173 mac_buf[12] = '\0';
174
175 if(!lookup_adapter_info_reg(device->device_name, adapter_info_reg, sizeof(adapter_info_reg))) {
176 printf("Could not determine adapter MAC registry key\n");
177 exit(EXIT_FAILURE);
178 }
179
180 _snprintf(cmd, sizeof(cmd),
181 "reg add HKEY_LOCAL_MACHINE\\%s /v MAC /d %s /f > nul", adapter_info_reg, mac_buf);
182 system(cmd);
183
184 /* Put down then up again to apply */
185 CloseHandle(device->device_handle);
186 _snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" disabled > nul", device->ifName);
187 system(cmd);
188 _snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" enabled > nul", device->ifName);
189 system(cmd);
190
191 device->device_handle = open_tap_device(device->device_name);
192 if(device->device_handle == INVALID_HANDLE_VALUE) {
193 printf("Reopening TAP device \"%s\" failed\n", device->device_name);
194 exit(EXIT_FAILURE);
195 }
196 }
197
198 /* ***************************************************** */
199
choose_adapter_callback(struct win_adapter_info * adapter,struct tuntap_dev * device)200 static int choose_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) {
201 if(device->device_name) {
202 /* A device name filter was set, name must match */
203 if(strcmp(device->device_name, adapter->adapterid) &&
204 strcmp(device->device_name, adapter->adaptername)) {
205 /* Not found, continue */
206 return(1);
207 }
208 } /* otherwise just pick the first available adapter */
209
210 /* Adapter found, break */
211 device->device_handle = adapter->handle;
212 if(device->device_name) free(device->device_name);
213 device->device_name = _strdup(adapter->adapterid);
214 device->ifName = _strdup(adapter->adaptername);
215 return(0);
216 }
217
218 /* ***************************************************** */
219
open_wintap(struct tuntap_dev * device,const char * devname,const char * address_mode,char * device_ip,char * device_mask,const char * device_mac,int mtu)220 int open_wintap(struct tuntap_dev *device,
221 const char * devname,
222 const char * address_mode, /* "static" or "dhcp" */
223 char *device_ip,
224 char *device_mask,
225 const char *device_mac,
226 int mtu) {
227 char cmd[256];
228 DWORD len;
229 ULONG status = TRUE;
230
231 memset(device, 0, sizeof(struct tuntap_dev));
232 device->device_handle = INVALID_HANDLE_VALUE;
233 device->device_name = devname[0] ? _strdup(devname) : NULL;
234 device->ifName = NULL;
235 device->ip_addr = inet_addr(device_ip);
236
237 iterate_win_network_adapters(choose_adapter_callback, device);
238
239 if(device->device_handle == INVALID_HANDLE_VALUE) {
240 if(!devname[0])
241 printf("No Windows tap devices found, did you run tapinstall.exe?\n");
242 else
243 printf("Cannot find tap device \"%s\"\n", devname);
244 return -1;
245 }
246
247 /* ************************************** */
248
249 if(device_mac[0])
250 set_interface_mac(device, device_mac);
251
252 /* Get MAC address from tap device->device_name */
253
254 if(!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC,
255 device->mac_addr, sizeof(device->mac_addr),
256 device->mac_addr, sizeof(device->mac_addr), &len, 0)) {
257 printf("Could not get MAC address from Windows tap %s (%s)\n",
258 device->device_name, device->ifName);
259 return -1;
260 }
261
262 device->mtu = mtu;
263
264 printf("Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n",
265 device->device_name, device_ip, device->ifName, device->mtu,
266 device->mac_addr[0] & 0xFF,
267 device->mac_addr[1] & 0xFF,
268 device->mac_addr[2] & 0xFF,
269 device->mac_addr[3] & 0xFF,
270 device->mac_addr[4] & 0xFF,
271 device->mac_addr[5] & 0xFF);
272
273 /* ****************** */
274
275 if ( 0 == strcmp("dhcp", address_mode) )
276 {
277 _snprintf(cmd, sizeof(cmd),
278 "netsh interface ip set address \"%s\" dhcp > nul",
279 device->ifName);
280 }
281 else
282 {
283 _snprintf(cmd, sizeof(cmd),
284 "netsh interface ip set address \"%s\" static %s %s > nul",
285 device->ifName, device_ip, device_mask);
286 }
287
288 if(system(cmd) == 0) {
289 device->ip_addr = inet_addr(device_ip);
290 device->device_mask = inet_addr(device_mask);
291 } else
292 printf("WARNING: Unable to set device %s IP address [%s]\n",
293 device->ifName, cmd);
294
295 /* ****************** */
296
297 /* MTU */
298 _snprintf(cmd, sizeof(cmd),
299 "netsh interface ipv4 set subinterface \"%s\" mtu=%d store=persistent > nul",
300 device->ifName, mtu);
301
302 if(system(cmd) != 0)
303 printf("WARNING: Unable to set device %s MTU [%s]\n",
304 device->ifName, cmd);
305
306 /* set driver media status to 'connected' (i.e. set the interface up) */
307 if (!DeviceIoControl (device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS,
308 &status, sizeof (status),
309 &status, sizeof (status), &len, NULL))
310 printf("WARNING: Unable to enable TAP adapter\n");
311
312 /*
313 * Initialize overlapped structures
314 */
315 device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
316 device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
317 if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) {
318 return -1;
319 }
320
321 return(0);
322 }
323
324 /* ************************************************ */
325
tuntap_read(struct tuntap_dev * tuntap,unsigned char * buf,int len)326 int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len)
327 {
328 DWORD read_size, last_err;
329
330 ResetEvent(tuntap->overlap_read.hEvent);
331 if (ReadFile(tuntap->device_handle, buf, len, &read_size, &tuntap->overlap_read)) {
332 //printf("tun_read(len=%d)\n", read_size);
333 return read_size;
334 }
335 switch (last_err = GetLastError()) {
336 case ERROR_IO_PENDING:
337 WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE);
338 GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, &read_size, FALSE);
339 return read_size;
340 break;
341 default:
342 printf("GetLastError() returned %d\n", last_err);
343 break;
344 }
345
346 return -1;
347 }
348 /* ************************************************ */
349
tuntap_write(struct tuntap_dev * tuntap,unsigned char * buf,int len)350 int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len)
351 {
352 DWORD write_size;
353
354 //printf("tun_write(len=%d)\n", len);
355
356 ResetEvent(tuntap->overlap_write.hEvent);
357 if (WriteFile(tuntap->device_handle,
358 buf,
359 len,
360 &write_size,
361 &tuntap->overlap_write)) {
362 //printf("DONE tun_write(len=%d)\n", write_size);
363 return write_size;
364 }
365 switch (GetLastError()) {
366 case ERROR_IO_PENDING:
367 WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE);
368 GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write,
369 &write_size, FALSE);
370 return write_size;
371 break;
372 default:
373 break;
374 }
375
376 return -1;
377 }
378
379 /* ************************************************ */
380
tuntap_open(struct tuntap_dev * device,char * dev,const char * address_mode,char * device_ip,char * device_mask,const char * device_mac,int mtu)381 int tuntap_open(struct tuntap_dev *device,
382 char *dev,
383 const char *address_mode, /* static or dhcp */
384 char *device_ip,
385 char *device_mask,
386 const char * device_mac,
387 int mtu) {
388 return(open_wintap(device, dev, address_mode, device_ip, device_mask, device_mac, mtu));
389 }
390
391 /* ************************************************ */
392
tuntap_close(struct tuntap_dev * tuntap)393 void tuntap_close(struct tuntap_dev *tuntap) {
394 CloseHandle(tuntap->device_handle);
395 }
396
397 /* Fill out the ip_addr value from the interface. Called to pick up dynamic
398 * address changes. */
tuntap_get_address(struct tuntap_dev * tuntap)399 void tuntap_get_address(struct tuntap_dev *tuntap)
400 {
401 }
402
403 /* ************************************************ */
404
405 #if 0
406 int main(int argc, char* argv[]) {
407 struct tuntap_dev tuntap;
408 int i;
409 int mtu = 1400;
410
411 printf("Welcome to n2n\n");
412 initWin32();
413 open_wintap(&tuntap, "static", "1.2.3.20", "255.255.255.0", mtu);
414
415 for(i=0; i<10; i++) {
416 u_char buf[MTU];
417 int rc;
418
419 rc = tun_read(&tuntap, buf, sizeof(buf));
420 buf[0]=2;
421 buf[1]=3;
422 buf[2]=4;
423
424 printf("tun_read returned %d\n", rc);
425 rc = tun_write(&tuntap, buf, rc);
426 printf("tun_write returned %d\n", rc);
427 }
428 // rc = tun_open (device->device_name, IF_MODE_TUN);
429 WSACleanup ();
430 return(0);
431 }
432
433 #endif
434