OpenVAS Scanner 22.7.9
pcap.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Greenbone AG
2 * SPDX-FileCopyrightText: 1999 Renaud Deraison
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "bpf_share.h"
8#include "network.h"
9#include "pcap_openvas.h"
10#include "support.h"
11
12#include <arpa/inet.h>
13#include <errno.h>
14#include <gvm/base/logging.h>
15#include <gvm/base/networking.h>
16#include <ifaddrs.h>
17#include <net/if.h>
18#include <netdb.h>
19#include <netinet/in.h>
20#include <pcap.h>
21#include <resolv.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/ioctl.h>
25#include <sys/param.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29#define MAXROUTES 1024
30
31#undef G_LOG_DOMAIN
35#define G_LOG_DOMAIN "lib misc"
36
40#define MAX_IFACE_NAME_LEN 64
41
43{
45 struct in_addr addr;
46 struct in6_addr addr6;
47 struct in6_addr mask;
48};
49
54struct myroute
55{
57 struct in6_addr dest6;
58 unsigned long mask;
59 unsigned long dest;
60 unsigned long metric;
61};
62
63struct interface_info *
64getinterfaces (int *howmany);
65struct interface_info *
66v6_getinterfaces (int *howmany);
67int
68getipv6routes (struct myroute *myroutes, int *numroutes);
69
81static int
82ipv6_prefix_to_mask (unsigned prefix, struct in6_addr *mask)
83{
84 struct in6_addr in6;
85 int i, j;
86
87 if (prefix > 128)
88 return -1;
89
90 memset (&in6, 0x0, sizeof (in6));
91 for (i = prefix, j = 0; i > 0; i -= 8, j++)
92 {
93 if (i >= 8)
94 {
95 in6.s6_addr[j] = 0xff;
96 }
97 else
98 {
99 in6.s6_addr[j] = (unsigned long) (0xffU << (8 - i));
100 }
101 }
102
103 memcpy (mask, &in6, sizeof (*mask));
104 return 0;
105}
106
107int
108v6_is_local_ip (struct in6_addr *addr)
109{
110 int i, j, ifaces, numroutes = 0;
111 struct interface_info *ifs;
112 static struct myroute myroutes[MAXROUTES];
113 struct in6_addr network, mask;
114 bpf_u_int32 v4mappednet, v4mappedmask;
115
116 if ((ifs = v6_getinterfaces (&ifaces)) == NULL)
117 return -1;
118
119 if (IN6_IS_ADDR_V4MAPPED (addr))
120 {
121 for (i = 0; i < ifaces; i++)
122 {
123 char errbuf[PCAP_ERRBUF_SIZE];
124 pcap_lookupnet (ifs[i].name, &v4mappednet, &v4mappedmask, errbuf);
125 if ((v4mappednet & v4mappedmask)
126 == (addr->s6_addr32[3] & v4mappedmask))
127 return 1;
128 }
129 }
130 else
131 {
132 if (IN6_IS_ADDR_LINKLOCAL (addr))
133 return 1;
134 if (IN6_IS_ADDR_LOOPBACK (addr))
135 return 1;
136 if (getipv6routes (myroutes, &numroutes) == 0)
137 {
138 for (i = 0; i < numroutes; i++)
139 {
140 char addr1[INET6_ADDRSTRLEN];
141 char addr2[INET6_ADDRSTRLEN];
142
143 if (ipv6_prefix_to_mask (myroutes[i].mask, &mask) == -1)
144 return -1;
145 for (j = 0; j < (int) sizeof (struct in6_addr); j++)
146 network.s6_addr[j] = addr->s6_addr[j] & mask.s6_addr[j];
147
148 g_debug ("comparing addresses %s and %s",
149 inet_ntop (AF_INET6, &network, addr1, sizeof (addr1)),
150 inet_ntop (AF_INET6, &myroutes[i].dest6, addr2,
151 sizeof (addr2)));
152 if (IN6_ARE_ADDR_EQUAL (&network, &myroutes[i].dest6))
153 {
154 return 1;
155 }
156 }
157 }
158 }
159 return 0;
160}
161
162/*
163 * Taken straight out of Fyodor's Nmap
164 */
165static int
166v6_ipaddr2devname (char *dev, int sz, struct in6_addr *addr)
167{
168 struct interface_info *mydevs;
169 int numdevs = 0;
170 int i;
171 mydevs = v6_getinterfaces (&numdevs);
172
173 if (!mydevs)
174 return -1;
175
176 for (i = 0; i < numdevs; i++)
177 {
178 char addr1[INET6_ADDRSTRLEN];
179 char addr2[INET6_ADDRSTRLEN];
180 g_debug ("comparing addresses %s and %s",
181 inet_ntop (AF_INET6, addr, addr1, sizeof (addr1)),
182 inet_ntop (AF_INET6, &mydevs[i].addr6, addr2, sizeof (addr2)));
183 if (IN6_ARE_ADDR_EQUAL (addr, &mydevs[i].addr6))
184 {
185 dev[sz - 1] = '\0';
186 strncpy (dev, mydevs[i].name, sz);
187 return 0;
188 }
189 }
190 return -1;
191}
192
193/*
194 * Taken straight out of Fyodor's Nmap
195 */
196static int
197ipaddr2devname (char *dev, int sz, struct in_addr *addr)
198{
199 struct interface_info *mydevs;
200 int numdevs;
201 int i;
202 mydevs = getinterfaces (&numdevs);
203
204 if (!mydevs)
205 return -1;
206
207 for (i = 0; i < numdevs; i++)
208 {
209 if (addr->s_addr == mydevs[i].addr.s_addr)
210 {
211 dev[sz - 1] = '\0';
212 strncpy (dev, mydevs[i].name, sz);
213 return 0;
214 }
215 }
216 return -1;
217}
218
223int
224v6_islocalhost (struct in6_addr *addr)
225{
226 char dev[128];
227
228 if (addr == NULL)
229 return -1;
230
231 if (IN6_IS_ADDR_V4MAPPED (addr))
232 {
233 /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
234 probably localhost */
235 if ((addr->s6_addr32[3] & htonl (0xFF000000)) == htonl (0x7F000000))
236 return 1;
237
238 if (!addr->s6_addr32[3])
239 return 1;
240 }
241
242 if (IN6_IS_ADDR_LOOPBACK (addr))
243 return 1;
244
245 /* If it is the same addy as a local interface, then it is
246 probably localhost */
247
248 if (v6_ipaddr2devname (dev, sizeof (dev), addr) != -1)
249 return 1;
250
251 /* OK, so to a first approximation, this addy is probably not
252 localhost */
253 return 0;
254}
255
260int
261islocalhost (struct in_addr *addr)
262{
263 char dev[128];
264
265 if (addr == NULL)
266 return -1;
267
268 /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
269 probably localhost */
270 if ((addr->s_addr & htonl (0xFF000000)) == htonl (0x7F000000))
271 return 1;
272
273 if (!addr->s_addr)
274 return 1;
275
276 /* If it is the same addy as a local interface, then it is
277 probably localhost */
278
279 if (ipaddr2devname (dev, sizeof (dev), addr) != -1)
280 return 1;
281
282 /* OK, so to a first approximation, this addy is probably not
283 localhost */
284 return 0;
285}
286
287int
288get_datalink_size (int datalink)
289{
290 int offset = -1;
291 switch (datalink)
292 {
293 case DLT_EN10MB:
294 offset = 14;
295 break;
296 case DLT_IEEE802:
297 offset = 22;
298 break;
299 case DLT_NULL:
300 offset = 4;
301 break;
302 case DLT_SLIP:
303#if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
304 offset = 16;
305#else
306 offset = 24; /* Anyone use this??? */
307#endif
308 break;
309 case DLT_PPP:
310#if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
311 offset = 4;
312#else
313#ifdef SOLARIS
314 offset = 8;
315#else
316 offset = 24; /* Anyone use this? */
317#endif /* ifdef solaris */
318#endif /* if freebsd || openbsd || netbsd || bsdi */
319 break;
320 case DLT_RAW:
321 offset = 0;
322 break;
323 }
324 return (offset);
325}
326
327struct interface_info *
328v6_getinterfaces (int *howmany)
329{
330 struct sockaddr_in *saddr;
331 struct sockaddr_in6 *s6addr;
332 static struct interface_info mydevs[1024];
333 int numinterfaces = 0;
334 struct ifaddrs *ifaddr, *ifa;
335 int family;
336
337 if (getifaddrs (&ifaddr) == -1)
338 {
339 perror ("getifaddrs");
340 }
341 else
342 {
343 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
344 {
345 if (ifa->ifa_addr == NULL)
346 continue;
347
348 family = ifa->ifa_addr->sa_family;
349 if (family == AF_INET)
350 {
351 strncpy (mydevs[numinterfaces].name, ifa->ifa_name,
352 sizeof (mydevs[numinterfaces].name) - 1);
353 saddr = (struct sockaddr_in *) ifa->ifa_addr;
354 mydevs[numinterfaces].addr6.s6_addr32[0] = 0;
355 mydevs[numinterfaces].addr6.s6_addr32[1] = 0;
356 mydevs[numinterfaces].addr6.s6_addr32[2] = htonl (0xffff);
357 mydevs[numinterfaces].addr6.s6_addr32[3] = saddr->sin_addr.s_addr;
358 saddr = (struct sockaddr_in *) ifa->ifa_netmask;
359 mydevs[numinterfaces].mask.s6_addr32[0] = 0;
360 mydevs[numinterfaces].mask.s6_addr32[1] = 0;
361 mydevs[numinterfaces].mask.s6_addr32[2] = htonl (0xffff);
362 mydevs[numinterfaces].mask.s6_addr32[3] = saddr->sin_addr.s_addr;
363 g_debug ("interface name is %s", ifa->ifa_name);
364 g_debug ("\tAF_INET family");
365 g_debug ("\taddress is %s", inet_ntoa (saddr->sin_addr));
366 g_debug ("\tnetmask is %s", inet_ntoa (saddr->sin_addr));
367 numinterfaces++;
368 }
369 else if (family == AF_INET6)
370 {
371 char ipaddr[INET6_ADDRSTRLEN];
372
373 strncpy (mydevs[numinterfaces].name, ifa->ifa_name,
374 sizeof (mydevs[numinterfaces].name) - 1);
375 s6addr = (struct sockaddr_in6 *) ifa->ifa_addr;
376 memcpy (&(mydevs[numinterfaces].addr6),
377 (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
378 s6addr = (struct sockaddr_in6 *) ifa->ifa_netmask;
379 memcpy (&(mydevs[numinterfaces].mask),
380 (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
381 numinterfaces++;
382 g_debug ("\tAF_INET6 family");
383 g_debug ("interface name is %s", ifa->ifa_name);
384 g_debug ("\taddress is %s",
385 inet_ntop (AF_INET6, &s6addr->sin6_addr, ipaddr,
386 sizeof (ipaddr)));
387 }
388 else
389 g_debug ("\tfamily is %d", ifa->ifa_addr->sa_family);
390 }
391 *howmany = numinterfaces;
392
393 freeifaddrs (ifaddr);
394 }
395 return mydevs;
396}
397
402struct interface_info *
403getinterfaces (int *howmany)
404{
405 static struct interface_info mydevs[1024];
406 int numinterfaces = 0;
407 int sd;
408 int len;
409 char *p;
410 char buf[10240];
411 struct ifconf ifc;
412 struct ifreq *ifr;
413 struct sockaddr_in *sin;
414 char *bufp;
415
416 /* Dummy socket for ioctl. */
417 sd = socket (AF_INET, SOCK_DGRAM, 0);
418 bzero (buf, sizeof (buf));
419 if (sd < 0)
420 {
421 g_message ("socket in getinterfaces");
422 return NULL;
423 }
424
425 ifc.ifc_len = sizeof (buf);
426 ifc.ifc_buf = buf;
427 if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
428 g_message ("Failed to determine your configured interfaces!");
429
430 close (sd);
431 if (ifc.ifc_len == 0)
432 g_message (
433 "getinterfaces: SIOCGIFCONF claims you have no network interfaces!");
434
435#ifndef __FreeBSD__
436 len = sizeof (struct ifmap);
437#else
438 len = sizeof (struct sockaddr);
439#endif
440
441 for (bufp = buf; bufp && *bufp && (bufp < (buf + ifc.ifc_len));
442 bufp += sizeof (ifr->ifr_name) + len)
443 {
444 ifr = (struct ifreq *) bufp;
445 sin = (struct sockaddr_in *) &ifr->ifr_addr;
446 memcpy (&(mydevs[numinterfaces].addr), (char *) &(sin->sin_addr),
447 sizeof (struct in_addr));
448 /* In case it is a stinkin' alias */
449 if ((p = strchr (ifr->ifr_name, ':')))
450 *p = '\0';
451
452 memset (mydevs[numinterfaces].name, '\0', MAX_IFACE_NAME_LEN);
453 if (strlen (ifr->ifr_name) < MAX_IFACE_NAME_LEN)
454 memcpy (mydevs[numinterfaces].name, ifr->ifr_name,
455 strlen (ifr->ifr_name));
456 else
457 memcpy (mydevs[numinterfaces].name, ifr->ifr_name,
459 numinterfaces++;
460 if (numinterfaces == 1023)
461 {
462 g_message ("You seem to have more than 1023 network interfaces."
463 " Things may not work right.");
464 break;
465 }
466 mydevs[numinterfaces].name[0] = '\0';
467 }
468
469 // If output parameter given, set value
470 if (howmany)
471 *howmany = numinterfaces;
472
473 return mydevs;
474}
475
476int
477v6_getsourceip (struct in6_addr *src, struct in6_addr *dst)
478{
479 int sd;
480 struct sockaddr_in sock;
481 unsigned int socklen;
482 unsigned short p1;
483
484 p1 = (unsigned short) rand ();
485 if (p1 < 5000)
486 p1 += 5000;
487
488 if (IN6_IS_ADDR_V4MAPPED (dst))
489 {
490 char name[INET6_ADDRSTRLEN];
491
492 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
493 {
494 perror ("Socket troubles");
495 return 0;
496 }
497 bzero (&sock, sizeof (struct sockaddr_in));
498 sock.sin_family = AF_INET;
499 sock.sin_addr.s_addr = dst->s6_addr32[3];
500 sock.sin_port = htons (p1);
501 if (connect (sd, (struct sockaddr *) &sock, sizeof (struct sockaddr_in))
502 == -1)
503 {
504 close (sd);
505 return 0;
506 }
507 bzero (&sock, sizeof (struct sockaddr_in));
508 socklen = sizeof (struct sockaddr_in);
509 if (getsockname (sd, (struct sockaddr *) &sock, &socklen) == -1)
510 {
511 perror ("getsockname");
512 close (sd);
513 return 0;
514 }
515
516 src->s6_addr32[0] = 0;
517 src->s6_addr32[1] = 0;
518 src->s6_addr32[2] = htonl (0xffff);
519 src->s6_addr32[3] = sock.sin_addr.s_addr;
520 g_debug ("source address is %s",
521 inet_ntop (AF_INET6, src, name, sizeof (name)));
522 close (sd);
523 }
524 else
525 {
526 struct sockaddr_in6 sock6;
527 char name[INET6_ADDRSTRLEN];
528
529 if ((sd = socket (AF_INET6, SOCK_DGRAM, 0)) == -1)
530 {
531 perror ("Socket troubles");
532 return 0;
533 }
534 bzero (&sock6, sizeof (sock6));
535 sock6.sin6_family = AF_INET6;
536 sock6.sin6_addr.s6_addr32[0] = dst->s6_addr32[0];
537 sock6.sin6_addr.s6_addr32[1] = dst->s6_addr32[1];
538 sock6.sin6_addr.s6_addr32[2] = dst->s6_addr32[2];
539 sock6.sin6_addr.s6_addr32[3] = dst->s6_addr32[3];
540 sock6.sin6_port = htons (p1);
541 if (connect (sd, (struct sockaddr *) &sock6, sizeof (struct sockaddr_in6))
542 == -1)
543 {
544 close (sd);
545 return 0;
546 }
547 bzero (&sock6, sizeof (struct sockaddr_in6));
548 socklen = sizeof (struct sockaddr_in6);
549 if (getsockname (sd, (struct sockaddr *) &sock6, &socklen) == -1)
550 {
551 perror ("getsockname");
552 close (sd);
553 return 0;
554 }
555
556 src->s6_addr32[0] = sock6.sin6_addr.s6_addr32[0];
557 src->s6_addr32[1] = sock6.sin6_addr.s6_addr32[1];
558 src->s6_addr32[2] = sock6.sin6_addr.s6_addr32[2];
559 src->s6_addr32[3] = sock6.sin6_addr.s6_addr32[3];
560 memcpy (src, &sock6.sin6_addr, sizeof (struct in6_addr));
561 g_debug ("source addrss is %s",
562 inet_ntop (AF_INET6, src, name, sizeof (name)));
563 close (sd);
564 }
565 return 1; /* Calling function responsible for checking validity */
566}
567
580static int
581getipv4routes (struct myroute *myroutes, int *numroutes)
582{
583 struct interface_info *mydevs;
584 int i;
585 int numinterfaces;
586 char buf[1024];
587 char *p, *endptr;
588 char iface[MAX_IFACE_NAME_LEN];
589 FILE *routez;
590 unsigned long dest;
591 struct in_addr inaddr;
592 unsigned long mask;
593 unsigned long ones;
594
595 /* Dummy socket for ioctl */
596 mydevs = v6_getinterfaces (&numinterfaces);
597
598 /* Now we must go through several techniques to determine info */
599 routez = fopen ("/proc/net/route", "r");
600
601 if (routez)
602 {
603 /* OK, linux style /proc/net/route ... we can handle this ... */
604 /* Now that we've got the interfaces, we g0 after the r0ut3Z */
605 if (fgets (buf, sizeof (buf), routez) == NULL) /* Kill the first line */
606 {
607 // /proc/net/route was empty or an error occurred.
608 g_message ("Could not read from /proc/net/route");
609 fclose (routez);
610 return -1;
611 }
612 while (fgets (buf, sizeof (buf), routez))
613 {
614 p = strtok (buf, " \t\n");
615 if (!p)
616 {
617 g_message ("Could not find interface in"
618 " /proc/net/route line");
619 continue;
620 }
621 strncpy (iface, p, sizeof (iface));
622 iface[MAX_IFACE_NAME_LEN - 1] = '\0';
623 if ((p = strchr (iface, ':')))
624 {
625 *p = '\0'; /* To support IP aliasing */
626 }
627 p = strtok (NULL, " \t\n");
628 endptr = NULL;
629 dest = strtoul (p, &endptr, 16);
630 g_debug ("ipv4 dest is %s", p);
631 if (!endptr || *endptr)
632 {
633 g_message ("Failed to determine Destination from"
634 " /proc/net/route");
635 continue;
636 }
637 inaddr.s_addr = dest;
638 myroutes[*numroutes].dest6.s6_addr32[0] = 0;
639 myroutes[*numroutes].dest6.s6_addr32[1] = 0;
640 myroutes[*numroutes].dest6.s6_addr32[2] = htonl (0xffff);
641 myroutes[*numroutes].dest6.s6_addr32[3] = inaddr.s_addr;
642 for (i = 0; i < 5; i++)
643 {
644 p = strtok (NULL, " \t\n");
645 if (!p)
646 break;
647 }
648 if (!p)
649 {
650 g_message ("Failed to find field %d in"
651 " /proc/net/route",
652 i + 2);
653 continue;
654 }
655 /* set metric */
656 endptr = NULL;
657 myroutes[*numroutes].metric = strtol (p, &endptr, 10);
658 if (!endptr || *endptr)
659 {
660 g_message ("%s: Failed to determine metric from /proc/net/route",
661 __func__);
662 continue;
663 }
664 p = strtok (NULL, " \t\n");
665 endptr = NULL;
666 mask = strtoul (p, &endptr, 16);
667 ones = 0;
668 i = 0;
669 while (mask & (1 << i++) && i < 32)
670 ones++;
671 myroutes[*numroutes].mask = ones + 96;
672 g_debug ("mask is %lu", myroutes[*numroutes].mask);
673 if (!endptr || *endptr)
674 {
675 g_message ("Failed to determine mask from"
676 " /proc/net/route");
677 continue;
678 }
679
680 g_debug ("#%d: for dev %s, The dest is %lX and the mask is %lX",
681 *numroutes, iface, myroutes[*numroutes].dest,
682 myroutes[*numroutes].mask);
683 for (i = 0; i < numinterfaces; i++)
684 if (!strcmp (iface, mydevs[i].name))
685 {
686 myroutes[*numroutes].dev = &mydevs[i];
687 break;
688 }
689 if (i == numinterfaces)
690 g_message (
691 "Failed to find interface %s mentioned in /proc/net/route",
692 iface);
693 (*numroutes)++;
694 if (*numroutes >= MAXROUTES)
695 {
696 g_message ("You seem to have WAY to many routes!");
697 break;
698 }
699 }
700 fclose (routez);
701 return 0;
702 }
703 else
704 return -1;
705}
706
718int
719getipv6routes (struct myroute *myroutes, int *numroutes)
720{
721 struct interface_info *mydevs;
722 int i, j;
723 int len;
724 struct in6_addr in6addr;
725 char destaddr[100];
726 int numinterfaces;
727 char buf[1024];
728 char *endptr;
729 FILE *routez;
730 char v6addr[INET6_ADDRSTRLEN];
731 char *token;
732 int cnt;
733
734 /* Dummy socket for ioctl */
735 mydevs = v6_getinterfaces (&numinterfaces);
736 routez = fopen ("/proc/net/ipv6_route", "r");
737 if (routez)
738 {
739 /* linux style /proc/net/ipv6_route ... we can handle this too... */
740 while (fgets (buf, sizeof (buf), routez) != NULL)
741 {
742 char iface[64];
743
744 token = strtok (buf, " \t\n");
745 if (token)
746 {
747 g_debug ("first token is %s", token);
748 strncpy (destaddr, token, sizeof (destaddr) - 1);
749 len = strlen (destaddr);
750 for (i = 0, j = 0; j < len; j++)
751 {
752 v6addr[i++] = destaddr[j];
753 if (j % 4 == 3)
754 v6addr[i++] = ':';
755 }
756 v6addr[--i] = '\0';
757 g_debug ("ipv6 dest is %s", v6addr);
758 if (inet_pton (AF_INET6, v6addr, &in6addr) <= 0)
759 {
760 g_message ("invalid ipv6 addressd");
761 continue;
762 }
763 memcpy (&myroutes[*numroutes].dest6, &in6addr,
764 sizeof (struct in6_addr));
765 }
766 token = strtok (NULL, " \t\n");
767 if (token)
768 {
769 endptr = NULL;
770 myroutes[*numroutes].mask = strtoul (token, &endptr, 16);
771 }
772
773 /* set metric */
774 cnt = 4;
775 while (cnt--)
776 {
777 token = strtok (NULL, " \t\n");
778 if (!token)
779 g_message ("getipv6routes error");
780 }
781 endptr = NULL;
782 myroutes[*numroutes].metric = strtoul (token, &endptr, 16);
783 if (!endptr || *endptr)
784 {
785 g_message (
786 "%s: Failed to determine metric from /proc/net/ipv6_route",
787 __func__);
788 continue;
789 }
790
791 /* set interface name */
792 cnt = 3;
793 while (cnt--)
794 {
795 token = strtok (NULL, " \t\n");
796 if (!token)
797 g_message ("getipv6routes error");
798 }
799 bzero (iface, sizeof (iface));
800 token = strtok (NULL, " \t\n");
801 if (token)
802 strncpy (iface, token, sizeof (iface) - 1);
803 for (i = 0; i < numinterfaces; i++)
804 if (!strcmp (iface, mydevs[i].name)
805 && !IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
806 {
807 myroutes[*numroutes].dev = &mydevs[i];
808 break;
809 }
810 if (i == numinterfaces)
811 g_message (
812 "Failed to find interface %s mentioned in /proc/net/ipv6_route",
813 iface);
814 (*numroutes)++;
815 if (*numroutes >= MAXROUTES)
816 {
817 g_message ("You seem to have WAY to many routes!");
818 break;
819 }
820 }
821 fclose (routez);
822 return 0;
823 }
824 else
825 {
826 g_message ("Didn't find IPv6 routes");
827 return -1;
828 }
829}
830
840char *
841v6_routethrough (struct in6_addr *dest, struct in6_addr *source)
842{
843 static int initialized = 0;
844 int i;
845 struct in6_addr addy;
846 static enum {
847 procroutetechnique,
848 connectsockettechnique,
849 guesstechnique
850 } technique = procroutetechnique;
851 struct interface_info *mydevs;
852 static struct myroute myroutes[MAXROUTES];
853 int numinterfaces = 0;
854 static int numroutes = 0;
855 struct in6_addr mask;
856 struct in6_addr network = {0};
857 struct in6_addr src;
858 long best_match = -1;
859
860 if (!dest)
861 {
862 g_message ("ipaddr2devname passed a NULL dest address");
863 return NULL;
864 }
865
866 if (IN6_IS_ADDR_V4MAPPED (dest))
867 gvm_source_addr_as_addr6 (&src);
868 else
869 gvm_source_addr6 (&src);
870
871 if (!initialized)
872 {
873 /* Dummy socket for ioctl */
874 initialized = 1;
875 mydevs = v6_getinterfaces (&numinterfaces);
876 if (IN6_IS_ADDR_V4MAPPED (dest))
877 {
878 if (getipv4routes (myroutes, &numroutes) < 0)
879 technique = connectsockettechnique;
880 }
881 else
882 {
883 if (getipv6routes (myroutes, &numroutes) < 0)
884 technique = connectsockettechnique;
885 }
886 }
887 else
888 {
889 mydevs = v6_getinterfaces (&numinterfaces);
890 }
891 /* WHEW, that takes care of initializing, now we have the easy job of
892 finding which route matches */
893 if (v6_islocalhost (dest))
894 {
895 if (source)
896 {
897 if (IN6_IS_ADDR_V4MAPPED (source))
898 {
899 source->s6_addr32[0] = 0;
900 source->s6_addr32[1] = 0;
901 source->s6_addr32[2] = htonl (0xffff);
902 source->s6_addr32[3] = htonl (0x7F000001);
903 }
904 else
905 {
906 source->s6_addr32[0] = 0;
907 source->s6_addr32[1] = 0;
908 source->s6_addr32[2] = 0;
909 source->s6_addr32[3] = htonl (1);
910 }
911 }
912 /* Now we find the localhost interface name, assuming 127.0.0.1
913 or ::1 is localhost (it damn well better be!)... */
914 for (i = 0; i < numinterfaces; i++)
915 {
916 if (IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
917 {
918 if (mydevs[i].addr6.s6_addr32[3] == htonl (0x7F000001))
919 return mydevs[i].name;
920 }
921 else
922 {
923 if (IN6_ARE_ADDR_EQUAL (&in6addr_any, &mydevs[i].addr6))
924 return mydevs[i].name;
925 }
926 }
927 return NULL;
928 }
929
930 if (technique == procroutetechnique)
931 {
932 char addr1[INET6_ADDRSTRLEN];
933 char addr2[INET6_ADDRSTRLEN];
934 for (i = 0; i < numroutes; i++)
935 {
936 if (ipv6_prefix_to_mask (myroutes[i].mask, &mask) == -1)
937 {
938 g_warning ("error creating IPv6 mask from prefix: %ld",
939 myroutes[i].mask);
940 return NULL;
941 }
942 for (int j = 0; j < (int) sizeof (struct in6_addr); j++)
943 network.s6_addr[j] = dest->s6_addr[j] & mask.s6_addr[j];
944
945 g_debug (
946 "comparing addresses %s and %s",
947 inet_ntop (AF_INET6, &network, addr1, sizeof (addr1)),
948 inet_ntop (AF_INET6, &myroutes[i].dest6, addr2, sizeof (addr2)));
949 /* matching route found */
950 if (IN6_ARE_ADDR_EQUAL (&network, &myroutes[i].dest6))
951 {
952 /* First time a match is found */
953 if (-1 == best_match)
954 {
955 best_match = i;
956 }
957 else
958 {
959 /* Better match found */
960 if (myroutes[i].mask > myroutes[best_match].mask)
961 {
962 best_match = i;
963 }
964 /* Match with equal mask and smaller (better) metric found */
965 else if ((myroutes[i].mask == myroutes[best_match].mask)
966 && (myroutes[i].metric
967 < myroutes[best_match].metric))
968 {
969 best_match = i;
970 }
971 }
972 }
973 }
974 if (source)
975 {
976 if (!IN6_ARE_ADDR_EQUAL (&src, &in6addr_any))
977 memcpy (source, &src, sizeof (struct in6_addr));
978 else
979 {
980 if (myroutes[best_match].dev != NULL)
981 {
982 memcpy (source, &myroutes[best_match].dev->addr6,
983 sizeof (struct in6_addr));
984 }
985 }
986 }
987 g_debug (
988 "%s: Best matching route with dst '%s' metric '%ld' and interface '%s'",
989 __func__,
990 inet_ntop (AF_INET6, &myroutes[best_match].dest6, addr1,
991 sizeof (addr1)),
992 myroutes[best_match].mask, myroutes[best_match].dev->name);
993 if (best_match != -1)
994 return myroutes[best_match].dev->name;
995
996 technique = connectsockettechnique;
997 }
998 if (technique == connectsockettechnique)
999 {
1000 if (!v6_getsourceip (&addy, dest))
1001 return NULL;
1002 if (IN6_ARE_ADDR_EQUAL (&addy, &network))
1003 {
1004 struct hostent *myhostent = NULL;
1005 char myname[MAXHOSTNAMELEN + 1];
1006
1007 myhostent = gethostbyname (myname);
1008 if (gethostname (myname, MAXHOSTNAMELEN) || !myhostent)
1009 g_message ("Cannot get hostname!");
1010 else if (myhostent->h_addrtype == AF_INET)
1011 {
1012 addy.s6_addr32[0] = 0;
1013 addy.s6_addr32[1] = 0;
1014 addy.s6_addr32[2] = htonl (0xffff);
1015 memcpy (&addy.s6_addr32[0], myhostent->h_addr_list[0],
1016 sizeof (struct in6_addr));
1017 }
1018 else
1019 memcpy (&addy, myhostent->h_addr_list[0], sizeof (struct in6_addr));
1020 }
1021
1022 /* Now we insure this claimed address is a real interface ... */
1023 for (i = 0; i < numinterfaces; i++)
1024 {
1025 char addr1[INET6_ADDRSTRLEN];
1026 char addr2[INET6_ADDRSTRLEN];
1027
1028 g_debug (
1029 "comparing addresses %s and %s",
1030 inet_ntop (AF_INET6, &mydevs[i].addr6, addr1, sizeof (addr1)),
1031 inet_ntop (AF_INET6, &addy, addr2, sizeof (addr2)));
1032 if (IN6_ARE_ADDR_EQUAL (&mydevs[i].addr6, &addy))
1033 {
1034 if (source)
1035 {
1036 memcpy (source, &addy, sizeof (struct in6_addr));
1037 }
1038 return mydevs[i].name;
1039 }
1040 }
1041 return NULL;
1042 }
1043 else
1044 g_message ("%s: Provided technique is neither proc route nor"
1045 " connect socket",
1046 __func__);
1047 return NULL;
1048}
1049
1059char *
1060routethrough (struct in_addr *dest, struct in_addr *source)
1061{
1062 static int initialized = 0;
1063 int i;
1064 char buf[10240];
1065 struct interface_info *mydevs;
1066 static struct myroute
1067 {
1068 struct interface_info *dev;
1069 unsigned long mask;
1070 unsigned long dest;
1071 unsigned long metric;
1072 } myroutes[MAXROUTES];
1073 int numinterfaces = 0;
1074 char *p, *endptr;
1075 char iface[MAX_IFACE_NAME_LEN];
1076 static int numroutes = 0;
1077 FILE *routez;
1078 long best_match = -1;
1079
1080 struct in_addr src;
1081
1082 gvm_source_addr (&src);
1083 if (!dest)
1084 {
1085 g_message ("ipaddr2devname passed a NULL dest address");
1086 return NULL;
1087 }
1088
1089 if (!initialized)
1090 {
1091 /* Dummy socket for ioctl */
1092 initialized = 1;
1093 mydevs = getinterfaces (&numinterfaces);
1094 if (!mydevs)
1095 return NULL;
1096
1097 routez = fopen ("/proc/net/route", "r");
1098 if (routez)
1099 {
1100 /* OK, linux style /proc/net/route ... we can handle this ... */
1101 /* Now that we've got the interfaces, we g0 after the r0ut3Z */
1102 if (fgets (buf, sizeof (buf), routez)
1103 == NULL) /* Kill the first line */
1104 g_message ("Could not read from /proc/net/route");
1105 while (fgets (buf, sizeof (buf), routez))
1106 {
1107 p = strtok (buf, " \t\n");
1108 if (!p)
1109 {
1110 g_message ("Could not find interface in"
1111 " /proc/net/route line");
1112 continue;
1113 }
1114 strncpy (iface, p, sizeof (iface));
1115 iface[MAX_IFACE_NAME_LEN - 1] = '\0';
1116 if ((p = strchr (iface, ':')))
1117 {
1118 *p = '\0'; /* To support IP aliasing */
1119 }
1120 p = strtok (NULL, " \t\n");
1121 endptr = NULL;
1122 myroutes[numroutes].dest = strtoul (p, &endptr, 16);
1123 if (!endptr || *endptr)
1124 {
1125 g_message (
1126 "Failed to determine Destination from /proc/net/route");
1127 continue;
1128 }
1129 for (i = 0; i < 5; i++)
1130 {
1131 p = strtok (NULL, " \t\n");
1132 if (!p)
1133 break;
1134 }
1135 if (!p)
1136 {
1137 g_message ("Failed to find field %d in"
1138 " /proc/net/route",
1139 i + 2);
1140 continue;
1141 }
1142 endptr = NULL;
1143 myroutes[numroutes].metric = strtol (p, &endptr, 10);
1144 if (!endptr || *endptr)
1145 {
1146 g_message ("Failed to determine metric from /proc/net/route");
1147 continue;
1148 }
1149 p = strtok (NULL, " \t\n");
1150 endptr = NULL;
1151 myroutes[numroutes].mask = strtoul (p, &endptr, 16);
1152 if (!endptr || *endptr)
1153 {
1154 g_message ("Failed to determine mask"
1155 " from /proc/net/route");
1156 continue;
1157 }
1158
1159 g_debug ("#%d: for dev %s, The dest is %lX and the mask is %lX",
1160 numroutes, iface, myroutes[numroutes].dest,
1161 myroutes[numroutes].mask);
1162 for (i = 0; i < numinterfaces; i++)
1163 if (!strcmp (iface, mydevs[i].name))
1164 {
1165 myroutes[numroutes].dev = &mydevs[i];
1166 break;
1167 }
1168 if (i == numinterfaces)
1169 g_message (
1170 "Failed to find interface %s mentioned in /proc/net/route",
1171 iface);
1172 numroutes++;
1173 if (numroutes >= MAXROUTES)
1174 {
1175 g_message ("You seem to have WAY to many routes!");
1176 break;
1177 }
1178 }
1179 fclose (routez);
1180 }
1181 else
1182 {
1183 g_message ("Could not read from /proc/net/route");
1184 return NULL;
1185 }
1186 }
1187 else
1188 mydevs = getinterfaces (&numinterfaces);
1189 /* WHEW, that takes care of initializing, now we have the easy job of
1190 finding which route matches */
1191 if (mydevs && islocalhost (dest))
1192 {
1193 if (source)
1194 source->s_addr = htonl (0x7F000001);
1195 /* Now we find the localhost interface name, assuming 127.0.0.1 is
1196 localhost (it damn well better be!)... */
1197 for (i = 0; i < numinterfaces; i++)
1198 {
1199 if (mydevs[i].addr.s_addr == htonl (0x7F000001))
1200 {
1201 return mydevs[i].name;
1202 }
1203 }
1204 return NULL;
1205 }
1206
1207 for (i = 0; i < numroutes; i++)
1208 {
1209 /* Matching route found */
1210 if ((dest->s_addr & myroutes[i].mask) == myroutes[i].dest)
1211 {
1212 /* First time a match is found */
1213 if (-1 == best_match)
1214 {
1215 best_match = i;
1216 }
1217 else
1218 {
1219 /* Better match found */
1220 if (myroutes[i].mask > myroutes[best_match].mask)
1221 {
1222 best_match = i;
1223 }
1224 /* Match with equal mask and smaller (better) metric found */
1225 else if ((myroutes[i].mask == myroutes[best_match].mask)
1226 && (myroutes[i].metric < myroutes[best_match].metric))
1227 {
1228 best_match = i;
1229 }
1230 }
1231 }
1232 }
1233
1234 /* Set source */
1235 if (source)
1236 {
1237 /* Source address is given */
1238 if (src.s_addr != INADDR_ANY)
1239 source->s_addr = src.s_addr;
1240 /* Source address is INADDR_ANY and there is a good route */
1241 else if (best_match != -1)
1242 source->s_addr = myroutes[best_match].dev->addr.s_addr;
1243 /* No best route found and no default */
1244 else
1245 {
1246 /* Assigned first route in the table */
1247 if (myroutes[0].dev)
1248 {
1249 source->s_addr = myroutes[0].dev->addr.s_addr;
1250 best_match = 0;
1251 }
1252 /* or any */
1253 else
1254 source->s_addr = INADDR_ANY;
1255 }
1256 }
1257
1258 if (best_match != -1)
1259 return myroutes[best_match].dev->name;
1260 return NULL;
1261}
1262
1269char *
1270get_iface_from_ip (const char *local_ip)
1271{
1272 char errbuf[PCAP_ERRBUF_SIZE];
1273 pcap_if_t *alldevsp1 = NULL, *devs_aux = NULL;
1274 char *if_name = NULL;
1275
1276 if (pcap_findalldevs (&alldevsp1, errbuf) == -1)
1277 g_debug ("Error for pcap_findalldevs(): %s", errbuf);
1278
1279 devs_aux = alldevsp1;
1280 while (devs_aux)
1281 {
1282 pcap_addr_t *addr_aux = NULL;
1283
1284 addr_aux = devs_aux->addresses;
1285 while (addr_aux)
1286 {
1287 char buffer[INET6_ADDRSTRLEN];
1288
1289 if (((struct sockaddr *) addr_aux->addr)->sa_family == AF_INET)
1290 inet_ntop (AF_INET,
1291 &(((struct sockaddr_in *) addr_aux->addr)->sin_addr),
1292 buffer, INET_ADDRSTRLEN);
1293 else if (((struct sockaddr *) addr_aux->addr)->sa_family == AF_INET6)
1294 inet_ntop (AF_INET6,
1295 &(((struct sockaddr_in6 *) addr_aux->addr)->sin6_addr),
1296 buffer, INET6_ADDRSTRLEN);
1297
1298 if (!g_strcmp0 (buffer, local_ip))
1299 {
1300 if_name = g_strdup (devs_aux->name);
1301 break;
1302 }
1303 addr_aux = addr_aux->next;
1304 }
1305
1306 if (if_name)
1307 break;
1308 devs_aux = devs_aux->next;
1309 }
1310 pcap_freealldevs (alldevsp1);
1311 g_debug ("returning %s as device", if_name);
1312
1313 return if_name;
1314}
1315
1323int
1324get_iface_index (struct in6_addr *ipaddr, int *ifindex)
1325{
1326 struct in6_addr src_addr;
1327 char *if_name, *ip_address;
1328
1329 // We get the local address to use, with the remote address.
1330 memset (&src_addr, '\0', sizeof (struct in6_addr));
1331 v6_getsourceip (&src_addr, ipaddr);
1332 ip_address = addr6_as_str (&src_addr);
1333
1334 // Once with the local ip address, we get the source iface name
1335 if_name = get_iface_from_ip (ip_address);
1336 g_free (ip_address);
1337 if (!if_name)
1338 {
1339 g_debug ("%s: Missing interface name", __func__);
1340 return -1;
1341 }
1342
1343 *ifindex = if_nametoindex (if_name);
1344
1345 return 0;
1346}
Header file for module bpf_share.
const char * name
Definition: nasl_init.c:411
struct in_addr saddr
uint8_t len
struct in6_addr s6addr
static void prefix(int n, int i)
Definition: nasl_tree.c:222
Header file for module network.
struct interface_info * v6_getinterfaces(int *howmany)
Definition: pcap.c:328
int islocalhost(struct in_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:261
int v6_is_local_ip(struct in6_addr *addr)
Definition: pcap.c:108
static int getipv4routes(struct myroute *myroutes, int *numroutes)
Get the ipv4 routes and number of routes.
Definition: pcap.c:581
char * routethrough(struct in_addr *dest, struct in_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition: pcap.c:1060
int v6_islocalhost(struct in6_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:224
int v6_getsourceip(struct in6_addr *src, struct in6_addr *dst)
Definition: pcap.c:477
static int v6_ipaddr2devname(char *dev, int sz, struct in6_addr *addr)
Definition: pcap.c:166
char * v6_routethrough(struct in6_addr *dest, struct in6_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition: pcap.c:841
int get_iface_index(struct in6_addr *ipaddr, int *ifindex)
Get the interface index depending on the target's IP.
Definition: pcap.c:1324
int getipv6routes(struct myroute *myroutes, int *numroutes)
Get the IPv6 routes and number of routes.
Definition: pcap.c:719
static int ipv6_prefix_to_mask(unsigned prefix, struct in6_addr *mask)
Generate an ipv6 mask from the given ipv6 prefix.
Definition: pcap.c:82
struct interface_info * getinterfaces(int *howmany)
Definition: pcap.c:403
#define MAX_IFACE_NAME_LEN
Maximum length of an interface's name.
Definition: pcap.c:40
static int ipaddr2devname(char *dev, int sz, struct in_addr *addr)
Definition: pcap.c:197
int get_datalink_size(int datalink)
Definition: pcap.c:288
char * get_iface_from_ip(const char *local_ip)
Given an IP address, determines which interface belongs to.
Definition: pcap.c:1270
#define MAXROUTES
Definition: pcap.c:29
Header file for module pcap.
struct in6_addr addr6
Definition: pcap.c:46
struct in6_addr mask
Definition: pcap.c:47
char name[MAX_IFACE_NAME_LEN]
Definition: pcap.c:44
struct in_addr addr
Definition: pcap.c:45
Definition: pcap.c:55
struct in6_addr dest6
Definition: pcap.c:57
unsigned long mask
Definition: pcap.c:58
unsigned long metric
Definition: pcap.c:60
unsigned long dest
Definition: pcap.c:59
struct interface_info * dev
Definition: pcap.c:56
Support macros for special platforms.