getgateway.c 18 KB

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