aboutsummaryrefslogtreecommitdiff
path: root/src/nat/libnatpmp/getgateway.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/libnatpmp/getgateway.c')
-rw-r--r--src/nat/libnatpmp/getgateway.c531
1 files changed, 0 insertions, 531 deletions
diff --git a/src/nat/libnatpmp/getgateway.c b/src/nat/libnatpmp/getgateway.c
deleted file mode 100644
index d948669ec..000000000
--- a/src/nat/libnatpmp/getgateway.c
+++ /dev/null
@@ -1,531 +0,0 @@
1/* $Id: getgateway.c,v 1.13 2009/03/10 10:15:31 nanard Exp $ */
2/* libnatpmp
3 * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
16#include <stdio.h>
17#include <ctype.h>
18#include <string.h>
19#ifndef WIN32
20#include <netinet/in.h>
21#endif
22#include <sys/param.h>
23/* There is no portable method to get the default route gateway.
24 * So below are three differents functions implementing this.
25 * Parsing /proc/net/route is for linux.
26 * sysctl is the way to access such informations on BSD systems.
27 * Many systems should provide route information through raw PF_ROUTE
28 * sockets. */
29#ifdef __linux__
30#define USE_PROC_NET_ROUTE
31#undef USE_SOCKET_ROUTE
32#undef USE_SYSCTL_NET_ROUTE
33#endif
34
35#ifdef BSD
36#undef USE_PROC_NET_ROUTE
37#define USE_SOCKET_ROUTE
38#undef USE_SYSCTL_NET_ROUTE
39#endif
40
41#ifdef __APPLE__
42#undef USE_PROC_NET_ROUTE
43#undef USE_SOCKET_ROUTE
44#define USE_SYSCTL_NET_ROUTE
45#endif
46
47#if (defined(sun) && defined(__SVR4))
48#undef USE_PROC_NET_ROUTE
49#define USE_SOCKET_ROUTE
50#undef USE_SYSCTL_NET_ROUTE
51#endif
52
53#ifdef WIN32
54#undef USE_PROC_NET_ROUTE
55#undef USE_SOCKET_ROUTE
56#undef USE_SYSCTL_NET_ROUTE
57#define USE_WIN32_CODE
58#endif
59
60#ifdef USE_PROC_NET_ROUTE
61#include <arpa/inet.h>
62#endif
63#ifdef USE_SYSCTL_NET_ROUTE
64#include <stdlib.h>
65#include <sys/sysctl.h>
66#include <sys/socket.h>
67#include <net/route.h>
68#endif
69#ifdef USE_SOCKET_ROUTE
70#include <unistd.h>
71#include <string.h>
72#include <sys/socket.h>
73#include <net/if.h>
74#include <net/route.h>
75#endif
76#ifdef WIN32
77#include <unknwn.h>
78#include <winreg.h>
79#define MAX_KEY_LENGTH 255
80#define MAX_VALUE_LENGTH 16383
81#endif
82#include "getgateway.h"
83
84#ifndef WIN32
85#define SUCCESS (0)
86#define FAILED (-1)
87#endif
88
89#ifdef USE_PROC_NET_ROUTE
90int
91getdefaultgateway (int *af, uint8_t addr[16])
92{
93 unsigned int tmp;
94 uint8_t d[16];
95 char buf[256];
96 int line = 0;
97 FILE *f;
98 char *p;
99 int i;
100 f = fopen ("/proc/net/route", "r");
101 if (!f)
102 return FAILED;
103 while (fgets (buf, sizeof (buf), f))
104 {
105 if (line > 0)
106 {
107 p = buf;
108 while (*p && !isspace ( (unsigned char) *p))
109 p++;
110 while (*p && isspace ( (unsigned char) *p))
111 p++;
112 for (i = 0; i < 16; i++)
113 {
114 if (sscanf (p, "%2X", &tmp) < 1)
115 d[i] = tmp;
116 else
117 break;
118 }
119
120 if (i == 8) /* IPv4 address on 8 hex chars */
121 {
122 /* Move the 32 bits address to the end of the array */
123 for (i = 4; i < 16; i++)
124 d[i] = 0;
125
126 for (i = 0; i < 4; i++)
127 {
128 d[i+12] = d[i];
129 d[i] = 0;
130 }
131 memcpy (addr, d, 16 * sizeof (uint8_t));
132 *af = AF_INET;
133 fclose (f);
134 return SUCCESS;
135 }
136 else if (i == 16) /* IPv6 address on 16 hex chars,
137 * or IPv4 address padded with 0 */
138 {
139 memcpy (addr, d, 16 * sizeof (uint8_t));
140 /* Check at what byte the actual address starts */
141 for (i = 0; i <= 12; i++)
142 if (addr[i]) break;
143
144 if (i == 12)
145 {
146 *af = AF_INET;
147 fclose (f);
148 return SUCCESS;
149 }
150 else if (i == 0)
151 {
152 *af = AF_INET6;
153 fclose (f);
154 return SUCCESS;
155 }
156 }
157 }
158 line++;
159 }
160 /* default route not found ! */
161 if (f)
162 fclose (f);
163 return FAILED;
164}
165#endif /* #ifdef USE_PROC_NET_ROUTE */
166
167
168#ifdef USE_SYSCTL_NET_ROUTE
169
170#define ROUNDUP(a) \
171 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
172
173int
174getdefaultgateway (int *af, uint8_t addr[16])
175{
176#if 0
177 /* net.route.0.inet.dump.0.0 ? */
178 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
179 NET_RT_DUMP, 0, 0 /*tableid */
180 };
181#endif
182 /* net.route.0.inet.flags.gateway */
183 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
184 NET_RT_FLAGS, RTF_GATEWAY
185 };
186 size_t l;
187 char *buf, *p;
188 struct rt_msghdr *rt;
189 struct sockaddr *sa;
190 struct sockaddr *sa_tab[RTAX_MAX];
191 int i;
192 int r = FAILED;
193 if (sysctl (mib, sizeof (mib) / sizeof (int), 0, &l, 0, 0) < 0)
194 {
195 return FAILED;
196 }
197 if (l > 0)
198 {
199 buf = malloc (l);
200 if (sysctl (mib, sizeof (mib) / sizeof (int), buf, &l, 0, 0) < 0)
201 {
202 free (buf);
203 return FAILED;
204 }
205 for (p = buf; p < buf + l; p += rt->rtm_msglen)
206 {
207 rt = (struct rt_msghdr *) p;
208 sa = (struct sockaddr *) (rt + 1);
209 for (i = 0; i < RTAX_MAX; i++)
210 {
211 if (rt->rtm_addrs & (1 << i))
212 {
213 sa_tab[i] = sa;
214 sa =
215 (struct sockaddr *) ((char *) sa + ROUNDUP (sa->sa_len));
216 }
217 else
218 {
219 sa_tab[i] = NULL;
220 }
221 }
222 if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
223 (RTA_DST | RTA_GATEWAY))
224 && sa_tab[RTAX_DST]->sa_family == AF_INET
225 && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET)
226 {
227 if (((struct sockaddr_in *) sa_tab[RTAX_DST])->sin_addr.
228 s_addr == 0)
229 {
230 *addr =
231 ((struct sockaddr_in *) (sa_tab[RTAX_GATEWAY]))->sin_addr.
232 s_addr;
233 *af = AF_INET;
234 r = SUCCESS;
235 }
236 }
237 else if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
238 (RTA_DST | RTA_GATEWAY))
239 && sa_tab[RTAX_DST]->sa_family == AF_INET6
240 && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET6)
241 {
242 if (IN6_IS_ADDR_UNSPECIFIED (&(((struct sockaddr_in6 *)
243 sa_tab[RTAX_DST])->sin6_addr)))
244 {
245 *(struct in6_addr *)addr =
246 ((struct sockaddr_in6 *) (sa_tab[RTAX_GATEWAY]))->sin6_addr;
247 *af = AF_INET6;
248 r = SUCCESS;
249 }
250 }
251 }
252 free (buf);
253 }
254 return r;
255}
256#endif /* #ifdef USE_SYSCTL_NET_ROUTE */
257
258
259#ifdef USE_SOCKET_ROUTE
260/* Thanks to Darren Kenny for this code */
261#define NEXTADDR(w, u) \
262 if (rtm_addrs & (w)) {\
263 l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
264 }
265
266#define rtm m_rtmsg.m_rtm
267
268struct
269{
270 struct rt_msghdr m_rtm;
271 char m_space[512];
272} m_rtmsg;
273
274int
275getdefaultgateway (int *af, uint8_t addr[16])
276{
277 int s, seq, l, rtm_addrs, i;
278 pid_t pid;
279 struct sockaddr so_dst, so_mask;
280 char *cp = m_rtmsg.m_space;
281 struct sockaddr *gate = NULL, *sa;
282 struct rt_msghdr *msg_hdr;
283
284 pid = getpid ();
285 seq = 0;
286 rtm_addrs = RTA_DST | RTA_NETMASK;
287
288 memset (&so_dst, 0, sizeof (so_dst));
289 memset (&so_mask, 0, sizeof (so_mask));
290 memset (&rtm, 0, sizeof (struct rt_msghdr));
291
292 rtm.rtm_type = RTM_GET;
293 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
294 rtm.rtm_version = RTM_VERSION;
295 rtm.rtm_seq = ++seq;
296 rtm.rtm_addrs = rtm_addrs;
297
298 so_dst.sa_family = AF_INET;
299 so_mask.sa_family = AF_INET;
300
301 NEXTADDR (RTA_DST, so_dst);
302 NEXTADDR (RTA_NETMASK, so_mask);
303
304 rtm.rtm_msglen = l = cp - (char *) &m_rtmsg;
305
306 s = socket (PF_ROUTE, SOCK_RAW, 0);
307
308 if (write (s, (char *) &m_rtmsg, l) < 0)
309 {
310 close (s);
311 return FAILED;
312 }
313
314 do
315 {
316 l = read (s, (char *) &m_rtmsg, sizeof (m_rtmsg));
317 }
318 while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
319
320 close (s);
321
322 msg_hdr = &rtm;
323
324 cp = ((char *) (msg_hdr + 1));
325 if (msg_hdr->rtm_addrs)
326 {
327 for (i = 1; i; i <<= 1)
328 if (i & msg_hdr->rtm_addrs)
329 {
330 sa = (struct sockaddr *) cp;
331 if (i == RTA_GATEWAY)
332 gate = sa;
333
334 cp += sizeof (struct sockaddr);
335 }
336 }
337 else
338 {
339 return FAILED;
340 }
341
342
343 if (gate != NULL && gate->sa_family == AF_INET)
344 {
345 *addr = ((struct sockaddr_in *) gate)->sin_addr.s_addr;
346 *af = AF_INET;
347 return SUCCESS;
348 }
349 else if (gate != NULL && gate->sa_family == AF_INET6)
350 {
351 memcpy (addr, ((struct sockaddr_in6 *) gate)->sin6_addr.s6_addr, 16 * sizeof (uint8_t));
352 *af = AF_INET6;
353 return SUCCESS;
354 }
355 else
356 {
357 return FAILED;
358 }
359}
360#endif /* #ifdef USE_SOCKET_ROUTE */
361
362#ifdef USE_WIN32_CODE
363int
364getdefaultgateway (int *af, uint8_t addr[16])
365{
366 HKEY networkCardsKey;
367 HKEY networkCardKey;
368 HKEY interfacesKey;
369 HKEY interfaceKey;
370 DWORD i = 0;
371 DWORD numSubKeys = 0;
372 TCHAR keyName[MAX_KEY_LENGTH];
373 DWORD keyNameLength = MAX_KEY_LENGTH;
374 TCHAR keyValue[MAX_VALUE_LENGTH];
375 DWORD keyValueLength = MAX_VALUE_LENGTH;
376 DWORD keyValueType = REG_SZ;
377 TCHAR gatewayValue[MAX_VALUE_LENGTH];
378 DWORD gatewayValueLength = MAX_VALUE_LENGTH;
379 DWORD gatewayValueType = REG_MULTI_SZ;
380 int done = 0;
381
382 char networkCardsPath[] =
383 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
384 char interfacesPath[] =
385 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
386
387 // The windows registry lists its primary network devices in the following location:
388 // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
389 //
390 // Each network device has its own subfolder, named with an index, with various properties:
391 // -NetworkCards
392 // -5
393 // -Description = Broadcom 802.11n Network Adapter
394 // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
395 // -8
396 // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
397 // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
398 //
399 // The above service name is the name of a subfolder within:
400 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
401 //
402 // There may be more subfolders in this interfaces path than listed in the network cards path above:
403 // -Interfaces
404 // -{3a539854-6a70-11db-887c-806e6f6e6963}
405 // -DhcpIPAddress = 0.0.0.0
406 // -[more]
407 // -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
408 // -DhcpIPAddress = 10.0.1.4
409 // -DhcpDefaultGateway = 10.0.1.1
410 // -[more]
411 // -{86226414-5545-4335-A9D1-5BD7120119AD}
412 // -DhcpIpAddress = 10.0.1.5
413 // -DhcpDefaultGateay = 10.0.1.1
414 // -[more]
415 //
416 // In order to extract this information, we enumerate each network card, and extract the ServiceName value.
417 // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
418 // Once one is found, we're done.
419 //
420 // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
421 // However, the technique used is the technique most cited on the web, and we assume it to be more correct.
422
423 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predifined key
424 networkCardsPath, // Name of registry subkey to open
425 0, // Reserved - must be zero
426 KEY_READ, // Mask - desired access rights
427 &networkCardsKey)) // Pointer to output key
428 {
429 // Unable to open network cards keys
430 return -1;
431 }
432
433 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predefined key
434 interfacesPath, // Name of registry subkey to open
435 0, // Reserved - must be zero
436 KEY_READ, // Mask - desired access rights
437 &interfacesKey)) // Pointer to output key
438 {
439 // Unable to open interfaces key
440 RegCloseKey (networkCardsKey);
441 return -1;
442 }
443
444 // Figure out how many subfolders are within the NetworkCards folder
445 RegQueryInfoKey (networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL,
446 NULL, NULL, NULL, NULL, NULL);
447
448 //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
449
450 // Enumrate through each subfolder within the NetworkCards folder
451 for (i = 0; i < numSubKeys && !done; i++)
452 {
453 keyNameLength = MAX_KEY_LENGTH;
454 if (ERROR_SUCCESS == RegEnumKeyEx (networkCardsKey, // Open registry key
455 i, // Index of subkey to retrieve
456 keyName, // Buffer that receives the name of the subkey
457 &keyNameLength, // Variable that receives the size of the above buffer
458 NULL, // Reserved - must be NULL
459 NULL, // Buffer that receives the class string
460 NULL, // Variable that receives the size of the above buffer
461 NULL)) // Variable that receives the last write time of subkey
462 {
463 if (RegOpenKeyEx
464 (networkCardsKey, keyName, 0, KEY_READ,
465 &networkCardKey) == ERROR_SUCCESS)
466 {
467 keyValueLength = MAX_VALUE_LENGTH;
468 if (ERROR_SUCCESS == RegQueryValueEx (networkCardKey, // Open registry key
469 "ServiceName", // Name of key to query
470 NULL, // Reserved - must be NULL
471 &keyValueType, // Receives value type
472 keyValue, // Receives value
473 &keyValueLength)) // Receives value length in bytes
474 {
475 //printf("keyValue: %s\n", keyValue);
476
477 if (RegOpenKeyEx
478 (interfacesKey, keyValue, 0, KEY_READ,
479 &interfaceKey) == ERROR_SUCCESS)
480 {
481 gatewayValueLength = MAX_VALUE_LENGTH;
482 if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
483 "DhcpDefaultGateway", // Name of key to query
484 NULL, // Reserved - must be NULL
485 &gatewayValueType, // Receives value type
486 gatewayValue, // Receives value
487 &gatewayValueLength)) // Receives value length in bytes
488 {
489 // Check to make sure it's a string
490 if (gatewayValueType == REG_MULTI_SZ
491 || gatewayValueType == REG_SZ)
492 {
493 //printf("gatewayValue: %s\n", gatewayValue);
494 done = 1;
495 }
496 }
497 else if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
498 "DefaultGateway", // Name of key to query
499 NULL, // Reserved - must be NULL
500 &gatewayValueType, // Receives value type
501 gatewayValue, // Receives value
502 &gatewayValueLength)) // Receives value length in bytes
503 {
504 // Check to make sure it's a string
505 if (gatewayValueType == REG_MULTI_SZ
506 || gatewayValueType == REG_SZ)
507 {
508 //printf("gatewayValue: %s\n", gatewayValue);
509 done = 1;
510 }
511 }
512 RegCloseKey (interfaceKey);
513 }
514 }
515 RegCloseKey (networkCardKey);
516 }
517 }
518 }
519
520 RegCloseKey (interfacesKey);
521 RegCloseKey (networkCardsKey);
522
523 if (done)
524 {
525 *addr = inet_addr (gatewayValue);
526 return 0;
527 }
528
529 return -1;
530}
531#endif /* #ifdef USE_WIN32_CODE */