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