aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn-windows.c
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2012-12-12 21:22:57 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2012-12-12 21:22:57 +0000
commit530b55e3cf376821a4e28cfdd86f82e151c6f28f (patch)
treeb37cb0c9d9be9cf7b966acee32f966ba3bdb11b6 /src/vpn/gnunet-helper-vpn-windows.c
parent6401897402591c23caa12ecf9258dc179368cdc3 (diff)
downloadgnunet-530b55e3cf376821a4e28cfdd86f82e151c6f28f.tar.gz
gnunet-530b55e3cf376821a4e28cfdd86f82e151c6f28f.zip
Added basic functionality for setting IPv4/V6 addresses in win32 using
netsh. Added wrapper for launching programs in a windows shell. Added define for _tpopen
Diffstat (limited to 'src/vpn/gnunet-helper-vpn-windows.c')
-rw-r--r--src/vpn/gnunet-helper-vpn-windows.c242
1 files changed, 131 insertions, 111 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c
index 03da4ed60..a4c020186 100644
--- a/src/vpn/gnunet-helper-vpn-windows.c
+++ b/src/vpn/gnunet-helper-vpn-windows.c
@@ -77,6 +77,15 @@
77 */ 77 */
78#define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 78#define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
79 79
80/**
81 * TCHAR wrappers, which is missing in mingw's includes:
82 */
83#ifdef _UNICODE
84#define _tpopen _wpopen
85#else
86#define _tpopen _popen
87#endif
88
80/* 89/*
81 * Our local process' PID. Used for creating a sufficiently unique additional 90 * Our local process' PID. Used for creating a sufficiently unique additional
82 * hardware ID for our device. 91 * hardware ID for our device.
@@ -117,41 +126,68 @@ static TCHAR class[128];
117static GUID guid; 126static GUID guid;
118 127
119/** 128/**
129 * Wrapper for executing a shellcommand in windows.
130 *
131 * @param command - the command + parameters to execute
132 * @return * exitcode of the program executed,
133 * * EINVAL (cmd/file not found)
134 * * EPIPE (could not read STDOUT)
135 */
136static int
137execute_shellcommand (TCHAR * command)
138{
139 FILE *pipe;
140
141 if (NULL == command ||
142 NULL == (pipe = _tpopen (command, "rt")))
143 return EINVAL;
144
145#ifdef TESTING
146 {
147 TCHAR output[LINE_LEN];
148
149 _tprintf (_T ("executed command: %s"), command);
150 while (NULL != _fgetts (output, sizeof (output), pipe))
151 _tprintf (output);
152 }
153#endif
154
155 if (!feof (pipe))
156 return EPIPE;
157
158 return _pclose (pipe);
159}
160
161/**
120 * @brief Sets the IPv6-Address given in address on the interface dev 162 * @brief Sets the IPv6-Address given in address on the interface dev
121 * 163 *
122 * @param address the IPv6-Address 164 * @param address the IPv6-Address
123 * @param prefix_len the length of the network-prefix 165 * @param prefix_len the length of the network-prefix
124 */ 166 */
125static void 167static void
126set_address6 (const char *address, unsigned long prefix_len) 168set_address6 (const TCHAR *address, unsigned long prefix_len)
127{ 169{
128 int fd = -1; 170 int ret = EINVAL;
171 TCHAR command[LINE_LEN];
129 172
130 /* 173 /* TODO: Check if address makes sense? */
131 * parse the new address
132 */
133 174
134 /* 175 /*
135 * Get the index of the if 176 * prepare the command
136 */ 177 */
137 178
179 _sntprintf (command, LINE_LEN,
180 _T ("netsh interface ipv6 add address \"%s\" %s/%d"),
181 device_visible_name, address, prefix_len);
138 /* 182 /*
139 * Set the address 183 * Set the address
140 */ 184 */
185 ret = execute_shellcommand (command);
141 186
142 /* 187 /* Did it work?*/
143 * Get the flags 188 if (0 != ret)
144 */
145
146
147 /*
148 * Add the UP and RUNNING flags
149 */
150
151
152 if (0 != close (fd))
153 { 189 {
154 fprintf (stderr, "close failed: %s\n", strerror (errno)); 190 _ftprintf (stderr, _T ("Setting IPv6 address failed: %s\n"), strerror (ret));
155 exit (1); 191 exit (1);
156 } 192 }
157} 193}
@@ -164,42 +200,28 @@ set_address6 (const char *address, unsigned long prefix_len)
164 * @param mask the netmask 200 * @param mask the netmask
165 */ 201 */
166static void 202static void
167set_address4 (const char *dev, const char *address, const char *mask) 203set_address4 (const char *address, const char *mask)
168{ 204{
169 int fd = -1; 205 int ret = EINVAL;
170 206 TCHAR command[LINE_LEN];
171 /*
172 * Parse the address
173 */
174 207
175 /* 208 /* TODO: Check if address & prefix_len make sense*/
176 * Set the address
177 */
178 209
179 /* 210 /*
180 * Parse the netmask 211 * prepare the command
181 */ 212 */
182 213 _sntprintf (command, LINE_LEN,
183 214 _T ("netsh interface ipv4 add address \"%s\" %s %s"),
215 device_visible_name, address, mask);
184 /* 216 /*
185 * Set the netmask 217 * Set the address
186 */
187
188
189 /*
190 * Get the flags
191 */
192
193
194 /*
195 * Add the UP and RUNNING flags
196 */ 218 */
219 ret = execute_shellcommand (command);
197 220
198 221 /* Did it work?*/
199 if (0 != close (fd)) 222 if (0 != ret)
200 { 223 {
201 fprintf (stderr, "close failed: %s\n", strerror (errno)); 224 _ftprintf (stderr, _T ("Setting IPv4 address failed: %s\n"), strerror (ret));
202 (void) close (fd);
203 exit (1); 225 exit (1);
204 } 226 }
205} 227}
@@ -220,7 +242,7 @@ setup_interface ()
220 */ 242 */
221 TCHAR inf_file_path[MAX_PATH]; 243 TCHAR inf_file_path[MAX_PATH];
222 TCHAR hwidlist[LINE_LEN + 4]; 244 TCHAR hwidlist[LINE_LEN + 4];
223 245
224 int str_lenth = 0; 246 int str_lenth = 0;
225 247
226 248
@@ -238,9 +260,9 @@ setup_interface ()
238 * 260 *
239 * A HWID list is double-\0 terminated and \0 separated 261 * A HWID list is double-\0 terminated and \0 separated
240 */ 262 */
241 str_lenth = _tcslen (hwidlist) + 1 ; 263 str_lenth = _tcslen (hwidlist) + 1;
242 _tcsncpy (&hwidlist[str_lenth], secondary_hwid, LINE_LEN - str_lenth); 264 _tcsncpy (&hwidlist[str_lenth], secondary_hwid, LINE_LEN - str_lenth);
243 265
244 /** 266 /**
245 * Locate the inf-file, we need to store it somewhere where the system can 267 * Locate the inf-file, we need to store it somewhere where the system can
246 * find it. A good choice would be CWD/PDW or %WINDIR$\system32\ 268 * find it. A good choice would be CWD/PDW or %WINDIR$\system32\
@@ -257,44 +279,43 @@ setup_interface ()
257 &guid, 279 &guid,
258 class, sizeof (class) / sizeof (TCHAR), 280 class, sizeof (class) / sizeof (TCHAR),
259 NULL)) 281 NULL))
260 return FALSE; 282 return FALSE;
261 283
262 /** 284 /**
263 * Collect all the other needed information... 285 * Collect all the other needed information...
264 * let the system fill our this form 286 * let the system fill our this form
265 */ 287 */
266 DeviceInfo = SetupDiCreateDeviceInfoList (&guid, NULL); 288 DeviceInfo = SetupDiCreateDeviceInfoList (&guid, NULL);
267 if (DeviceInfo == INVALID_HANDLE_VALUE) 289 if (DeviceInfo == INVALID_HANDLE_VALUE)
268 return FALSE; 290 return FALSE;
269 291
270 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); 292 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA);
271 if (! SetupDiCreateDeviceInfo (DeviceInfo, 293 if (!SetupDiCreateDeviceInfo (DeviceInfo,
272 class, 294 class,
273 &guid, 295 &guid,
274 NULL, 296 NULL,
275 NULL, 297 NULL,
276 DICD_GENERATE_ID, 298 DICD_GENERATE_ID,
277 &DeviceNode)) 299 &DeviceNode))
278 return FALSE; 300 return FALSE;
279 301
280 /* Deploy all the information collected into the registry */ 302 /* Deploy all the information collected into the registry */
281 if (!SetupDiSetDeviceRegistryProperty (DeviceInfo, 303 if (!SetupDiSetDeviceRegistryProperty (DeviceInfo,
282 &DeviceNode, 304 &DeviceNode,
283 SPDRP_HARDWAREID, 305 SPDRP_HARDWAREID,
284 (LPBYTE) hwidlist, 306 (LPBYTE) hwidlist,
285 (lstrlen (hwidlist) + 2) * sizeof (TCHAR))) 307 (lstrlen (hwidlist) + 2) * sizeof (TCHAR)))
286 return FALSE; 308 return FALSE;
287 309
288 /* Install our new class(=device) into the system */ 310 /* Install our new class(=device) into the system */
289 if (! SetupDiCallClassInstaller (DIF_REGISTERDEVICE, 311 if (!SetupDiCallClassInstaller (DIF_REGISTERDEVICE,
290 DeviceInfo, 312 DeviceInfo,
291 &DeviceNode)) 313 &DeviceNode))
292 return FALSE; 314 return FALSE;
293 315
294 return TRUE; 316 return TRUE;
295} 317}
296 318
297
298/** 319/**
299 * Remove our new virtual interface to use for tunneling. 320 * Remove our new virtual interface to use for tunneling.
300 * This function must be called AFTER setup_interface! 321 * This function must be called AFTER setup_interface!
@@ -305,10 +326,10 @@ static boolean
305remove_interface () 326remove_interface ()
306{ 327{
307 SP_REMOVEDEVICE_PARAMS remove; 328 SP_REMOVEDEVICE_PARAMS remove;
308 329
309 if (INVALID_HANDLE_VALUE == DeviceInfo) 330 if (INVALID_HANDLE_VALUE == DeviceInfo)
310 return FALSE; 331 return FALSE;
311 332
312 remove.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER); 333 remove.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER);
313 remove.HwProfile = 0; 334 remove.HwProfile = 0;
314 remove.Scope = DI_REMOVEDEVICE_GLOBAL; 335 remove.Scope = DI_REMOVEDEVICE_GLOBAL;
@@ -317,21 +338,21 @@ remove_interface ()
317 * 1. Prepare our existing device information set, and place the 338 * 1. Prepare our existing device information set, and place the
318 * uninstall related information into the structure 339 * uninstall related information into the structure
319 */ 340 */
320 if (! SetupDiSetClassInstallParams (DeviceInfo, 341 if (!SetupDiSetClassInstallParams (DeviceInfo,
321 (PSP_DEVINFO_DATA) &DeviceNode, 342 (PSP_DEVINFO_DATA) & DeviceNode,
322 &remove.ClassInstallHeader, 343 &remove.ClassInstallHeader,
323 sizeof (remove))) 344 sizeof (remove)))
324 return FALSE; 345 return FALSE;
325 /* 346 /*
326 * 2. Uninstall the virtual interface using the class installer 347 * 2. Uninstall the virtual interface using the class installer
327 */ 348 */
328 if (! SetupDiCallClassInstaller (DIF_REMOVE, 349 if (!SetupDiCallClassInstaller (DIF_REMOVE,
329 DeviceInfo, 350 DeviceInfo,
330 (PSP_DEVINFO_DATA) &DeviceNode)) 351 (PSP_DEVINFO_DATA) & DeviceNode))
331 return FALSE; 352 return FALSE;
332 353
333 SetupDiDestroyDeviceInfoList(DeviceInfo); 354 SetupDiDestroyDeviceInfoList (DeviceInfo);
334 355
335 return TRUE; 356 return TRUE;
336} 357}
337 358
@@ -351,7 +372,7 @@ resolve_interface_name ()
351 LONG status; 372 LONG status;
352 DWORD len; 373 DWORD len;
353 int i = 0; 374 int i = 0;
354 boolean retval=FALSE; 375 boolean retval = FALSE;
355 TCHAR adapter[] = _T (INTERFACE_REGISTRY_LOCATION); 376 TCHAR adapter[] = _T (INTERFACE_REGISTRY_LOCATION);
356 377
357 /* We can obtain the PNP instance ID from our setupapi handle */ 378 /* We can obtain the PNP instance ID from our setupapi handle */
@@ -380,9 +401,9 @@ resolve_interface_name ()
380 TCHAR instance_key[256]; 401 TCHAR instance_key[256];
381 TCHAR query_key [256]; 402 TCHAR query_key [256];
382 HKEY instance_key_handle; 403 HKEY instance_key_handle;
383 TCHAR pnpinstanceid_name[] = _T("PnpInstanceID"); 404 TCHAR pnpinstanceid_name[] = _T ("PnpInstanceID");
384 TCHAR pnpinstanceid_value[256]; 405 TCHAR pnpinstanceid_value[256];
385 TCHAR adaptername_name[] = _T("Name"); 406 TCHAR adaptername_name[] = _T ("Name");
386 DWORD data_type; 407 DWORD data_type;
387 408
388 len = sizeof (adapter_key_handle); 409 len = sizeof (adapter_key_handle);
@@ -407,8 +428,8 @@ resolve_interface_name ()
407 428
408 /* prepare our new querty string: */ 429 /* prepare our new querty string: */
409 _sntprintf (query_key, 256, _T ("%s\\%s\\Connection"), 430 _sntprintf (query_key, 256, _T ("%s\\%s\\Connection"),
410 _T (INTERFACE_REGISTRY_LOCATION), 431 _T (INTERFACE_REGISTRY_LOCATION),
411 instance_key); 432 instance_key);
412 433
413 /* look inside instance_key\\Connection */ 434 /* look inside instance_key\\Connection */
414 status = RegOpenKeyEx ( 435 status = RegOpenKeyEx (
@@ -420,7 +441,7 @@ resolve_interface_name ()
420 441
421 if (status != ERROR_SUCCESS) 442 if (status != ERROR_SUCCESS)
422 continue; 443 continue;
423 444
424 /* now, read our PnpInstanceID */ 445 /* now, read our PnpInstanceID */
425 len = sizeof (pnpinstanceid_value); 446 len = sizeof (pnpinstanceid_value);
426 status = RegQueryValueEx (instance_key_handle, 447 status = RegQueryValueEx (instance_key_handle,
@@ -432,12 +453,12 @@ resolve_interface_name ()
432 453
433 if (status != ERROR_SUCCESS || data_type != REG_SZ) 454 if (status != ERROR_SUCCESS || data_type != REG_SZ)
434 goto cleanup; 455 goto cleanup;
435 456
436 /* compare the value we got to our devices PNPInstanceID*/ 457 /* compare the value we got to our devices PNPInstanceID*/
437 if ( 0 != _tcsncmp (pnpinstanceid_value, pnp_instance_id, 458 if (0 != _tcsncmp (pnpinstanceid_value, pnp_instance_id,
438 sizeof (pnpinstanceid_value)/sizeof(TCHAR))) 459 sizeof (pnpinstanceid_value) / sizeof (TCHAR)))
439 goto cleanup; 460 goto cleanup;
440 461
441 len = sizeof (device_visible_name); 462 len = sizeof (device_visible_name);
442 status = RegQueryValueEx ( 463 status = RegQueryValueEx (
443 instance_key_handle, 464 instance_key_handle,
@@ -451,9 +472,9 @@ resolve_interface_name ()
451 { 472 {
452 retval = TRUE; 473 retval = TRUE;
453 } 474 }
454 cleanup: 475cleanup:
455 RegCloseKey (instance_key_handle); 476 RegCloseKey (instance_key_handle);
456 477
457 ++i; 478 ++i;
458 } 479 }
459 480
@@ -472,7 +493,7 @@ resolve_interface_name ()
472static int 493static int
473init_tun (TCHAR *hwid) 494init_tun (TCHAR *hwid)
474{ 495{
475 int fd; 496 int fd=-1;
476 497
477 if (NULL == hwid) 498 if (NULL == hwid)
478 { 499 {
@@ -480,17 +501,19 @@ init_tun (TCHAR *hwid)
480 return -1; 501 return -1;
481 } 502 }
482 503
483 if (! setup_interface()){ 504 if (!setup_interface ())
505 {
484 errno = ENODEV; 506 errno = ENODEV;
485 return -1; 507 return -1;
486 } 508 }
487 509
488 if (! resolve_interface_name()){ 510 if (!resolve_interface_name ())
511 {
489 errno = ENODEV; 512 errno = ENODEV;
490 return -1; 513 return -1;
491 } 514 }
492 515
493 516
494 return fd; 517 return fd;
495} 518}
496 519
@@ -520,7 +543,6 @@ run (int fd_tun)
520 543
521} 544}
522 545
523
524/** 546/**
525 * Open VPN tunnel interface. 547 * Open VPN tunnel interface.
526 * 548 *
@@ -539,24 +561,24 @@ main (int argc, char **argv)
539 TCHAR pid_as_string[LINE_LEN / 4]; 561 TCHAR pid_as_string[LINE_LEN / 4];
540 int fd_tun; 562 int fd_tun;
541 int global_ret; 563 int global_ret;
542 564
543 if (6 != argc) 565 if (6 != argc)
544 { 566 {
545 fprintf (stderr, "Fatal: must supply 5 arguments!\n"); 567 fprintf (stderr, "Fatal: must supply 5 arguments!\n");
546 return 1; 568 return 1;
547 } 569 }
548 570
549 strncpy (hwid, argv[1], LINE_LEN); 571 strncpy (hwid, argv[1], LINE_LEN);
550 hwid[LINE_LEN - 1] = _T('\0'); 572 hwid[LINE_LEN - 1] = _T ('\0');
551 573
552 /* 574 /*
553 * We use our PID for finding/resolving the control-panel name of our virtual 575 * We use our PID for finding/resolving the control-panel name of our virtual
554 * device. PIDs are (of course) unique at runtime, thus we can safely use it 576 * device. PIDs are (of course) unique at runtime, thus we can safely use it
555 * as additional hardware-id for our device. 577 * as additional hardware-id for our device.
556 */ 578 */
557 _itot(_getpid(), pid_as_string, 10); 579 _itot (_getpid (), pid_as_string, 10);
558 strncpy (secondary_hwid, hwid, LINE_LEN); 580 strncpy (secondary_hwid, hwid, LINE_LEN);
559 strncat (secondary_hwid, pid_as_string, LINE_LEN); 581 strncat (secondary_hwid, pid_as_string, LINE_LEN);
560 582
561 if (-1 == (fd_tun = init_tun (hwid))) 583 if (-1 == (fd_tun = init_tun (hwid)))
562 { 584 {
@@ -577,7 +599,8 @@ main (int argc, char **argv)
577 if ((prefix_len < 1) || (prefix_len > 127)) 599 if ((prefix_len < 1) || (prefix_len > 127))
578 { 600 {
579 fprintf (stderr, "Fatal: prefix_len out of range\n"); 601 fprintf (stderr, "Fatal: prefix_len out of range\n");
580 return 1; 602 global_ret = -1;
603 goto cleanup;
581 } 604 }
582 605
583 set_address6 (address, prefix_len); 606 set_address6 (address, prefix_len);
@@ -588,13 +611,10 @@ main (int argc, char **argv)
588 const char *address = argv[4]; 611 const char *address = argv[4];
589 const char *mask = argv[5]; 612 const char *mask = argv[5];
590 613
591 set_address4 (NULL, address, mask); 614 set_address4 (address, mask);
592 }
593
594 if (setup_interface ())
595 {
596 ;
597 } 615 }
616
617 /*TODO: attach network interface! (need to research how that works with ovpn )*/
598 618
599 /* 619 /*
600 uid_t uid = getuid (); 620 uid_t uid = getuid ();
@@ -613,10 +633,10 @@ main (int argc, char **argv)
613 // no exit, we might as well die with SIGPIPE should it ever happen 633 // no exit, we might as well die with SIGPIPE should it ever happen
614 } 634 }
615 */ 635 */
616 //run (fd_tun); 636 run (fd_tun);
617 global_ret = 0; 637 global_ret = 0;
618cleanup: 638cleanup:
619 remove_interface(); 639 remove_interface ();
620 640
621 return global_ret; 641 return global_ret;
622} 642}