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