getgateway.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /* $Id: getgateway.c,v 1.25 2014/04/22 10:28:57 nanard Exp $ */
  2. /* libnatpmp
  3. Copyright (c) 2007-2014, Thomas BERNARD
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7. * Redistributions of source code must retain the above copyright notice,
  8. this list of conditions and the following disclaimer.
  9. * Redistributions in binary form must reproduce the above copyright notice,
  10. this list of conditions and the following disclaimer in the documentation
  11. and/or other materials provided with the distribution.
  12. * The name of the author may not be used to endorse or promote products
  13. derived from this software without specific prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #ifndef WIN32
  29. #include <netinet/in.h>
  30. #endif
  31. #if !defined(_MSC_VER)
  32. #include <sys/param.h>
  33. #endif
  34. /* There is no portable method to get the default route gateway.
  35. * So below are four (or five ?) differents functions implementing this.
  36. * Parsing /proc/net/route is for linux.
  37. * sysctl is the way to access such informations on BSD systems.
  38. * Many systems should provide route information through raw PF_ROUTE
  39. * sockets.
  40. * In MS Windows, default gateway is found by looking into the registry
  41. * or by using GetBestRoute(). */
  42. #ifdef __linux__
  43. #define USE_PROC_NET_ROUTE
  44. #undef USE_SOCKET_ROUTE
  45. #undef USE_SYSCTL_NET_ROUTE
  46. #endif
  47. #if defined(BSD) || defined(__FreeBSD_kernel__)
  48. #undef USE_PROC_NET_ROUTE
  49. #define USE_SOCKET_ROUTE
  50. #undef USE_SYSCTL_NET_ROUTE
  51. #include <sys/sysctl.h>
  52. #endif
  53. #ifdef __APPLE__
  54. #undef USE_PROC_NET_ROUTE
  55. #undef USE_SOCKET_ROUTE
  56. #define USE_SYSCTL_NET_ROUTE
  57. #endif
  58. #if (defined(sun) && defined(__SVR4))
  59. #undef USE_PROC_NET_ROUTE
  60. #define USE_SOCKET_ROUTE
  61. #undef USE_SYSCTL_NET_ROUTE
  62. #endif
  63. #ifdef WIN32
  64. #undef USE_PROC_NET_ROUTE
  65. #undef USE_SOCKET_ROUTE
  66. #undef USE_SYSCTL_NET_ROUTE
  67. //#define USE_WIN32_CODE
  68. #define USE_WIN32_CODE_2
  69. #endif
  70. #ifdef __CYGWIN__
  71. #undef USE_PROC_NET_ROUTE
  72. #undef USE_SOCKET_ROUTE
  73. #undef USE_SYSCTL_NET_ROUTE
  74. #define USE_WIN32_CODE
  75. #include <stdarg.h>
  76. #include <w32api/windef.h>
  77. #include <w32api/winbase.h>
  78. #include <w32api/winreg.h>
  79. #endif
  80. #ifdef __HAIKU__
  81. #include <stdlib.h>
  82. #include <unistd.h>
  83. #include <net/if.h>
  84. #include <sys/sockio.h>
  85. #define USE_HAIKU_CODE
  86. #endif
  87. #ifdef USE_SYSCTL_NET_ROUTE
  88. #include <stdlib.h>
  89. #include <sys/socket.h>
  90. #include <net/route.h>
  91. #endif
  92. #ifdef USE_SOCKET_ROUTE
  93. #include <unistd.h>
  94. #include <string.h>
  95. #include <sys/socket.h>
  96. #include <net/if.h>
  97. #include <net/route.h>
  98. #endif
  99. #ifdef USE_WIN32_CODE
  100. #include <unknwn.h>
  101. #include <winreg.h>
  102. #define MAX_KEY_LENGTH 255
  103. #define MAX_VALUE_LENGTH 16383
  104. #endif
  105. #ifdef USE_WIN32_CODE_2
  106. #include <windows.h>
  107. #include <iphlpapi.h>
  108. #endif
  109. #include "getgateway.h"
  110. #ifndef WIN32
  111. #define SUCCESS (0)
  112. #define FAILED (-1)
  113. #endif
  114. #ifdef USE_PROC_NET_ROUTE
  115. /*
  116. parse /proc/net/route which is as follow :
  117. Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
  118. wlan0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
  119. eth0 0000FEA9 00000000 0001 0 0 0 0000FFFF 0 0 0
  120. wlan0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0
  121. eth0 00000000 00000000 0001 0 0 1000 00000000 0 0 0
  122. One header line, and then one line by route by route table entry.
  123. */
  124. int getdefaultgateway(in_addr_t * addr)
  125. {
  126. unsigned long d, g;
  127. char buf[256];
  128. int line = 0;
  129. FILE * f;
  130. char * p;
  131. f = fopen("/proc/net/route", "r");
  132. if(!f)
  133. return FAILED;
  134. while(fgets(buf, sizeof(buf), f)) {
  135. if(line > 0) { /* skip the first line */
  136. p = buf;
  137. /* skip the interface name */
  138. while(*p && !isspace(*p))
  139. p++;
  140. while(*p && isspace(*p))
  141. p++;
  142. if(sscanf(p, "%lx%lx", &d, &g)==2) {
  143. if(d == 0 && g != 0) { /* default */
  144. *addr = g;
  145. fclose(f);
  146. return SUCCESS;
  147. }
  148. }
  149. }
  150. line++;
  151. }
  152. /* default route not found ! */
  153. if(f)
  154. fclose(f);
  155. return FAILED;
  156. }
  157. #endif /* #ifdef USE_PROC_NET_ROUTE */
  158. #ifdef USE_SYSCTL_NET_ROUTE
  159. #define ROUNDUP(a) \
  160. ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  161. int getdefaultgateway(in_addr_t * addr)
  162. {
  163. #if 0
  164. /* net.route.0.inet.dump.0.0 ? */
  165. int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
  166. NET_RT_DUMP, 0, 0/*tableid*/};
  167. #endif
  168. /* net.route.0.inet.flags.gateway */
  169. int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
  170. NET_RT_FLAGS, RTF_GATEWAY};
  171. size_t l;
  172. char * buf, * p;
  173. struct rt_msghdr * rt;
  174. struct sockaddr * sa;
  175. struct sockaddr * sa_tab[RTAX_MAX];
  176. int i;
  177. int r = FAILED;
  178. if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
  179. return FAILED;
  180. }
  181. if(l>0) {
  182. buf = malloc(l);
  183. if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
  184. free(buf);
  185. return FAILED;
  186. }
  187. for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
  188. rt = (struct rt_msghdr *)p;
  189. sa = (struct sockaddr *)(rt + 1);
  190. for(i=0; i<RTAX_MAX; i++) {
  191. if(rt->rtm_addrs & (1 << i)) {
  192. sa_tab[i] = sa;
  193. sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
  194. } else {
  195. sa_tab[i] = NULL;
  196. }
  197. }
  198. if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
  199. && sa_tab[RTAX_DST]->sa_family == AF_INET
  200. && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
  201. if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
  202. *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
  203. r = SUCCESS;
  204. }
  205. }
  206. }
  207. free(buf);
  208. }
  209. return r;
  210. }
  211. #endif /* #ifdef USE_SYSCTL_NET_ROUTE */
  212. #ifdef USE_SOCKET_ROUTE
  213. /* Thanks to Darren Kenny for this code */
  214. #define NEXTADDR(w, u) \
  215. if (rtm_addrs & (w)) {\
  216. l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
  217. }
  218. #define rtm m_rtmsg.m_rtm
  219. struct {
  220. struct rt_msghdr m_rtm;
  221. char m_space[512];
  222. } m_rtmsg;
  223. int getdefaultgateway(in_addr_t *addr)
  224. {
  225. int s, seq, l, rtm_addrs, i;
  226. pid_t pid;
  227. struct sockaddr so_dst, so_mask;
  228. char *cp = m_rtmsg.m_space;
  229. struct sockaddr *gate = NULL, *sa;
  230. struct rt_msghdr *msg_hdr;
  231. pid = getpid();
  232. seq = 0;
  233. rtm_addrs = RTA_DST | RTA_NETMASK;
  234. memset(&so_dst, 0, sizeof(so_dst));
  235. memset(&so_mask, 0, sizeof(so_mask));
  236. memset(&rtm, 0, sizeof(struct rt_msghdr));
  237. rtm.rtm_type = RTM_GET;
  238. rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
  239. rtm.rtm_version = RTM_VERSION;
  240. rtm.rtm_seq = ++seq;
  241. rtm.rtm_addrs = rtm_addrs;
  242. so_dst.sa_family = AF_INET;
  243. so_dst.sa_len = sizeof(struct sockaddr);
  244. so_mask.sa_family = AF_INET;
  245. so_mask.sa_len = sizeof(struct sockaddr);
  246. NEXTADDR(RTA_DST, so_dst);
  247. NEXTADDR(RTA_NETMASK, so_mask);
  248. rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
  249. s = socket(PF_ROUTE, SOCK_RAW, 0);
  250. if (write(s, (char *)&m_rtmsg, l) < 0) {
  251. close(s);
  252. return FAILED;
  253. }
  254. do {
  255. l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
  256. } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
  257. close(s);
  258. msg_hdr = &rtm;
  259. cp = ((char *)(msg_hdr + 1));
  260. if (msg_hdr->rtm_addrs) {
  261. for (i = 1; i; i <<= 1)
  262. if (i & msg_hdr->rtm_addrs) {
  263. sa = (struct sockaddr *)cp;
  264. if (i == RTA_GATEWAY )
  265. gate = sa;
  266. cp += sizeof(struct sockaddr);
  267. }
  268. } else {
  269. return FAILED;
  270. }
  271. if (gate != NULL ) {
  272. *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr;
  273. return SUCCESS;
  274. } else {
  275. return FAILED;
  276. }
  277. }
  278. #endif /* #ifdef USE_SOCKET_ROUTE */
  279. #ifdef USE_WIN32_CODE
  280. LIBSPEC int getdefaultgateway(in_addr_t * addr)
  281. {
  282. HKEY networkCardsKey;
  283. HKEY networkCardKey;
  284. HKEY interfacesKey;
  285. HKEY interfaceKey;
  286. DWORD i = 0;
  287. DWORD numSubKeys = 0;
  288. TCHAR keyName[MAX_KEY_LENGTH];
  289. DWORD keyNameLength = MAX_KEY_LENGTH;
  290. TCHAR keyValue[MAX_VALUE_LENGTH];
  291. DWORD keyValueLength = MAX_VALUE_LENGTH;
  292. DWORD keyValueType = REG_SZ;
  293. TCHAR gatewayValue[MAX_VALUE_LENGTH];
  294. DWORD gatewayValueLength = MAX_VALUE_LENGTH;
  295. DWORD gatewayValueType = REG_MULTI_SZ;
  296. int done = 0;
  297. //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  298. //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  299. #ifdef UNICODE
  300. LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  301. LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  302. #define STR_SERVICENAME L"ServiceName"
  303. #define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway"
  304. #define STR_DEFAULTGATEWAY L"DefaultGateway"
  305. #else
  306. LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  307. LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  308. #define STR_SERVICENAME "ServiceName"
  309. #define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway"
  310. #define STR_DEFAULTGATEWAY "DefaultGateway"
  311. #endif
  312. // The windows registry lists its primary network devices in the following location:
  313. // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
  314. //
  315. // Each network device has its own subfolder, named with an index, with various properties:
  316. // -NetworkCards
  317. // -5
  318. // -Description = Broadcom 802.11n Network Adapter
  319. // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
  320. // -8
  321. // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
  322. // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
  323. //
  324. // The above service name is the name of a subfolder within:
  325. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
  326. //
  327. // There may be more subfolders in this interfaces path than listed in the network cards path above:
  328. // -Interfaces
  329. // -{3a539854-6a70-11db-887c-806e6f6e6963}
  330. // -DhcpIPAddress = 0.0.0.0
  331. // -[more]
  332. // -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
  333. // -DhcpIPAddress = 10.0.1.4
  334. // -DhcpDefaultGateway = 10.0.1.1
  335. // -[more]
  336. // -{86226414-5545-4335-A9D1-5BD7120119AD}
  337. // -DhcpIpAddress = 10.0.1.5
  338. // -DhcpDefaultGateay = 10.0.1.1
  339. // -[more]
  340. //
  341. // In order to extract this information, we enumerate each network card, and extract the ServiceName value.
  342. // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
  343. // Once one is found, we're done.
  344. //
  345. // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
  346. // However, the technique used is the technique most cited on the web, and we assume it to be more correct.
  347. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key
  348. networkCardsPath, // Name of registry subkey to open
  349. 0, // Reserved - must be zero
  350. KEY_READ, // Mask - desired access rights
  351. &networkCardsKey)) // Pointer to output key
  352. {
  353. // Unable to open network cards keys
  354. return -1;
  355. }
  356. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key
  357. interfacesPath, // Name of registry subkey to open
  358. 0, // Reserved - must be zero
  359. KEY_READ, // Mask - desired access rights
  360. &interfacesKey)) // Pointer to output key
  361. {
  362. // Unable to open interfaces key
  363. RegCloseKey(networkCardsKey);
  364. return -1;
  365. }
  366. // Figure out how many subfolders are within the NetworkCards folder
  367. RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  368. //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
  369. // Enumrate through each subfolder within the NetworkCards folder
  370. for(i = 0; i < numSubKeys && !done; i++)
  371. {
  372. keyNameLength = MAX_KEY_LENGTH;
  373. if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key
  374. i, // Index of subkey to retrieve
  375. keyName, // Buffer that receives the name of the subkey
  376. &keyNameLength, // Variable that receives the size of the above buffer
  377. NULL, // Reserved - must be NULL
  378. NULL, // Buffer that receives the class string
  379. NULL, // Variable that receives the size of the above buffer
  380. NULL)) // Variable that receives the last write time of subkey
  381. {
  382. if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS)
  383. {
  384. keyValueLength = MAX_VALUE_LENGTH;
  385. if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key
  386. STR_SERVICENAME, // Name of key to query
  387. NULL, // Reserved - must be NULL
  388. &keyValueType, // Receives value type
  389. (LPBYTE)keyValue, // Receives value
  390. &keyValueLength)) // Receives value length in bytes
  391. {
  392. // printf("keyValue: %s\n", keyValue);
  393. if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS)
  394. {
  395. gatewayValueLength = MAX_VALUE_LENGTH;
  396. if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
  397. STR_DHCPDEFAULTGATEWAY, // Name of key to query
  398. NULL, // Reserved - must be NULL
  399. &gatewayValueType, // Receives value type
  400. (LPBYTE)gatewayValue, // Receives value
  401. &gatewayValueLength)) // Receives value length in bytes
  402. {
  403. // Check to make sure it's a string
  404. if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
  405. {
  406. //printf("gatewayValue: %s\n", gatewayValue);
  407. done = 1;
  408. }
  409. }
  410. else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
  411. STR_DEFAULTGATEWAY, // Name of key to query
  412. NULL, // Reserved - must be NULL
  413. &gatewayValueType, // Receives value type
  414. (LPBYTE)gatewayValue,// Receives value
  415. &gatewayValueLength)) // Receives value length in bytes
  416. {
  417. // Check to make sure it's a string
  418. if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
  419. {
  420. //printf("gatewayValue: %s\n", gatewayValue);
  421. done = 1;
  422. }
  423. }
  424. RegCloseKey(interfaceKey);
  425. }
  426. }
  427. RegCloseKey(networkCardKey);
  428. }
  429. }
  430. }
  431. RegCloseKey(interfacesKey);
  432. RegCloseKey(networkCardsKey);
  433. if(done)
  434. {
  435. #if UNICODE
  436. char tmp[32];
  437. for(i = 0; i < 32; i++) {
  438. tmp[i] = (char)gatewayValue[i];
  439. if(!tmp[i])
  440. break;
  441. }
  442. tmp[31] = '\0';
  443. *addr = inet_addr(tmp);
  444. #else
  445. *addr = inet_addr(gatewayValue);
  446. #endif
  447. return 0;
  448. }
  449. return -1;
  450. }
  451. #endif /* #ifdef USE_WIN32_CODE */
  452. #ifdef USE_WIN32_CODE_2
  453. int getdefaultgateway(in_addr_t *addr)
  454. {
  455. MIB_IPFORWARDROW ip_forward;
  456. memset(&ip_forward, 0, sizeof(ip_forward));
  457. if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR)
  458. return -1;
  459. *addr = ip_forward.dwForwardNextHop;
  460. return 0;
  461. }
  462. #endif /* #ifdef USE_WIN32_CODE_2 */
  463. #ifdef USE_HAIKU_CODE
  464. int getdefaultgateway(in_addr_t *addr)
  465. {
  466. int fd, ret = -1;
  467. struct ifconf config;
  468. void *buffer = NULL;
  469. struct ifreq *interface;
  470. if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  471. return -1;
  472. }
  473. if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) {
  474. goto fail;
  475. }
  476. if (config.ifc_value < 1) {
  477. goto fail; /* No routes */
  478. }
  479. if ((buffer = malloc(config.ifc_value)) == NULL) {
  480. goto fail;
  481. }
  482. config.ifc_len = config.ifc_value;
  483. config.ifc_buf = buffer;
  484. if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) {
  485. goto fail;
  486. }
  487. for (interface = buffer;
  488. (uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) {
  489. struct route_entry route = interface->ifr_route;
  490. int intfSize;
  491. if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) {
  492. *addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr;
  493. ret = 0;
  494. break;
  495. }
  496. intfSize = sizeof(route) + IF_NAMESIZE;
  497. if (route.destination != NULL) {
  498. intfSize += route.destination->sa_len;
  499. }
  500. if (route.mask != NULL) {
  501. intfSize += route.mask->sa_len;
  502. }
  503. if (route.gateway != NULL) {
  504. intfSize += route.gateway->sa_len;
  505. }
  506. interface = (struct ifreq *)((uint8_t *)interface + intfSize);
  507. }
  508. fail:
  509. free(buffer);
  510. close(fd);
  511. return ret;
  512. }
  513. #endif /* #ifdef USE_HAIKU_CODE */
  514. #if !defined(USE_PROC_NET_ROUTE) && !defined(USE_SOCKET_ROUTE) && !defined(USE_SYSCTL_NET_ROUTE) && !defined(USE_WIN32_CODE) && !defined(USE_WIN32_CODE_2) && !defined(USE_HAIKU_CODE)
  515. int getdefaultgateway(in_addr_t * addr)
  516. {
  517. return -1;
  518. }
  519. #endif