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
32 
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 
54 struct myroute
55 {
57  struct in6_addr dest6;
58  unsigned long mask;
59  unsigned long dest;
60  unsigned long metric;
61 };
62 
63 struct interface_info *
64 getinterfaces (int *howmany);
65 struct interface_info *
66 v6_getinterfaces (int *howmany);
67 int
68 getipv6routes (struct myroute *myroutes, int *numroutes);
69 
81 static int
82 ipv6_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 
107 int
108 v6_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  */
165 static int
166 v6_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  */
196 static int
197 ipaddr2devname (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 
223 int
224 v6_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 
260 int
261 islocalhost (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 
287 int
288 get_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 
327 struct interface_info *
328 v6_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 
402 struct interface_info *
403 getinterfaces (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,
458  MAX_IFACE_NAME_LEN - 1);
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 
476 int
477 v6_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 
580 static int
581 getipv4routes (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 
718 int
719 getipv6routes (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 
840 char *
841 v6_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 
1059 char *
1060 routethrough (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 
1269 char *
1270 get_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 
1323 int
1324 get_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 }
getipv6routes
int getipv6routes(struct myroute *myroutes, int *numroutes)
Get the IPv6 routes and number of routes.
Definition: pcap.c:719
bpf_share.h
Header file for module bpf_share.
v6_getinterfaces
struct interface_info * v6_getinterfaces(int *howmany)
Definition: pcap.c:328
getipv4routes
static int getipv4routes(struct myroute *myroutes, int *numroutes)
Get the ipv4 routes and number of routes.
Definition: pcap.c:581
myroute::mask
unsigned long mask
Definition: pcap.c:58
ipv6_prefix_to_mask
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
v6_routethrough
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
interface_info::addr6
struct in6_addr addr6
Definition: pcap.c:46
getinterfaces
struct interface_info * getinterfaces(int *howmany)
Definition: pcap.c:403
interface_info::name
char name[MAX_IFACE_NAME_LEN]
Definition: pcap.c:44
name
const char * name
Definition: nasl_init.c:411
v6_is_local_ip
int v6_is_local_ip(struct in6_addr *addr)
Definition: pcap.c:108
get_iface_from_ip
char * get_iface_from_ip(const char *local_ip)
Given an IP address, determines which interface belongs to.
Definition: pcap.c:1270
saddr
struct in_addr saddr
Definition: nasl_packet_forgery.c:0
support.h
Support macros for special platforms.
get_iface_index
int get_iface_index(struct in6_addr *ipaddr, int *ifindex)
Get the interface index depending on the target's IP.
Definition: pcap.c:1324
v6_getsourceip
int v6_getsourceip(struct in6_addr *src, struct in6_addr *dst)
Definition: pcap.c:477
s6addr
struct in6_addr s6addr
Definition: nasl_packet_forgery_v6.c:0
len
uint8_t len
Definition: nasl_packet_forgery.c:1
v6_ipaddr2devname
static int v6_ipaddr2devname(char *dev, int sz, struct in6_addr *addr)
Definition: pcap.c:166
myroute::metric
unsigned long metric
Definition: pcap.c:60
pcap_openvas.h
Header file for module pcap.
islocalhost
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
prefix
static void prefix(int n, int i)
Definition: nasl_tree.c:222
ipaddr2devname
static int ipaddr2devname(char *dev, int sz, struct in_addr *addr)
Definition: pcap.c:197
get_datalink_size
int get_datalink_size(int datalink)
Definition: pcap.c:288
MAXROUTES
#define MAXROUTES
Definition: pcap.c:29
myroute::dev
struct interface_info * dev
Definition: pcap.c:56
v6_islocalhost
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
network.h
Header file for module network.
myroute
Definition: pcap.c:55
interface_info
Definition: pcap.c:43
MAX_IFACE_NAME_LEN
#define MAX_IFACE_NAME_LEN
Maximum length of an interface's name.
Definition: pcap.c:40
interface_info::addr
struct in_addr addr
Definition: pcap.c:45
routethrough
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
interface_info::mask
struct in6_addr mask
Definition: pcap.c:47
myroute::dest
unsigned long dest
Definition: pcap.c:59
myroute::dest6
struct in6_addr dest6
Definition: pcap.c:57