1 /*
2     get default route (gateway) IPv4 address of the named network
3     interface/adapter (like "eth0").
4 
5     This works on both Linux and windows.
6 */
7 #include "rawsock.h"
8 #include "string_s.h"
9 #include "util-malloc.h"
10 #include "massip-parse.h"
11 #include "logger.h"
12 
13 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun__)
14 #include <unistd.h>
15 #include <sys/socket.h>
16 #include <net/route.h>
17 #include <netinet/in.h>
18 #include <net/if_dl.h>
19 #include <ctype.h>
20 
21 #define ROUNDUP2(a, n)       ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
22 
23 #if defined(__APPLE__)
24 # define ROUNDUP(a)           ROUNDUP2((a), sizeof(int))
25 #elif defined(__NetBSD__)
26 # define ROUNDUP(a)           ROUNDUP2((a), sizeof(uint64_t))
27 #elif defined(__FreeBSD__)
28 # define ROUNDUP(a)           ROUNDUP2((a), sizeof(int))
29 #elif defined(__OpenBSD__)
30 # define ROUNDUP(a)           ROUNDUP2((a), sizeof(int))
31 #else
32 # error unknown platform
33 #endif
34 
35 static struct sockaddr *
get_rt_address(struct rt_msghdr * rtm,int desired)36 get_rt_address(struct rt_msghdr *rtm, int desired)
37 {
38     int i;
39     int bitmask = rtm->rtm_addrs;
40     struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
41 
42     for (i = 0; i < RTAX_MAX; i++) {
43         if (bitmask & (1 << i)) {
44             if ((1<<i) == desired)
45                 return sa;
46             sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
47         } else
48             ;
49     }
50     return NULL;
51 
52 }
53 
54 static void
hexdump(const void * v,size_t len)55 hexdump(const void *v, size_t len)
56 {
57     const unsigned char *p = (const unsigned char *)v;
58     size_t i;
59 
60 
61     for (i=0; i<len; i += 16) {
62         size_t j;
63 
64         for (j=i; j<i+16 && j<len; j++)
65             printf("%02x ", p[j]);
66         for (;j<i+16; j++)
67             printf("   ");
68         printf("  ");
69         for (j=i; j<i+16 && j<len; j++)
70             if (isprint(p[j]) && !isspace(p[j]))
71                 printf("%c", p[j]);
72             else
73                 printf(".");
74         printf("\n");
75     }
76 }
77 
78 #if 0
79 #define RTA_DST         0x1     /* destination sockaddr present */
80 #define RTA_GATEWAY     0x2     /* gateway sockaddr present */
81 #define RTA_NETMASK     0x4     /* netmask sockaddr present */
82 #define RTA_GENMASK     0x8     /* cloning mask sockaddr present */
83 #define RTA_IFP         0x10    /* interface name sockaddr present */
84 #define RTA_IFA         0x20    /* interface addr sockaddr present */
85 #define RTA_AUTHOR      0x40    /* sockaddr for author of redirect */
86 #define RTA_BRD         0x80    /* for NEWADDR, broadcast or p-p dest addr */
87 #endif
88 
89 void
90 dump_rt_addresses(struct rt_msghdr *rtm);
91 
92 void
dump_rt_addresses(struct rt_msghdr * rtm)93 dump_rt_addresses(struct rt_msghdr *rtm)
94 {
95     int i;
96     int bitmask = rtm->rtm_addrs;
97     struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
98 
99     for (i = 0; i < RTAX_MAX; i++) {
100         if (bitmask & (1 << i)) {
101             printf("b=%u fam=%u len=%u\n", (1<<i), sa->sa_family, sa->sa_len);
102             hexdump(sa, sa->sa_len + sizeof(sa->sa_family));
103             sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
104         } else
105             ;
106     }
107 }
108 
109 int
rawsock_get_default_gateway(const char * ifname,unsigned * ipv4)110 rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
111 {
112     int fd;
113     int seq = (int)time(0);
114     ssize_t err;
115     struct rt_msghdr *rtm;
116     size_t sizeof_buffer;
117 
118 
119     /*
120      * Requests/responses from the kernel are done with an "rt_msghdr"
121      * structure followed by an array of "sockaddr" structures.
122      */
123     sizeof_buffer = sizeof(*rtm) + 512;
124     rtm = calloc(1, sizeof_buffer);
125 
126     /*
127      * Create a socket for querying the kernel
128      */
129     fd = socket(AF_ROUTE, SOCK_RAW, 0);
130     if (fd < 0) {
131         perror("socket(AF_ROUTE)");
132         free(rtm);
133         return errno;
134     }
135 
136     /* Needs a timeout. Sometimes it'll hang indefinitely waiting for a
137      * response that will never arrive */
138     {
139         struct timeval timeout;
140         timeout.tv_sec = 1;
141         timeout.tv_usec = 0;
142 
143         err = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
144         if (err < 0)
145             LOG(0, "[-] SO_RCVTIMEO: %d %s\n", errno, strerror(errno));
146 
147         err = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
148         if (err < 0)
149             LOG(0, "[-] SO_SNDTIMEO: %d %s\n", errno, strerror(errno));
150    }
151 
152     /*
153      * Format and send request to kernel
154      */
155     rtm->rtm_msglen = sizeof(*rtm) + sizeof(struct sockaddr_in);
156     rtm->rtm_version = RTM_VERSION;
157     rtm->rtm_flags = RTF_UP;
158     rtm->rtm_type = RTM_GET;
159     rtm->rtm_addrs = RTA_DST | RTA_IFP;
160     rtm->rtm_pid = getpid();
161     rtm->rtm_seq = seq;
162 
163     /*
164      * Create an empty address of 0.0.0.0 to query the route
165      */
166     {
167         struct sockaddr_in *sin;
168         sin = (struct sockaddr_in *)(rtm + 1);
169         sin->sin_len = sizeof(*sin);
170         sin->sin_family = AF_INET;
171         sin->sin_addr.s_addr = 0;
172     }
173 
174     err = write(fd, (char *)rtm, rtm->rtm_msglen);
175     if (err <= 0) {
176         LOG(0, "[-] getroute: write(): returned %d %s\n", errno, strerror(errno));
177         goto fail;
178     }
179 
180     /*
181      * Read responses until we find one that belongs to us
182      */
183     for (;;) {
184         err = read(fd, (char *)rtm, sizeof_buffer);
185         if (err <= 0)
186             break;
187         if (rtm->rtm_seq != seq) {
188             printf("seq: %u %u\n", rtm->rtm_seq, seq);
189             continue;
190         }
191         if (rtm->rtm_pid != getpid()) {
192             printf("pid: %u %u\n", rtm->rtm_pid, getpid());
193             continue;
194         }
195         break;
196     }
197     close(fd);
198 
199     /*
200      * Parse our data
201      */
202     {
203         struct sockaddr_in *sin;
204         struct sockaddr_dl *sdl;
205 
206         sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP);
207         if (sdl) {
208             //hexdump(sdl, sdl->sdl_len);
209             //printf("%.*s\n", sdl->sdl_nlen, sdl->sdl_data);
210             if (memcmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0) {
211                 fprintf(stderr, "ERROR: ROUTE DOESN'T MATCH INTERFACE\n");
212                 fprintf(stderr, "YOU'LL HAVE TO SET --router-mac MANUALLY\n");
213                 exit(1);
214             }
215         }
216 
217         sin = (struct sockaddr_in *)get_rt_address(rtm, RTA_GATEWAY);
218         if (sin) {
219             *ipv4 = ntohl(sin->sin_addr.s_addr);
220             free(rtm);
221             return 0;
222         }
223 
224     }
225 
226 fail:
227     free(rtm);
228     return -1;
229 }
230 
231 #elif defined(__linux__)
232 #include <netinet/in.h>
233 #include <net/if.h>
234 #include <stdio.h>
235 #include <string.h>
236 #include <stdlib.h>
237 #include <unistd.h>
238 #include <sys/socket.h>
239 #include <sys/ioctl.h>
240 #include <linux/netlink.h>
241 #include <linux/rtnetlink.h>
242 #include <sys/types.h>
243 #include <sys/socket.h>
244 #include <arpa/inet.h>
245 
246 
247 
248 struct route_info {
249     struct in_addr dstAddr;
250     struct in_addr srcAddr;
251     struct in_addr gateWay;
252     char ifName[IF_NAMESIZE];
253 };
254 
255 static int
read_netlink(int fd,char * bufPtr,size_t sizeof_buffer,int seqNum,int pId)256 read_netlink(int fd, char *bufPtr, size_t sizeof_buffer, int seqNum, int pId)
257 {
258     struct nlmsghdr *nlHdr;
259     int readLen = 0, msgLen = 0;
260 
261  do {
262         /* Recieve response from the kernel */
263         if ((readLen = recv(fd, bufPtr, sizeof_buffer - msgLen, 0)) < 0) {
264             perror("SOCK READ: ");
265             return -1;
266         }
267 
268         nlHdr = (struct nlmsghdr *) bufPtr;
269 
270         /* Check if the header is valid */
271         if ((NLMSG_OK(nlHdr, readLen) == 0)
272             || (nlHdr->nlmsg_type == NLMSG_ERROR)) {
273             perror("Error in received packet");
274             return -1;
275         }
276 
277         /* Check if the its the last message */
278         if (nlHdr->nlmsg_type == NLMSG_DONE) {
279             break;
280         } else {
281             /* Else move the pointer to buffer appropriately */
282             bufPtr += readLen;
283             msgLen += readLen;
284         }
285 
286         /* Check if its a multi part message */
287         if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
288             /* return if its not */
289             break;
290         }
291     } while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
292 
293     return msgLen;
294 }
295 
296 /* For parsing the route info returned */
297 static int
parseRoutes(struct nlmsghdr * nlHdr,struct route_info * rtInfo)298 parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
299 {
300     struct rtmsg *rtMsg;
301     struct rtattr *rtAttr;
302     int rtLen = 0;
303 
304     rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr);
305 
306     /* This must be an IPv4 (AF_INET) route */
307     if (rtMsg->rtm_family != AF_INET)
308         return 1;
309 
310     /* This must be in main routing table */
311     if (rtMsg->rtm_table != RT_TABLE_MAIN)
312         return 1;
313 
314     /* Attributes field*/
315     rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
316     rtLen = RTM_PAYLOAD(nlHdr);
317     for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
318         switch (rtAttr->rta_type) {
319         case RTA_OIF:
320             if_indextoname(*(int *) RTA_DATA(rtAttr), rtInfo->ifName);
321             break;
322         case RTA_GATEWAY:
323             rtInfo->gateWay.s_addr = *(u_int *)RTA_DATA(rtAttr);
324             break;
325         case RTA_PREFSRC:
326             rtInfo->srcAddr.s_addr = *(u_int *)RTA_DATA(rtAttr);
327             break;
328         case RTA_DST:
329             rtInfo->dstAddr .s_addr = *(u_int *)RTA_DATA(rtAttr);
330             break;
331         }
332     }
333 
334     return 0;
335 }
336 
337 
rawsock_get_default_gateway(const char * ifname,unsigned * ipv4)338 int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
339 {
340     int fd;
341     struct nlmsghdr *nlMsg;
342     char msgBuf[16384];
343     int len;
344     int msgSeq = 0;
345 
346     /*
347      * Set to zero, in case we cannot find it
348      */
349     *ipv4 = 0;
350 
351     /*
352      * Create 'netlink' socket to query kernel
353      */
354     fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
355     if (fd < 0) {
356         fprintf(stderr, "%s:%d: socket(NETLINK_ROUTE): %d\n",
357             __FILE__, __LINE__, errno);
358         return errno;
359     }
360 
361     /*
362      * format the netlink buffer
363      */
364     memset(msgBuf, 0, sizeof(msgBuf));
365     nlMsg = (struct nlmsghdr *)msgBuf;
366 
367     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
368     nlMsg->nlmsg_type = RTM_GETROUTE;
369     nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
370     nlMsg->nlmsg_seq = msgSeq++;
371     nlMsg->nlmsg_pid = getpid();
372 
373     /*
374      * send first request to kernel
375      */
376     if (send(fd, nlMsg, nlMsg->nlmsg_len, 0) < 0) {
377         fprintf(stderr, "%s:%d: send(NETLINK_ROUTE): %d\n",
378             __FILE__, __LINE__, errno);
379         return errno;
380     }
381 
382     /*
383      * Now read all the responses
384      */
385     len = read_netlink(fd, msgBuf, sizeof(msgBuf), msgSeq, getpid());
386     if (len <= 0) {
387         fprintf(stderr, "%s:%d: read_netlink: %d\n",
388             __FILE__, __LINE__, errno);
389         return errno;
390     }
391 
392 
393     /*
394      * Parse the response
395      */
396     for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) {
397         struct route_info rtInfo[1];
398         int err;
399 
400         memset(rtInfo, 0, sizeof(struct route_info));
401 
402         err = parseRoutes(nlMsg, rtInfo);
403         if (err != 0)
404             continue;
405 
406         /* make sure we match the desired network interface */
407         if (ifname && strcmp(rtInfo->ifName, ifname) != 0)
408             continue;
409 
410         /* make sure destination = 0.0.0.0 for "default route" */
411         if (rtInfo->dstAddr.s_addr != 0)
412             continue;
413 
414         /* found the gateway! */
415         *ipv4 = ntohl(rtInfo->gateWay.s_addr);
416     }
417 
418     close(fd);
419 
420     return 0;
421 }
422 
423 #endif
424 
425 
426 #if defined(WIN32)
427 #include <winsock2.h>
428 #include <iphlpapi.h>
429 #ifdef _MSC_VER
430 #pragma comment(lib, "IPHLPAPI.lib")
431 #endif
432 
433 
434 
rawsock_get_default_gateway(const char * ifname,unsigned * ipv4)435 int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
436 {
437     PIP_ADAPTER_INFO pAdapterInfo;
438     PIP_ADAPTER_INFO pAdapter = NULL;
439     DWORD err;
440     ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
441 
442     /*
443      * Translate numeric index (if it exists) to real name
444      */
445     ifname = rawsock_win_name(ifname);
446     //printf("------ %s -----\n", ifname);
447 
448     /*
449      * Allocate a proper sized buffer
450      */
451     pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof (IP_ADAPTER_INFO));
452     if (pAdapterInfo == NULL) {
453         fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
454         return EFAULT;
455     }
456 
457     /*
458      * Query the adapter info. If the buffer is not big enough, loop around
459      * and try again
460      */
461 again:
462     err = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
463     if (err == ERROR_BUFFER_OVERFLOW) {
464         free(pAdapterInfo);
465         pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
466         if (pAdapterInfo == NULL) {
467             fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
468             return EFAULT;
469         }
470         goto again;
471     }
472     if (err != NO_ERROR) {
473         fprintf(stderr, "GetAdaptersInfo failed with error: %u\n",
474                             (unsigned)err);
475         return EFAULT;
476     }
477 
478     /*
479      * loop through all adapters looking for ours
480      */
481     for (   pAdapter = pAdapterInfo;
482             pAdapter;
483             pAdapter = pAdapter->Next) {
484         if (rawsock_is_adapter_names_equal(pAdapter->AdapterName, ifname))
485             break;
486     }
487 
488     if (pAdapter) {
489         //printf("\tComboIndex: \t%d\n", pAdapter->ComboIndex);
490         //printf("\tAdapter Name: \t%s\n", pAdapter->AdapterName);
491         //printf("\tAdapter Desc: \t%s\n", pAdapter->Description);
492 
493 
494         //printf("\tAdapter Addr: \t");
495         /*for (i = 0; i < pAdapter->AddressLength; i++) {
496             if (i == (pAdapter->AddressLength - 1))
497                 printf("%.2X\n", (int) pAdapter->Address[i]);
498             else
499                 printf("%.2X-", (int) pAdapter->Address[i]);
500         }*/
501         //printf("\tIndex: \t%d\n", pAdapter->Index);
502         //printf("\tType: \t");
503         switch (pAdapter->Type) {
504         case MIB_IF_TYPE_OTHER:
505             //printf("Other\n");
506             break;
507         case MIB_IF_TYPE_ETHERNET:
508             //printf("Ethernet\n");
509             break;
510         case MIB_IF_TYPE_TOKENRING:
511             //printf("Token Ring\n");
512             break;
513         case MIB_IF_TYPE_FDDI:
514             //printf("FDDI\n");
515             break;
516         case MIB_IF_TYPE_PPP:
517             //printf("PPP\n");
518             break;
519         case MIB_IF_TYPE_LOOPBACK:
520             //printf("Lookback\n");
521             break;
522         case MIB_IF_TYPE_SLIP:
523             //printf("Slip\n");
524             break;
525         default:
526             //printf("Unknown type %ld\n", pAdapter->Type);
527             break;
528         }
529 
530         //printf("\tIP Address: \t%s\n", pAdapter->IpAddressList.IpAddress.String);
531         //printf("\tIP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
532 
533 /*typedef struct _IP_ADDR_STRING {
534     struct _IP_ADDR_STRING* Next;
535     IP_ADDRESS_STRING IpAddress;
536     IP_MASK_STRING IpMask;
537     DWORD Context;
538 } IP_ADDR_STRING, *PIP_ADDR_STRING;*/
539 
540         {
541             const IP_ADDR_STRING *addr;
542 
543             for (addr = &pAdapter->GatewayList; addr; addr = addr->Next) {
544                 unsigned x = massip_parse_ipv4(addr->IpAddress.String);
545                 if (x != 0xFFFFFFFF) {
546                     *ipv4 = x;
547                     goto end;
548                 }
549             }
550         }
551 
552 
553         //printf("\n");
554     }
555 end:
556     if (pAdapterInfo)
557         free(pAdapterInfo);
558     return 0;
559 }
560 
561 #endif
562