getgateway.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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_mask.sa_family = AF_INET;
  244. NEXTADDR(RTA_DST, so_dst);
  245. NEXTADDR(RTA_NETMASK, so_mask);
  246. rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
  247. s = socket(PF_ROUTE, SOCK_RAW, 0);
  248. if (write(s, (char *)&m_rtmsg, l) < 0) {
  249. close(s);
  250. return FAILED;
  251. }
  252. do {
  253. l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
  254. } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
  255. close(s);
  256. msg_hdr = &rtm;
  257. cp = ((char *)(msg_hdr + 1));
  258. if (msg_hdr->rtm_addrs) {
  259. for (i = 1; i; i <<= 1)
  260. if (i & msg_hdr->rtm_addrs) {
  261. sa = (struct sockaddr *)cp;
  262. if (i == RTA_GATEWAY )
  263. gate = sa;
  264. cp += sizeof(struct sockaddr);
  265. }
  266. } else {
  267. return FAILED;
  268. }
  269. if (gate != NULL ) {
  270. *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr;
  271. return SUCCESS;
  272. } else {
  273. return FAILED;
  274. }
  275. }
  276. #endif /* #ifdef USE_SOCKET_ROUTE */
  277. #ifdef USE_WIN32_CODE
  278. LIBSPEC int getdefaultgateway(in_addr_t * addr)
  279. {
  280. HKEY networkCardsKey;
  281. HKEY networkCardKey;
  282. HKEY interfacesKey;
  283. HKEY interfaceKey;
  284. DWORD i = 0;
  285. DWORD numSubKeys = 0;
  286. TCHAR keyName[MAX_KEY_LENGTH];
  287. DWORD keyNameLength = MAX_KEY_LENGTH;
  288. TCHAR keyValue[MAX_VALUE_LENGTH];
  289. DWORD keyValueLength = MAX_VALUE_LENGTH;
  290. DWORD keyValueType = REG_SZ;
  291. TCHAR gatewayValue[MAX_VALUE_LENGTH];
  292. DWORD gatewayValueLength = MAX_VALUE_LENGTH;
  293. DWORD gatewayValueType = REG_MULTI_SZ;
  294. int done = 0;
  295. //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  296. //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  297. #ifdef UNICODE
  298. LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  299. LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  300. #define STR_SERVICENAME L"ServiceName"
  301. #define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway"
  302. #define STR_DEFAULTGATEWAY L"DefaultGateway"
  303. #else
  304. LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
  305. LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
  306. #define STR_SERVICENAME "ServiceName"
  307. #define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway"
  308. #define STR_DEFAULTGATEWAY "DefaultGateway"
  309. #endif
  310. // The windows registry lists its primary network devices in the following location:
  311. // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
  312. //
  313. // Each network device has its own subfolder, named with an index, with various properties:
  314. // -NetworkCards
  315. // -5
  316. // -Description = Broadcom 802.11n Network Adapter
  317. // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
  318. // -8
  319. // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
  320. // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
  321. //
  322. // The above service name is the name of a subfolder within:
  323. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
  324. //
  325. // There may be more subfolders in this interfaces path than listed in the network cards path above:
  326. // -Interfaces
  327. // -{3a539854-6a70-11db-887c-806e6f6e6963}
  328. // -DhcpIPAddress = 0.0.0.0
  329. // -[more]
  330. // -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
  331. // -DhcpIPAddress = 10.0.1.4
  332. // -DhcpDefaultGateway = 10.0.1.1
  333. // -[more]
  334. // -{86226414-5545-4335-A9D1-5BD7120119AD}
  335. // -DhcpIpAddress = 10.0.1.5
  336. // -DhcpDefaultGateay = 10.0.1.1
  337. // -[more]
  338. //
  339. // In order to extract this information, we enumerate each network card, and extract the ServiceName value.
  340. // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
  341. // Once one is found, we're done.
  342. //
  343. // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
  344. // However, the technique used is the technique most cited on the web, and we assume it to be more correct.
  345. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key
  346. networkCardsPath, // Name of registry subkey to open
  347. 0, // Reserved - must be zero
  348. KEY_READ, // Mask - desired access rights
  349. &networkCardsKey)) // Pointer to output key
  350. {
  351. // Unable to open network cards keys
  352. return -1;
  353. }
  354. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key
  355. interfacesPath, // Name of registry subkey to open
  356. 0, // Reserved - must be zero
  357. KEY_READ, // Mask - desired access rights
  358. &interfacesKey)) // Pointer to output key
  359. {
  360. // Unable to open interfaces key
  361. RegCloseKey(networkCardsKey);
  362. return -1;
  363. }
  364. // Figure out how many subfolders are within the NetworkCards folder
  365. RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  366. //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
  367. // Enumrate through each subfolder within the NetworkCards folder
  368. for(i = 0; i < numSubKeys && !done; i++)
  369. {
  370. keyNameLength = MAX_KEY_LENGTH;
  371. if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key
  372. i, // Index of subkey to retrieve
  373. keyName, // Buffer that receives the name of the subkey
  374. &keyNameLength, // Variable that receives the size of the above buffer
  375. NULL, // Reserved - must be NULL
  376. NULL, // Buffer that receives the class string
  377. NULL, // Variable that receives the size of the above buffer
  378. NULL)) // Variable that receives the last write time of subkey
  379. {
  380. if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS)
  381. {
  382. keyValueLength = MAX_VALUE_LENGTH;
  383. if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key
  384. STR_SERVICENAME, // Name of key to query
  385. NULL, // Reserved - must be NULL
  386. &keyValueType, // Receives value type
  387. (LPBYTE)keyValue, // Receives value
  388. &keyValueLength)) // Receives value length in bytes
  389. {
  390. // printf("keyValue: %s\n", keyValue);
  391. if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS)
  392. {
  393. gatewayValueLength = MAX_VALUE_LENGTH;
  394. if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
  395. STR_DHCPDEFAULTGATEWAY, // Name of key to query
  396. NULL, // Reserved - must be NULL
  397. &gatewayValueType, // Receives value type
  398. (LPBYTE)gatewayValue, // Receives value
  399. &gatewayValueLength)) // Receives value length in bytes
  400. {
  401. // Check to make sure it's a string
  402. if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
  403. {
  404. //printf("gatewayValue: %s\n", gatewayValue);
  405. done = 1;
  406. }
  407. }
  408. else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
  409. STR_DEFAULTGATEWAY, // Name of key to query
  410. NULL, // Reserved - must be NULL
  411. &gatewayValueType, // Receives value type
  412. (LPBYTE)gatewayValue,// Receives value
  413. &gatewayValueLength)) // Receives value length in bytes
  414. {
  415. // Check to make sure it's a string
  416. if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1))
  417. {
  418. //printf("gatewayValue: %s\n", gatewayValue);
  419. done = 1;
  420. }
  421. }
  422. RegCloseKey(interfaceKey);
  423. }
  424. }
  425. RegCloseKey(networkCardKey);
  426. }
  427. }
  428. }
  429. RegCloseKey(interfacesKey);
  430. RegCloseKey(networkCardsKey);
  431. if(done)
  432. {
  433. #if UNICODE
  434. char tmp[32];
  435. for(i = 0; i < 32; i++) {
  436. tmp[i] = (char)gatewayValue[i];
  437. if(!tmp[i])
  438. break;
  439. }
  440. tmp[31] = '\0';
  441. *addr = inet_addr(tmp);
  442. #else
  443. *addr = inet_addr(gatewayValue);
  444. #endif
  445. return 0;
  446. }
  447. return -1;
  448. }
  449. #endif /* #ifdef USE_WIN32_CODE */
  450. #ifdef USE_WIN32_CODE_2
  451. int getdefaultgateway(in_addr_t *addr)
  452. {
  453. MIB_IPFORWARDROW ip_forward;
  454. memset(&ip_forward, 0, sizeof(ip_forward));
  455. if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR)
  456. return -1;
  457. *addr = ip_forward.dwForwardNextHop;
  458. return 0;
  459. }
  460. #endif /* #ifdef USE_WIN32_CODE_2 */
  461. #ifdef USE_HAIKU_CODE
  462. int getdefaultgateway(in_addr_t *addr)
  463. {
  464. int fd, ret = -1;
  465. struct ifconf config;
  466. void *buffer = NULL;
  467. struct ifreq *interface;
  468. if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  469. return -1;
  470. }
  471. if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) {
  472. goto fail;
  473. }
  474. if (config.ifc_value < 1) {
  475. goto fail; /* No routes */
  476. }
  477. if ((buffer = malloc(config.ifc_value)) == NULL) {
  478. goto fail;
  479. }
  480. config.ifc_len = config.ifc_value;
  481. config.ifc_buf = buffer;
  482. if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) {
  483. goto fail;
  484. }
  485. for (interface = buffer;
  486. (uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) {
  487. struct route_entry route = interface->ifr_route;
  488. int intfSize;
  489. if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) {
  490. *addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr;
  491. ret = 0;
  492. break;
  493. }
  494. intfSize = sizeof(route) + IF_NAMESIZE;
  495. if (route.destination != NULL) {
  496. intfSize += route.destination->sa_len;
  497. }
  498. if (route.mask != NULL) {
  499. intfSize += route.mask->sa_len;
  500. }
  501. if (route.gateway != NULL) {
  502. intfSize += route.gateway->sa_len;
  503. }
  504. interface = (struct ifreq *)((uint8_t *)interface + intfSize);
  505. }
  506. fail:
  507. free(buffer);
  508. close(fd);
  509. return ret;
  510. }
  511. #endif /* #ifdef USE_HAIKU_CODE */
  512. #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)
  513. int getdefaultgateway(in_addr_t * addr)
  514. {
  515. return -1;
  516. }
  517. #endif