OpenVAS Scanner  7.0.1~git
pcap.c
Go to the documentation of this file.
1 /* Portions Copyright (C) 2009-2019 Greenbone Networks GmbH
2  * Based on work Copyright (C) 1999 Renaud Deraison
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "bpf_share.h"
22 #include "network.h"
23 #include "pcap_openvas.h"
24 #include "support.h"
25 
26 #include <arpa/inet.h>
27 #include <gvm/base/logging.h>
28 #include <gvm/base/networking.h>
29 #include <ifaddrs.h>
30 #include <net/if.h>
31 #include <netdb.h>
32 #include <netinet/in.h>
33 #include <pcap.h>
34 #include <resolv.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/ioctl.h>
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 
42 #define MAXROUTES 1024
43 
44 #undef G_LOG_DOMAIN
45 
48 #define G_LOG_DOMAIN "lib misc"
49 
51 {
52  char name[64];
53  struct in_addr addr;
54  struct in6_addr addr6;
55  struct in6_addr mask;
56 };
57 
58 struct myroute
59 {
61  struct in6_addr dest6;
62  unsigned long mask;
63  unsigned long dest;
64 };
65 
66 struct interface_info *
67 getinterfaces (int *howmany);
68 struct interface_info *
69 v6_getinterfaces (int *howmany);
70 int
71 getipv6routes (struct myroute *myroutes, int *numroutes);
72 
73 static void
74 ipv6addrmask (struct in6_addr *in6addr, int mask)
75 {
76  int wordmask;
77  int word;
78  uint32_t *ptr;
79  uint32_t addr;
80 
81  word = mask / 32;
82  wordmask = mask % 32;
83  ptr = (uint32_t *) in6addr;
84  switch (word)
85  {
86  case 0:
87  ptr[1] = ptr[2] = ptr[3] = 0;
88  addr = ptr[0];
89  addr = ntohl (addr) >> (32 - wordmask);
90  addr = htonl (addr << (32 - wordmask));
91  ptr[0] = addr;
92  break;
93  case 1:
94  ptr[2] = ptr[3] = 0;
95  addr = ptr[1];
96  addr = ntohl (addr) >> (32 - wordmask);
97  addr = htonl (addr << (32 - wordmask));
98  ptr[1] = addr;
99  break;
100  case 2:
101  ptr[3] = 0;
102  addr = ptr[2];
103  addr = ntohl (addr) >> (32 - wordmask);
104  addr = htonl (addr << (32 - wordmask));
105  ptr[2] = addr;
106  break;
107  case 3:
108  addr = ptr[3];
109  addr = ntohl (addr) >> (32 - wordmask);
110  addr = htonl (addr << (32 - wordmask));
111  ptr[3] = addr;
112  break;
113  }
114 }
115 
116 int
117 v6_is_local_ip (struct in6_addr *addr)
118 {
119  int ifaces;
120  struct interface_info *ifs;
121  int i;
122  static struct myroute myroutes[MAXROUTES];
123  int numroutes = 0;
124  struct in6_addr in6addr;
125 
126  if ((ifs = v6_getinterfaces (&ifaces)) == NULL)
127  return -1;
128 
129  if (IN6_IS_ADDR_V4MAPPED (addr))
130  {
131  for (i = 0; i < ifaces; i++)
132  {
133  bpf_u_int32 net, mask;
134  char errbuf[PCAP_ERRBUF_SIZE];
135  pcap_lookupnet (ifs[i].name, &net, &mask, errbuf);
136  if ((net & mask) == (addr->s6_addr32[3] & mask))
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  memcpy (&in6addr, addr, sizeof (struct in6_addr));
154  ipv6addrmask (&in6addr, myroutes[i].mask);
155  g_debug ("comparing addresses %s and %s\n",
156  inet_ntop (AF_INET6, &in6addr, addr1, sizeof (addr1)),
157  inet_ntop (AF_INET6, &myroutes[i].dest6, addr2,
158  sizeof (addr2)));
159  if (IN6_ARE_ADDR_EQUAL (&in6addr, &myroutes[i].dest6))
160  {
161  return 1;
162  }
163  }
164  }
165  }
166  return 0;
167 }
168 
169 /*
170  * Taken straight out of Fyodor's Nmap
171  */
172 int
173 v6_ipaddr2devname (char *dev, int sz, struct in6_addr *addr)
174 {
175  struct interface_info *mydevs;
176  int numdevs = 0;
177  int i;
178  mydevs = v6_getinterfaces (&numdevs);
179 
180  if (!mydevs)
181  return -1;
182 
183  for (i = 0; i < numdevs; i++)
184  {
185  char addr1[INET6_ADDRSTRLEN];
186  char addr2[INET6_ADDRSTRLEN];
187  g_debug ("comparing addresses %s and %s\n",
188  inet_ntop (AF_INET6, addr, addr1, sizeof (addr1)),
189  inet_ntop (AF_INET6, &mydevs[i].addr6, addr2, sizeof (addr2)));
190  if (IN6_ARE_ADDR_EQUAL (addr, &mydevs[i].addr6))
191  {
192  dev[sz - 1] = '\0';
193  strncpy (dev, mydevs[i].name, sz);
194  return 0;
195  }
196  }
197  return -1;
198 }
199 
200 /*
201  * Taken straight out of Fyodor's Nmap
202  */
203 int
204 ipaddr2devname (char *dev, int sz, struct in_addr *addr)
205 {
206  struct interface_info *mydevs;
207  int numdevs;
208  int i;
209  mydevs = getinterfaces (&numdevs);
210 
211  if (!mydevs)
212  return -1;
213 
214  for (i = 0; i < numdevs; i++)
215  {
216  if (addr->s_addr == mydevs[i].addr.s_addr)
217  {
218  dev[sz - 1] = '\0';
219  strncpy (dev, mydevs[i].name, sz);
220  return 0;
221  }
222  }
223  return -1;
224 }
225 
230 int
231 v6_islocalhost (struct in6_addr *addr)
232 {
233  char dev[128];
234 
235  if (addr == NULL)
236  return -1;
237 
238  if (IN6_IS_ADDR_V4MAPPED (addr))
239  {
240  /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
241  probably localhost */
242  if ((addr->s6_addr32[3] & htonl (0xFF000000)) == htonl (0x7F000000))
243  return 1;
244 
245  if (!addr->s6_addr32[3])
246  return 1;
247  }
248 
249  if (IN6_IS_ADDR_LOOPBACK (addr))
250  return 1;
251 
252  /* If it is the same addy as a local interface, then it is
253  probably localhost */
254 
255  if (v6_ipaddr2devname (dev, sizeof (dev), addr) != -1)
256  return 1;
257 
258  /* OK, so to a first approximation, this addy is probably not
259  localhost */
260  return 0;
261 }
262 
267 int
268 islocalhost (struct in_addr *addr)
269 {
270  char dev[128];
271 
272  if (addr == NULL)
273  return -1;
274 
275  /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
276  probably localhost */
277  if ((addr->s_addr & htonl (0xFF000000)) == htonl (0x7F000000))
278  return 1;
279 
280  if (!addr->s_addr)
281  return 1;
282 
283  /* If it is the same addy as a local interface, then it is
284  probably localhost */
285 
286  if (ipaddr2devname (dev, sizeof (dev), addr) != -1)
287  return 1;
288 
289  /* OK, so to a first approximation, this addy is probably not
290  localhost */
291  return 0;
292 }
293 
294 int
295 get_datalink_size (int datalink)
296 {
297  int offset = -1;
298  switch (datalink)
299  {
300  case DLT_EN10MB:
301  offset = 14;
302  break;
303  case DLT_IEEE802:
304  offset = 22;
305  break;
306  case DLT_NULL:
307  offset = 4;
308  break;
309  case DLT_SLIP:
310 #if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
311  offset = 16;
312 #else
313  offset = 24; /* Anyone use this??? */
314 #endif
315  break;
316  case DLT_PPP:
317 #if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
318  offset = 4;
319 #else
320 #ifdef SOLARIS
321  offset = 8;
322 #else
323  offset = 24; /* Anyone use this? */
324 #endif /* ifdef solaris */
325 #endif /* if freebsd || openbsd || netbsd || bsdi */
326  break;
327  case DLT_RAW:
328  offset = 0;
329  break;
330  }
331  return offset;
332 }
333 
334 struct interface_info *
335 v6_getinterfaces (int *howmany)
336 {
337  struct sockaddr_in *saddr;
338  struct sockaddr_in6 *s6addr;
339  static struct interface_info mydevs[1024];
340  int numinterfaces = 0;
341  struct ifaddrs *ifaddr, *ifa;
342  int family;
343 
344  if (getifaddrs (&ifaddr) == -1)
345  {
346  perror ("getifaddrs");
347  }
348  else
349  {
350  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
351  {
352  if (ifa->ifa_addr == NULL)
353  continue;
354 
355  family = ifa->ifa_addr->sa_family;
356  if (family == AF_INET)
357  {
358  strncpy (mydevs[numinterfaces].name, ifa->ifa_name,
359  sizeof (mydevs[numinterfaces].name) - 1);
360  saddr = (struct sockaddr_in *) ifa->ifa_addr;
361  mydevs[numinterfaces].addr6.s6_addr32[0] = 0;
362  mydevs[numinterfaces].addr6.s6_addr32[1] = 0;
363  mydevs[numinterfaces].addr6.s6_addr32[2] = htonl (0xffff);
364  mydevs[numinterfaces].addr6.s6_addr32[3] = saddr->sin_addr.s_addr;
365  saddr = (struct sockaddr_in *) ifa->ifa_netmask;
366  mydevs[numinterfaces].mask.s6_addr32[0] = 0;
367  mydevs[numinterfaces].mask.s6_addr32[1] = 0;
368  mydevs[numinterfaces].mask.s6_addr32[2] = htonl (0xffff);
369  mydevs[numinterfaces].mask.s6_addr32[3] = saddr->sin_addr.s_addr;
370  g_debug ("interface name is %s\n", ifa->ifa_name);
371  g_debug ("\tAF_INET family\n");
372  g_debug ("\taddress is %s\n", inet_ntoa (saddr->sin_addr));
373  g_debug ("\tnetmask is %s\n", inet_ntoa (saddr->sin_addr));
374  numinterfaces++;
375  }
376  else if (family == AF_INET6)
377  {
378  char ipaddr[INET6_ADDRSTRLEN];
379 
380  strncpy (mydevs[numinterfaces].name, ifa->ifa_name,
381  sizeof (mydevs[numinterfaces].name) - 1);
382  s6addr = (struct sockaddr_in6 *) ifa->ifa_addr;
383  memcpy (&(mydevs[numinterfaces].addr6),
384  (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
385  s6addr = (struct sockaddr_in6 *) ifa->ifa_netmask;
386  memcpy (&(mydevs[numinterfaces].mask),
387  (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
388  numinterfaces++;
389  g_debug ("\tAF_INET6 family\n");
390  g_debug ("interface name is %s\n", ifa->ifa_name);
391  g_debug ("\taddress is %s\n",
392  inet_ntop (AF_INET6, &s6addr->sin6_addr, ipaddr,
393  sizeof (ipaddr)));
394  }
395  else
396  g_debug ("\tfamily is %d\n", ifa->ifa_addr->sa_family);
397  }
398  *howmany = numinterfaces;
399 
400  freeifaddrs (ifaddr);
401  }
402  return mydevs;
403 }
404 
409 struct interface_info *
410 getinterfaces (int *howmany)
411 {
412  static struct interface_info mydevs[1024];
413  int numinterfaces = 0;
414  int sd;
415  int len;
416  char *p;
417  char buf[10240];
418  struct ifconf ifc;
419  struct ifreq *ifr;
420  struct sockaddr_in *sin;
421  char *bufp;
422 
423  /* Dummy socket for ioctl. */
424  sd = socket (AF_INET, SOCK_DGRAM, 0);
425  bzero (buf, sizeof (buf));
426  if (sd < 0)
427  {
428  g_message ("socket in getinterfaces");
429  return NULL;
430  }
431 
432  ifc.ifc_len = sizeof (buf);
433  ifc.ifc_buf = buf;
434  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
435  g_message ("Failed to determine your configured interfaces!");
436 
437  close (sd);
438  if (ifc.ifc_len == 0)
439  g_message (
440  "getinterfaces: SIOCGIFCONF claims you have no network interfaces!");
441 
442 #ifndef __FreeBSD__
443  len = sizeof (struct ifmap);
444 #else
445  len = sizeof (struct sockaddr);
446 #endif
447 
448  for (bufp = buf; bufp && *bufp && (bufp < (buf + ifc.ifc_len));
449  bufp += sizeof (ifr->ifr_name) + len)
450  {
451  ifr = (struct ifreq *) bufp;
452  sin = (struct sockaddr_in *) &ifr->ifr_addr;
453  memcpy (&(mydevs[numinterfaces].addr), (char *) &(sin->sin_addr),
454  sizeof (struct in_addr));
455  /* In case it is a stinkin' alias */
456  if ((p = strchr (ifr->ifr_name, ':')))
457  *p = '\0';
458  strncpy (mydevs[numinterfaces].name, ifr->ifr_name, 63);
459  mydevs[numinterfaces].name[63] = '\0';
460  numinterfaces++;
461  if (numinterfaces == 1023)
462  {
463  g_message ("You seem to have more than 1023 network interfaces."
464  " Things may not work right.");
465  break;
466  }
467  mydevs[numinterfaces].name[0] = '\0';
468  }
469 
470  // If output parameter given, set value
471  if (howmany)
472  *howmany = numinterfaces;
473 
474  return mydevs;
475 }
476 
477 int
478 v6_getsourceip (struct in6_addr *src, struct in6_addr *dst)
479 {
480  int sd;
481  struct sockaddr_in sock;
482  unsigned int socklen;
483  unsigned short p1;
484 
485  p1 = (unsigned short) rand ();
486  if (p1 < 5000)
487  p1 += 5000;
488 
489  if (IN6_IS_ADDR_V4MAPPED (dst))
490  {
491  char name[INET6_ADDRSTRLEN];
492 
493  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
494  {
495  perror ("Socket troubles");
496  return 0;
497  }
498  bzero (&sock, sizeof (struct sockaddr_in));
499  sock.sin_family = AF_INET;
500  sock.sin_addr.s_addr = dst->s6_addr32[3];
501  sock.sin_port = htons (p1);
502  if (connect (sd, (struct sockaddr *) &sock, sizeof (struct sockaddr_in))
503  == -1)
504  {
505  close (sd);
506  return 0;
507  }
508  bzero (&sock, sizeof (struct sockaddr_in));
509  socklen = sizeof (struct sockaddr_in);
510  if (getsockname (sd, (struct sockaddr *) &sock, &socklen) == -1)
511  {
512  perror ("getsockname");
513  close (sd);
514  return 0;
515  }
516 
517  src->s6_addr32[0] = 0;
518  src->s6_addr32[1] = 0;
519  src->s6_addr32[2] = htonl (0xffff);
520  src->s6_addr32[3] = sock.sin_addr.s_addr;
521  g_debug ("source address is %s\n",
522  inet_ntop (AF_INET6, src, name, sizeof (name)));
523  close (sd);
524  }
525  else
526  {
527  struct sockaddr_in6 sock6;
528  char name[INET6_ADDRSTRLEN];
529 
530  if ((sd = socket (AF_INET6, SOCK_DGRAM, 0)) == -1)
531  {
532  perror ("Socket troubles");
533  return 0;
534  }
535  bzero (&sock6, sizeof (sock6));
536  sock6.sin6_family = AF_INET6;
537  sock6.sin6_addr.s6_addr32[0] = dst->s6_addr32[0];
538  sock6.sin6_addr.s6_addr32[1] = dst->s6_addr32[1];
539  sock6.sin6_addr.s6_addr32[2] = dst->s6_addr32[2];
540  sock6.sin6_addr.s6_addr32[3] = dst->s6_addr32[3];
541  sock6.sin6_port = htons (p1);
542  if (connect (sd, (struct sockaddr *) &sock6, sizeof (struct sockaddr_in6))
543  == -1)
544  {
545  close (sd);
546  return 0;
547  }
548  bzero (&sock6, sizeof (struct sockaddr_in6));
549  socklen = sizeof (struct sockaddr_in6);
550  if (getsockname (sd, (struct sockaddr *) &sock6, &socklen) == -1)
551  {
552  perror ("getsockname");
553  close (sd);
554  return 0;
555  }
556 
557  src->s6_addr32[0] = sock6.sin6_addr.s6_addr32[0];
558  src->s6_addr32[1] = sock6.sin6_addr.s6_addr32[1];
559  src->s6_addr32[2] = sock6.sin6_addr.s6_addr32[2];
560  src->s6_addr32[3] = sock6.sin6_addr.s6_addr32[3];
561  memcpy (src, &sock6.sin6_addr, sizeof (struct in6_addr));
562  g_debug ("source addrss is %s\n",
563  inet_ntop (AF_INET6, src, name, sizeof (name)));
564  close (sd);
565  }
566  return 1; /* Calling function responsible for checking validity */
567 }
568 
569 int
570 getipv4routes (struct myroute *myroutes, int *numroutes)
571 {
572  struct interface_info *mydevs;
573  int i;
574  int numinterfaces;
575  char buf[1024];
576  char *p, *endptr;
577  char iface[64];
578  FILE *routez;
579  unsigned long dest;
580  struct in_addr inaddr;
581  unsigned long mask;
582  unsigned long ones;
583 
584  /* Dummy socket for ioctl */
585  mydevs = v6_getinterfaces (&numinterfaces);
586 
587  /* Now we must go through several techniques to determine info */
588  routez = fopen ("/proc/net/route", "r");
589 
590  if (routez)
591  {
592  /* OK, linux style /proc/net/route ... we can handle this ... */
593  /* Now that we've got the interfaces, we g0 after the r0ut3Z */
594  if (fgets (buf, sizeof (buf), routez) == NULL) /* Kill the first line */
595  {
596  // /proc/net/route was empty or an error occurred.
597  g_message ("Could not read from /proc/net/route");
598  fclose (routez);
599  return -1;
600  }
601  while (fgets (buf, sizeof (buf), routez))
602  {
603  p = strtok (buf, " \t\n");
604  if (!p)
605  {
606  g_message ("Could not find interface in"
607  " /proc/net/route line");
608  continue;
609  }
610  strncpy (iface, p, sizeof (iface));
611  if ((p = strchr (iface, ':')))
612  {
613  *p = '\0'; /* To support IP aliasing */
614  }
615  p = strtok (NULL, " \t\n");
616  endptr = NULL;
617  dest = strtoul (p, &endptr, 16);
618  g_debug ("ipv4 dest is %s\n", p);
619  if (!endptr || *endptr)
620  {
621  g_message ("Failed to determine Destination from"
622  " /proc/net/route");
623  continue;
624  }
625  inaddr.s_addr = dest;
626  myroutes[*numroutes].dest6.s6_addr32[0] = 0;
627  myroutes[*numroutes].dest6.s6_addr32[1] = 0;
628  myroutes[*numroutes].dest6.s6_addr32[2] = htonl (0xffff);
629  myroutes[*numroutes].dest6.s6_addr32[3] = inaddr.s_addr;
630  for (i = 0; i < 6; i++)
631  {
632  p = strtok (NULL, " \t\n");
633  if (!p)
634  break;
635  }
636  if (!p)
637  {
638  g_message ("Failed to find field %d in"
639  " /proc/net/route",
640  i + 2);
641  continue;
642  }
643  endptr = NULL;
644  mask = strtoul (p, &endptr, 16);
645  ones = 0;
646  i = 0;
647  while (mask & (1 << i++) && i < 32)
648  ones++;
649  myroutes[*numroutes].mask = ones + 96;
650  g_debug ("mask is %lu\n", myroutes[*numroutes].mask);
651  if (!endptr || *endptr)
652  {
653  g_message ("Failed to determine mask from"
654  " /proc/net/route");
655  continue;
656  }
657 
658  g_debug ("#%d: for dev %s, The dest is %lX and the mask is %lX\n",
659  *numroutes, iface, myroutes[*numroutes].dest,
660  myroutes[*numroutes].mask);
661  for (i = 0; i < numinterfaces; i++)
662  if (!strcmp (iface, mydevs[i].name))
663  {
664  myroutes[*numroutes].dev = &mydevs[i];
665  break;
666  }
667  if (i == numinterfaces)
668  g_message (
669  "Failed to find interface %s mentioned in /proc/net/route",
670  iface);
671  (*numroutes)++;
672  if (*numroutes >= MAXROUTES)
673  {
674  g_message ("You seem to have WAY to many routes!");
675  break;
676  }
677  }
678  fclose (routez);
679  return 0;
680  }
681  else
682  return -1;
683 }
684 
685 int
686 getipv6routes (struct myroute *myroutes, int *numroutes)
687 {
688  struct interface_info *mydevs;
689  int i, j;
690  int len;
691  struct in6_addr in6addr;
692  char destaddr[100];
693  int numinterfaces;
694  char buf[1024];
695  char *endptr;
696  FILE *routez;
697  char v6addr[INET6_ADDRSTRLEN];
698  char *token;
699  int cnt;
700 
701  /* Dummy socket for ioctl */
702  mydevs = v6_getinterfaces (&numinterfaces);
703  routez = fopen ("/proc/net/ipv6_route", "r");
704  if (routez)
705  {
706  /* linux style /proc/net/ipv6_route ... we can handle this too... */
707  while (fgets (buf, sizeof (buf), routez) != NULL)
708  {
709  char iface[64];
710 
711  token = strtok (buf, " \t\n");
712  if (token)
713  {
714  g_debug ("first token is %s\n", token);
715  strncpy (destaddr, token, sizeof (destaddr) - 1);
716  len = strlen (destaddr);
717  for (i = 0, j = 0; j < len; j++)
718  {
719  v6addr[i++] = destaddr[j];
720  if (j % 4 == 3)
721  v6addr[i++] = ':';
722  }
723  v6addr[--i] = '\0';
724  g_debug ("ipv6 dest is %s\n", v6addr);
725  if (inet_pton (AF_INET6, v6addr, &in6addr) <= 0)
726  {
727  g_message ("invalid ipv6 addressd");
728  continue;
729  }
730  memcpy (&myroutes[*numroutes].dest6, &in6addr,
731  sizeof (struct in6_addr));
732  }
733  token = strtok (NULL, " \t\n");
734  if (token)
735  {
736  endptr = NULL;
737  myroutes[*numroutes].mask = strtoul (token, &endptr, 16);
738  }
739  cnt = 7;
740  while (cnt--)
741  {
742  token = strtok (NULL, " \t\n");
743  if (!token)
744  g_message ("getipv6routes error");
745  }
746 
747  bzero (iface, sizeof (iface));
748  token = strtok (NULL, " \t\n");
749  if (token)
750  strncpy (iface, token, sizeof (iface) - 1);
751  for (i = 0; i < numinterfaces; i++)
752  if (!strcmp (iface, mydevs[i].name)
753  && !IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
754  {
755  myroutes[*numroutes].dev = &mydevs[i];
756  break;
757  }
758  if (i == numinterfaces)
759  g_message (
760  "Failed to find interface %s mentioned in /proc/net/route\n",
761  iface);
762  (*numroutes)++;
763  if (*numroutes >= MAXROUTES)
764  {
765  g_message ("You seem to have WAY to many routes!");
766  break;
767  }
768  }
769  fclose (routez);
770  return 0;
771  }
772  else
773  {
774  g_message ("Didn't find IPv6 routes");
775  return -1;
776  }
777 }
778 
788 char *
789 v6_routethrough (struct in6_addr *dest, struct in6_addr *source)
790 {
791  static int initialized = 0;
792  int i;
793  struct in6_addr addy;
794  static enum {
795  procroutetechnique,
796  connectsockettechnique,
797  guesstechnique
798  } technique = procroutetechnique;
799  struct interface_info *mydevs;
800  static struct myroute myroutes[MAXROUTES];
801  int numinterfaces = 0;
802  static int numroutes = 0;
803  struct in6_addr in6addr;
804  struct in6_addr src;
805 
806  if (!dest)
807  {
808  g_message ("ipaddr2devname passed a NULL dest address");
809  return NULL;
810  }
811 
812  if (IN6_IS_ADDR_V4MAPPED (dest))
813  gvm_source_addr_as_addr6 (&src);
814  else
815  gvm_source_addr6 (&src);
816 
817  if (!initialized)
818  {
819  /* Dummy socket for ioctl */
820  initialized = 1;
821  mydevs = v6_getinterfaces (&numinterfaces);
822  if (IN6_IS_ADDR_V4MAPPED (dest))
823  {
824  if (getipv4routes (myroutes, &numroutes) < 0)
825  technique = connectsockettechnique;
826  }
827  else
828  {
829  if (getipv6routes (myroutes, &numroutes) < 0)
830  technique = connectsockettechnique;
831  }
832  }
833  else
834  {
835  mydevs = v6_getinterfaces (&numinterfaces);
836  }
837  /* WHEW, that takes care of initializing, now we have the easy job of
838  finding which route matches */
839  if (v6_islocalhost (dest))
840  {
841  if (source)
842  {
843  if (IN6_IS_ADDR_V4MAPPED (source))
844  {
845  source->s6_addr32[0] = 0;
846  source->s6_addr32[1] = 0;
847  source->s6_addr32[2] = htonl (0xffff);
848  source->s6_addr32[3] = htonl (0x7F000001);
849  }
850  else
851  {
852  source->s6_addr32[0] = 0;
853  source->s6_addr32[1] = 0;
854  source->s6_addr32[2] = 0;
855  source->s6_addr32[3] = htonl (1);
856  }
857  }
858  /* Now we find the localhost interface name, assuming 127.0.0.1
859  or ::1 is localhost (it damn well better be!)... */
860  for (i = 0; i < numinterfaces; i++)
861  {
862  if (IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
863  {
864  if (mydevs[i].addr6.s6_addr32[3] == htonl (0x7F000001))
865  return mydevs[i].name;
866  }
867  else
868  {
869  if (IN6_ARE_ADDR_EQUAL (&in6addr_any, &mydevs[i].addr6))
870  return mydevs[i].name;
871  }
872  }
873  return NULL;
874  }
875 
876  if (technique == procroutetechnique)
877  {
878  for (i = 0; i < numroutes; i++)
879  {
880  char addr1[INET6_ADDRSTRLEN];
881  char addr2[INET6_ADDRSTRLEN];
882 
883  memcpy (&in6addr, dest, sizeof (struct in6_addr));
884  ipv6addrmask (&in6addr, myroutes[i].mask);
885  g_debug (
886  "comparing addresses %s and %s\n",
887  inet_ntop (AF_INET6, &in6addr, addr1, sizeof (addr1)),
888  inet_ntop (AF_INET6, &myroutes[i].dest6, addr2, sizeof (addr2)));
889  if (IN6_ARE_ADDR_EQUAL (&in6addr, &myroutes[i].dest6))
890  {
891  if (source)
892  {
893  if (!IN6_ARE_ADDR_EQUAL (&src, &in6addr_any))
894  memcpy (source, &src, sizeof (struct in6_addr));
895  else
896  {
897  if (myroutes[i].dev != NULL)
898  {
899  g_debug ("copying address %s\n",
900  inet_ntop (AF_INET6, &myroutes[i].dev->addr6,
901  addr1, sizeof (addr1)));
902  g_debug ("dev name is %s\n", myroutes[i].dev->name);
903  memcpy (source, &myroutes[i].dev->addr6,
904  sizeof (struct in6_addr));
905  }
906  }
907  }
908  return myroutes[i].dev->name;
909  }
910  technique = connectsockettechnique;
911  }
912  }
913  if (technique == connectsockettechnique)
914  {
915  if (!v6_getsourceip (&addy, dest))
916  return NULL;
917  if (IN6_ARE_ADDR_EQUAL (&addy, &in6addr))
918  {
919  struct hostent *myhostent = NULL;
920  char myname[MAXHOSTNAMELEN + 1];
921 
922  myhostent = gethostbyname (myname);
923  if (gethostname (myname, MAXHOSTNAMELEN) || !myhostent)
924  g_message ("Cannot get hostname!");
925  else if (myhostent->h_addrtype == AF_INET)
926  {
927  addy.s6_addr32[0] = 0;
928  addy.s6_addr32[1] = 0;
929  addy.s6_addr32[2] = htonl (0xffff);
930  memcpy (&addy.s6_addr32[0], myhostent->h_addr_list[0],
931  sizeof (struct in6_addr));
932  }
933  else
934  memcpy (&addy, myhostent->h_addr_list[0], sizeof (struct in6_addr));
935  }
936 
937  /* Now we insure this claimed address is a real interface ... */
938  for (i = 0; i < numinterfaces; i++)
939  {
940  char addr1[INET6_ADDRSTRLEN];
941  char addr2[INET6_ADDRSTRLEN];
942 
943  g_debug (
944  "comparing addresses %s and %s\n",
945  inet_ntop (AF_INET6, &mydevs[i].addr6, addr1, sizeof (addr1)),
946  inet_ntop (AF_INET6, &addy, addr2, sizeof (addr2)));
947  if (IN6_ARE_ADDR_EQUAL (&mydevs[i].addr6, &addy))
948  {
949  if (source)
950  {
951  memcpy (source, &addy, sizeof (struct in6_addr));
952  }
953  return mydevs[i].name;
954  }
955  }
956  return NULL;
957  }
958  else
959  g_message ("%s: Provided technique is neither proc route nor"
960  " connect socket",
961  __FUNCTION__);
962  return NULL;
963 }
964 
974 char *
975 routethrough (struct in_addr *dest, struct in_addr *source)
976 {
977  static int initialized = 0;
978  int i;
979  char buf[10240];
980  struct interface_info *mydevs;
981  static struct myroute
982  {
983  struct interface_info *dev;
984  unsigned long mask;
985  unsigned long dest;
986  } myroutes[MAXROUTES];
987  int numinterfaces = 0;
988  char *p, *endptr;
989  char iface[64];
990  static int numroutes = 0;
991  FILE *routez;
992  long match = -1;
993  unsigned long bestmatch = 0;
994 
995  struct in_addr src;
996 
997  gvm_source_addr (&src);
998  if (!dest)
999  {
1000  g_message ("ipaddr2devname passed a NULL dest address");
1001  return NULL;
1002  }
1003 
1004  if (!initialized)
1005  {
1006  /* Dummy socket for ioctl */
1007  initialized = 1;
1008  mydevs = getinterfaces (&numinterfaces);
1009  if (!mydevs)
1010  return NULL;
1011 
1012  routez = fopen ("/proc/net/route", "r");
1013  if (routez)
1014  {
1015  /* OK, linux style /proc/net/route ... we can handle this ... */
1016  /* Now that we've got the interfaces, we g0 after the r0ut3Z */
1017  if (fgets (buf, sizeof (buf), routez)
1018  == NULL) /* Kill the first line */
1019  g_message ("Could not read from /proc/net/route");
1020  while (fgets (buf, sizeof (buf), routez))
1021  {
1022  p = strtok (buf, " \t\n");
1023  if (!p)
1024  {
1025  g_message ("Could not find interface in"
1026  " /proc/net/route line");
1027  continue;
1028  }
1029  strncpy (iface, p, sizeof (iface));
1030  if ((p = strchr (iface, ':')))
1031  {
1032  *p = '\0'; /* To support IP aliasing */
1033  }
1034  p = strtok (NULL, " \t\n");
1035  endptr = NULL;
1036  myroutes[numroutes].dest = strtoul (p, &endptr, 16);
1037  if (!endptr || *endptr)
1038  {
1039  g_message (
1040  "Failed to determine Destination from /proc/net/route");
1041  continue;
1042  }
1043  for (i = 0; i < 6; i++)
1044  {
1045  p = strtok (NULL, " \t\n");
1046  if (!p)
1047  break;
1048  }
1049  if (!p)
1050  {
1051  g_message ("Failed to find field %d in"
1052  " /proc/net/route",
1053  i + 2);
1054  continue;
1055  }
1056  endptr = NULL;
1057  myroutes[numroutes].mask = strtoul (p, &endptr, 16);
1058  if (!endptr || *endptr)
1059  {
1060  g_message ("Failed to determine mask"
1061  " from /proc/net/route");
1062  continue;
1063  }
1064 
1065  g_debug ("#%d: for dev %s, The dest is %lX and the mask is %lX\n",
1066  numroutes, iface, myroutes[numroutes].dest,
1067  myroutes[numroutes].mask);
1068  for (i = 0; i < numinterfaces; i++)
1069  if (!strcmp (iface, mydevs[i].name))
1070  {
1071  myroutes[numroutes].dev = &mydevs[i];
1072  break;
1073  }
1074  if (i == numinterfaces)
1075  g_message (
1076  "Failed to find interface %s mentioned in /proc/net/route",
1077  iface);
1078  numroutes++;
1079  if (numroutes >= MAXROUTES)
1080  {
1081  g_message ("You seem to have WAY to many routes!");
1082  break;
1083  }
1084  }
1085  fclose (routez);
1086  }
1087  else
1088  {
1089  g_message ("Could not read from /proc/net/route");
1090  return NULL;
1091  }
1092  }
1093  else
1094  mydevs = getinterfaces (&numinterfaces);
1095  /* WHEW, that takes care of initializing, now we have the easy job of
1096  finding which route matches */
1097  if (mydevs && islocalhost (dest))
1098  {
1099  if (source)
1100  source->s_addr = htonl (0x7F000001);
1101  /* Now we find the localhost interface name, assuming 127.0.0.1 is
1102  localhost (it damn well better be!)... */
1103  for (i = 0; i < numinterfaces; i++)
1104  {
1105  if (mydevs[i].addr.s_addr == htonl (0x7F000001))
1106  {
1107  return mydevs[i].name;
1108  }
1109  }
1110  return NULL;
1111  }
1112 
1113  for (i = 0; i < numroutes; i++)
1114  {
1115  if ((dest->s_addr & myroutes[i].mask) == myroutes[i].dest
1116  && myroutes[i].mask >= bestmatch)
1117  {
1118  if (source)
1119  {
1120  if (src.s_addr != INADDR_ANY)
1121  source->s_addr = src.s_addr;
1122  else
1123  source->s_addr = myroutes[i].dev->addr.s_addr;
1124  }
1125  match = i;
1126  bestmatch = myroutes[i].mask;
1127  }
1128  }
1129  if (match != -1)
1130  return myroutes[match].dev->name;
1131  return NULL;
1132 }
getipv6routes
int getipv6routes(struct myroute *myroutes, int *numroutes)
Definition: pcap.c:686
bpf_share.h
Header file for module bpf_share.
getipv4routes
int getipv4routes(struct myroute *myroutes, int *numroutes)
Definition: pcap.c:570
v6_getinterfaces
struct interface_info * v6_getinterfaces(int *howmany)
Definition: pcap.c:335
myroute::mask
unsigned long mask
Definition: pcap.c:62
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:789
interface_info::addr6
struct in6_addr addr6
Definition: pcap.c:54
getinterfaces
struct interface_info * getinterfaces(int *howmany)
Definition: pcap.c:410
v6_ipaddr2devname
int v6_ipaddr2devname(char *dev, int sz, struct in6_addr *addr)
Definition: pcap.c:173
name
const char * name
Definition: nasl_init.c:377
v6_is_local_ip
int v6_is_local_ip(struct in6_addr *addr)
Definition: pcap.c:117
support.h
Support macros for special platforms.
v6_getsourceip
int v6_getsourceip(struct in6_addr *src, struct in6_addr *dst)
Definition: pcap.c:478
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:268
get_datalink_size
int get_datalink_size(int datalink)
Definition: pcap.c:295
MAXROUTES
#define MAXROUTES
Definition: pcap.c:42
ipv6addrmask
static void ipv6addrmask(struct in6_addr *in6addr, int mask)
Definition: pcap.c:74
myroute::dev
struct interface_info * dev
Definition: pcap.c:60
interface_info::name
char name[64]
Definition: pcap.c:52
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:231
network.h
Header file for module network.
myroute
Definition: pcap.c:58
interface_info
Definition: pcap.c:50
interface_info::addr
struct in_addr addr
Definition: pcap.c:53
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:975
interface_info::mask
struct in6_addr mask
Definition: pcap.c:55
myroute::dest
unsigned long dest
Definition: pcap.c:63
ipaddr2devname
int ipaddr2devname(char *dev, int sz, struct in_addr *addr)
Definition: pcap.c:204
myroute::dest6
struct in6_addr dest6
Definition: pcap.c:61