OpenVAS Libraries  9.0.3
pcap.c
Go to the documentation of this file.
1 /* OpenVAS Libraries
2  * Copyright (C) 1999 Renaud Deraison
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <netinet/in.h>
20 #include <resolv.h>
21 #include <pcap.h>
22 #include <net/if.h>
23 #include <arpa/inet.h>
24 #include <sys/ioctl.h>
25 #include <netdb.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <ifaddrs.h>
31 
32 
33 #include "bpf_share.h"
34 #include "pcap_openvas.h"
35 #include "openvas_logging.h"
36 #include "network.h"
37 #include "support.h"
38 
39 #define MAXROUTES 1024
40 
41 
43 {
44  char name[64];
45  struct in_addr addr;
46  struct in6_addr addr6;
47  struct in6_addr mask;
48 };
49 
50 struct myroute
51 {
53  struct in6_addr dest6;
54  unsigned long mask;
55  unsigned long dest;
56 };
57 
58 struct interface_info *getinterfaces (int *howmany);
59 struct interface_info *v6_getinterfaces (int *howmany);
60 int getipv6routes (struct myroute *myroutes, int *numroutes);
61 
62 static void
63 ipv6addrmask (struct in6_addr *in6addr, int mask)
64 {
65  int wordmask;
66  int word;
67  uint32_t *ptr;
68  uint32_t addr;
69 
70  word = mask / 32;
71  wordmask = mask % 32;
72  ptr = (uint32_t *) in6addr;
73  switch (word)
74  {
75  case 0:
76  ptr[1] = ptr[2] = ptr[3] = 0;
77  addr = ptr[0];
78  addr = ntohl (addr) >> (32 - wordmask);
79  addr = htonl (addr << (32 - wordmask));
80  ptr[0] = addr;
81  break;
82  case 1:
83  ptr[2] = ptr[3] = 0;
84  addr = ptr[1];
85  addr = ntohl (addr) >> (32 - wordmask);
86  addr = htonl (addr << (32 - wordmask));
87  ptr[1] = addr;
88  break;
89  case 2:
90  ptr[3] = 0;
91  addr = ptr[2];
92  addr = ntohl (addr) >> (32 - wordmask);
93  addr = htonl (addr << (32 - wordmask));
94  ptr[2] = addr;
95  break;
96  case 3:
97  addr = ptr[3];
98  addr = ntohl (addr) >> (32 - wordmask);
99  addr = htonl (addr << (32 - wordmask));
100  ptr[3] = addr;
101  break;
102  }
103 }
104 
105 int
106 v6_is_local_ip (struct in6_addr *addr)
107 {
108  int ifaces;
109  struct interface_info *ifs;
110  int i;
111  static struct myroute myroutes[MAXROUTES];
112  int numroutes = 0;
113  struct in6_addr in6addr;
114 #if TCPIP_DEBUGGING
115  char addr1[INET6_ADDRSTRLEN];
116  char addr2[INET6_ADDRSTRLEN];
117 #endif
118 
119  if ((ifs = v6_getinterfaces (&ifaces)) == NULL)
120  return -1;
121 
122  if (IN6_IS_ADDR_V4MAPPED (addr))
123  {
124  for (i = 0; i < ifaces; i++)
125  {
126  bpf_u_int32 net, mask;
127  char errbuf[PCAP_ERRBUF_SIZE];
128  pcap_lookupnet (ifs[i].name, &net, &mask, errbuf);
129  if ((net & mask) == (addr->s6_addr32[3] & mask))
130  return 1;
131  }
132  }
133  else
134  {
135  if (IN6_IS_ADDR_LINKLOCAL (addr))
136  return 1;
137  if (IN6_IS_ADDR_LOOPBACK (addr))
138  return 1;
139  if (getipv6routes (myroutes, &numroutes) == 0)
140  {
141  for (i = 0; i < numroutes; i++)
142  {
143  memcpy (&in6addr, addr, sizeof (struct in6_addr));
144  ipv6addrmask (&in6addr, myroutes[i].mask);
145 #if TCPIP_DEBUGGING
146  printf ("comparing addresses %s and %s\n",
147  inet_ntop (AF_INET6, &in6addr, addr1, sizeof (addr1)),
148  inet_ntop (AF_INET6, &myroutes[i].dest6, addr2,
149  sizeof (addr2)));
150 #endif
151  if (IN6_ARE_ADDR_EQUAL (&in6addr, &myroutes[i].dest6))
152  {
153  return 1;
154  }
155  }
156  }
157  }
158  return 0;
159 }
160 
170 int
171 v6_get_mac_addr (struct in6_addr *addr, char **mac)
172 {
173  int soc;
174  struct sockaddr_in soca;
175  struct sockaddr_in6 soca6;
176  int bpf;
177  struct in6_addr me;
178  struct in_addr inaddr;
179  char *iface = v6_routethrough (addr, &me);
180  char filter[255];
181  char *src_host, *dst_host;
182  unsigned char *packet;
183  int len;
184  char hostname[INET6_ADDRSTRLEN];
185 
186  if (IN6_IS_ADDR_V4MAPPED (addr))
187  {
188  soc = socket (AF_INET, SOCK_DGRAM, 0);
189  *mac = NULL;
190  if (soc < 0)
191  return -1;
192 
193  inaddr.s_addr = me.s6_addr32[3];
194  src_host = g_strdup (inet_ntoa (inaddr));
195  inaddr.s_addr = addr->s6_addr32[3];
196  dst_host = g_strdup (inet_ntoa (inaddr));
197  snprintf (filter, sizeof (filter)-1, "ip and (src host %s and dst host %s)",
198  src_host, dst_host);
199  g_free (src_host);
200  g_free (dst_host);
201 
202  bpf = bpf_open_live (iface, filter);
203  if (bpf < 0)
204  {
205  close (soc);
206  return -1;
207  }
208 
209  /*
210  * We only deal with ethernet
211  */
212  if (bpf_datalink (bpf) != DLT_EN10MB)
213  {
214  bpf_close (bpf);
215  close (soc);
216  return -1;
217  }
218 
219 
220  soca.sin_addr.s_addr = addr->s6_addr32[3];
221  soca.sin_port = htons (9); /* or whatever */
222  soca.sin_family = AF_INET;
223  if (sendto (soc, NULL, 0, 0, (struct sockaddr *) &soca, sizeof (soca)) !=
224  0)
225  {
226  bpf_close (bpf);
227  close (soc);
228  return -1;
229  }
230  }
231  else
232  {
233  soc = socket (AF_INET6, SOCK_DGRAM, 0);
234  *mac = NULL;
235  if (soc < 0)
236  return -1;
237  src_host =
238  g_strdup (inet_ntop (AF_INET6, &me, hostname, sizeof (hostname)));
239  dst_host =
240  g_strdup (inet_ntop (AF_INET6, addr, hostname, sizeof (hostname)));
241  snprintf (filter, sizeof (filter)-1,
242  "ip6 and (src host %s and dst host %s)", src_host, dst_host);
243  g_free (src_host);
244  g_free (dst_host);
245 
246 
247  bpf = bpf_open_live (iface, filter);
248  if (bpf < 0)
249  {
250  close (soc);
251  return -1;
252  }
253 
254  /* We only deal with ethernet. */
255  if (bpf_datalink (bpf) != DLT_EN10MB)
256  {
257  bpf_close (bpf);
258  close (soc);
259  return -1;
260  }
261 
262 
263  memcpy (&soca6.sin6_addr, addr, sizeof (struct in6_addr));
264  soca6.sin6_port = htons (9); /* or whatever */
265  soca6.sin6_family = AF_INET6;
266  if (sendto (soc, NULL, 0, 0, (struct sockaddr *) &soca6, sizeof (soca6))
267  != 0)
268  {
269  bpf_close (bpf);
270  close (soc);
271  return -1;
272  }
273  }
274 
275  packet = (unsigned char *) bpf_next (bpf, &len);
276  if (packet)
277  {
278  if (len >= get_datalink_size (bpf_datalink (bpf)))
279  {
280  int i;
281  for (i = 0; i < 6; i++)
282  if (packet[i] != 0xFF)
283  break;
284 
285  if (i == 6)
286  {
287  bpf_close (bpf);
288  close (soc);
289  return 1;
290  }
291 
292  *mac = g_malloc0 (23);
293  snprintf (*mac, 22, "%.2x.%.2x.%.2x.%.2x.%.2x.%.2x",
294  (unsigned char) packet[0], (unsigned char) packet[1],
295  (unsigned char) packet[2], (unsigned char) packet[3],
296  (unsigned char) packet[4], (unsigned char) packet[5]);
297  bpf_close (bpf);
298  close (soc);
299  return 0;
300  }
301  }
302  else
303  {
304  bpf_close (bpf);
305  close (soc);
306  return 1;
307  }
308  return 1; /* keep the compiler happy */
309 }
310 
311 
312 /*
313  * Taken straight out of Fyodor's Nmap
314  */
315 int
316 v6_ipaddr2devname (char *dev, int sz, struct in6_addr *addr)
317 {
318  struct interface_info *mydevs;
319  int numdevs;
320  int i;
321  mydevs = v6_getinterfaces (&numdevs);
322 #if TCPIP_DEBUGGING
323  char addr1[INET6_ADDRSTRLEN];
324  char addr2[INET6_ADDRSTRLEN];
325 #endif
326 
327  if (!mydevs)
328  return -1;
329 
330  for (i = 0; i < numdevs; i++)
331  {
332 #if TCPIP_DEBUGGING
333  printf ("comparing addresses %s and %s\n",
334  inet_ntop (AF_INET6, addr, addr1, sizeof (addr1)),
335  inet_ntop (AF_INET6, &mydevs[i].addr6, addr2, sizeof (addr2)));
336 #endif
337  if (IN6_ARE_ADDR_EQUAL (addr, &mydevs[i].addr6))
338  {
339  dev[sz - 1] = '\0';
340  strncpy (dev, mydevs[i].name, sz);
341  return 0;
342  }
343  }
344  return -1;
345 }
346 
347 /*
348  * Taken straight out of Fyodor's Nmap
349  */
350 int
351 ipaddr2devname (char *dev, int sz, struct in_addr *addr)
352 {
353  struct interface_info *mydevs;
354  int numdevs;
355  int i;
356  mydevs = getinterfaces (&numdevs);
357 
358  if (!mydevs)
359  return -1;
360 
361  for (i = 0; i < numdevs; i++)
362  {
363  if (addr->s_addr == mydevs[i].addr.s_addr)
364  {
365  dev[sz - 1] = '\0';
366  strncpy (dev, mydevs[i].name, sz);
367  return 0;
368  }
369  }
370  return -1;
371 }
372 
377 int
378 v6_islocalhost (struct in6_addr *addr)
379 {
380  char dev[128];
381 
382  if (addr == NULL)
383  return -1;
384 
385  if (IN6_IS_ADDR_V4MAPPED (addr))
386  {
387  /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
388  probably localhost */
389  if ((addr->s6_addr32[3] & htonl (0xFF000000)) == htonl (0x7F000000))
390  return 1;
391 
392  if (!addr->s6_addr32[3])
393  return 1;
394  }
395 
396  if (IN6_IS_ADDR_LOOPBACK (addr))
397  return 1;
398 
399  /* If it is the same addy as a local interface, then it is
400  probably localhost */
401 
402  if (v6_ipaddr2devname (dev, sizeof (dev), addr) != -1)
403  return 1;
404 
405  /* OK, so to a first approximation, this addy is probably not
406  localhost */
407  return 0;
408 }
409 
414 int
415 islocalhost (struct in_addr *addr)
416 {
417  char dev[128];
418 
419  if (addr == NULL)
420  return -1;
421 
422  /* If it is 0.0.0.0 or starts with 127.0.0.1 then it is
423  probably localhost */
424  if ((addr->s_addr & htonl (0xFF000000)) == htonl (0x7F000000))
425  return 1;
426 
427  if (!addr->s_addr)
428  return 1;
429 
430  /* If it is the same addy as a local interface, then it is
431  probably localhost */
432 
433  if (ipaddr2devname (dev, sizeof (dev), addr) != -1)
434  return 1;
435 
436  /* OK, so to a first approximation, this addy is probably not
437  localhost */
438  return 0;
439 }
440 
441 int
442 get_datalink_size (int datalink)
443 {
444  int offset = -1;
445  switch (datalink)
446  {
447  case DLT_EN10MB:
448  offset = 14;
449  break;
450  case DLT_IEEE802:
451  offset = 22;
452  break;
453  case DLT_NULL:
454  offset = 4;
455  break;
456  case DLT_SLIP:
457 #if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
458  offset = 16;
459 #else
460  offset = 24; /* Anyone use this??? */
461 #endif
462  break;
463  case DLT_PPP:
464 #if (FREEBSD || OPENBSD || NETBSD || BSDI || DARWIN)
465  offset = 4;
466 #else
467 #ifdef SOLARIS
468  offset = 8;
469 #else
470  offset = 24; /* Anyone use this? */
471 #endif /* ifdef solaris */
472 #endif /* if freebsd || openbsd || netbsd || bsdi */
473  break;
474  case DLT_RAW:
475  offset = 0;
476  break;
477  }
478  return (offset);
479 }
480 
481 int
482 get_random_bytes (void *buf, int numbytes)
483 {
484  static char bytebuf[2048];
485  static char badrandomwarning = 0;
486  static int bytesleft = 0;
487  int res;
488  int tmp;
489  struct timeval tv;
490  FILE *fp = NULL;
491  short *iptr;
492 
493  if (numbytes < 0 || numbytes > 0xFFFF)
494  return -1;
495 
496  if (bytesleft == 0)
497  {
498  fp = fopen ("/dev/urandom", "r");
499  if (!fp)
500  fp = fopen ("/dev/random", "r");
501  if (fp)
502  {
503  res = fread (bytebuf, 1, sizeof (bytebuf), fp);
504  if (res != sizeof (bytebuf))
505  {
506  fclose (fp);
507  fp = NULL;
508  }
509  bytesleft = sizeof (bytebuf);
510  }
511  if (!fp)
512  {
513  unsigned int i;
514 
515  if (badrandomwarning == 0)
516  {
517  badrandomwarning++;
518  }
519  /* Seed our random generator */
520  gettimeofday (&tv, NULL);
521  srand ((tv.tv_sec ^ tv.tv_usec) ^ getpid ());
522 
523  for (i = 0; i < sizeof (bytebuf) / sizeof (short); i++)
524  {
525  iptr = (short *) ((char *) bytebuf + i * sizeof (short));
526  *iptr = rand ();
527  }
528  bytesleft = (sizeof (bytebuf) / sizeof (short)) * sizeof (short);
529  /* ^^^^^^^^^^^^^^^not as meaningless as it looks */
530  }
531  else
532  fclose (fp);
533  }
534  if (numbytes <= bytesleft)
535  { /* we can cover it */
536  memcpy (buf, bytebuf + (sizeof (bytebuf) - bytesleft), numbytes);
537  bytesleft -= numbytes;
538  return 0;
539  }
540 
541  /* We don't have enough */
542  memcpy (buf, bytebuf + (sizeof (bytebuf) - bytesleft), bytesleft);
543  tmp = bytesleft;
544  bytesleft = 0;
545  return get_random_bytes ((char *) buf + tmp, numbytes - tmp);
546 }
547 
548 struct interface_info *
549 v6_getinterfaces (int *howmany)
550 {
551  struct sockaddr_in *saddr;
552  struct sockaddr_in6 *s6addr;
553  static struct interface_info mydevs[1024];
554  int numinterfaces = 0;
555  struct ifaddrs *ifaddr, *ifa;
556  int family;
557 
558  if (getifaddrs (&ifaddr) == -1)
559  {
560  perror ("getifaddrs");
561  }
562  else
563  {
564  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
565  {
566  if (ifa->ifa_addr == NULL)
567  continue;
568 
569  family = ifa->ifa_addr->sa_family;
570  if (family == AF_INET)
571  {
572  memcpy (mydevs[numinterfaces].name, ifa->ifa_name,
573  strlen (ifa->ifa_name));
574  saddr = (struct sockaddr_in *) ifa->ifa_addr;
575  mydevs[numinterfaces].addr6.s6_addr32[0] = 0;
576  mydevs[numinterfaces].addr6.s6_addr32[1] = 0;
577  mydevs[numinterfaces].addr6.s6_addr32[2] = htonl (0xffff);
578  mydevs[numinterfaces].addr6.s6_addr32[3] = saddr->sin_addr.s_addr;
579  saddr = (struct sockaddr_in *) ifa->ifa_netmask;
580  mydevs[numinterfaces].mask.s6_addr32[0] = 0;
581  mydevs[numinterfaces].mask.s6_addr32[1] = 0;
582  mydevs[numinterfaces].mask.s6_addr32[2] = htonl (0xffff);
583  mydevs[numinterfaces].mask.s6_addr32[3] = saddr->sin_addr.s_addr;
584 #ifdef TCPIP_DEBUGGING
585  printf ("interface name is %s\n", ifa->ifa_name);
586  printf ("\tAF_INET family\n");
587  printf ("\taddress is %s\n", inet_ntoa (saddr->sin_addr));
588  printf ("\tnetmask is %s\n", inet_ntoa (saddr->sin_addr));
589 #endif
590  numinterfaces++;
591  }
592  else if (family == AF_INET6)
593  {
594  memcpy (mydevs[numinterfaces].name, ifa->ifa_name,
595  strlen (ifa->ifa_name));
596  s6addr = (struct sockaddr_in6 *) ifa->ifa_addr;
597  memcpy (&(mydevs[numinterfaces].addr6),
598  (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
599  s6addr = (struct sockaddr_in6 *) ifa->ifa_netmask;
600  memcpy (&(mydevs[numinterfaces].mask),
601  (char *) &(s6addr->sin6_addr), sizeof (struct in6_addr));
602  numinterfaces++;
603 #ifdef TCPIP_DEBUGGING
604  printf ("\tAF_INET6 family\n");
605  printf ("interface name is %s\n", ifa->ifa_name);
606  printf ("\taddress is %s\n",
607  inet_ntop (AF_INET6, &s6addr->sin6_addr, ipaddr,
608  sizeof (ipaddr)));
609 #endif
610  }
611  else
612  {
613 #ifdef TCPIP_DEBUGGING
614  printf ("\tfamily is %d\n", ifa->ifa_addr->sa_family);
615 #endif
616  }
617  }
618  *howmany = numinterfaces;
619 
620  freeifaddrs (ifaddr);
621  }
622  return mydevs;
623 }
624 
629 struct interface_info *
630 getinterfaces (int *howmany)
631 {
632  static struct interface_info mydevs[1024];
633  int numinterfaces = 0;
634  int sd;
635  int len;
636  char *p;
637  char buf[10240];
638  struct ifconf ifc;
639  struct ifreq *ifr;
640  struct sockaddr_in *sin;
641  char *bufp;
642 
643  /* Dummy socket for ioctl. */
644  sd = socket (AF_INET, SOCK_DGRAM, 0);
645  bzero (buf, sizeof (buf));
646  if (sd < 0)
647  log_legacy_write ("socket in getinterfaces");
648 
649  ifc.ifc_len = sizeof (buf);
650  ifc.ifc_buf = buf;
651  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
652  log_legacy_write ("Failed to determine your configured interfaces!");
653 
654  close (sd);
655  if (ifc.ifc_len == 0)
657  ("getinterfaces: SIOCGIFCONF claims you have no network interfaces!");
658 
659  len = sizeof (struct ifmap);
660 
661  for (bufp = buf; bufp && *bufp && (bufp < (buf + ifc.ifc_len));
662  bufp += sizeof (ifr->ifr_name) + len)
663  {
664  ifr = (struct ifreq *) bufp;
665  sin = (struct sockaddr_in *) &ifr->ifr_addr;
666  memcpy (&(mydevs[numinterfaces].addr), (char *) &(sin->sin_addr),
667  sizeof (struct in_addr));
668  /* In case it is a stinkin' alias */
669  if ((p = strchr (ifr->ifr_name, ':')))
670  *p = '\0';
671  strncpy (mydevs[numinterfaces].name, ifr->ifr_name, 63);
672  mydevs[numinterfaces].name[63] = '\0';
673  numinterfaces++;
674  if (numinterfaces == 1023)
675  {
677  ("You seem to have more than 1023 network interfaces."
678  " Things may not work right.");
679  break;
680  }
681  mydevs[numinterfaces].name[0] = '\0';
682  }
683 
684  // If output parameter given, set value
685  if (howmany)
686  *howmany = numinterfaces;
687 
688  return mydevs;
689 }
690 
691 int
692 v6_getsourceip (struct in6_addr *src, struct in6_addr *dst)
693 {
694  int sd;
695  struct sockaddr_in sock;
696  struct sockaddr_in6 sock6;
697  unsigned int socklen;
698  unsigned short p1;
699 
700 #ifdef TCPIP_DEBUGGING
701  char name[INET6_ADDRSTRLEN];
702 #endif
703 
704  get_random_bytes (&p1, 2);
705  if (p1 < 5000)
706  p1 += 5000;
707 
708  if (IN6_IS_ADDR_V4MAPPED (dst))
709  {
710  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
711  {
712  perror ("Socket troubles");
713  return 0;
714  }
715  sock.sin_family = AF_INET;
716  sock.sin_addr.s_addr = dst->s6_addr32[3];
717  sock.sin_port = htons (p1);
718  if (connect (sd, (struct sockaddr *) &sock, sizeof (struct sockaddr_in))
719  == -1)
720  {
721  close (sd);
722  return 0;
723  }
724  bzero (&sock, sizeof (struct sockaddr_in));
725  socklen = sizeof (struct sockaddr_in);
726  if (getsockname (sd, (struct sockaddr *) &sock, &socklen) == -1)
727  {
728  perror ("getsockname");
729  close (sd);
730  return 0;
731  }
732 
733 
734  src->s6_addr32[0] = 0;
735  src->s6_addr32[1] = 0;
736  src->s6_addr32[2] = htonl (0xffff);
737  src->s6_addr32[3] = sock.sin_addr.s_addr;
738 #ifdef TCPIP_DEBUGGING
739  printf ("source addrss is %s\n",
740  inet_ntop (AF_INET6, src, name, sizeof (name)));
741 #endif
742  close (sd);
743  }
744  else
745  {
746  if ((sd = socket (AF_INET6, SOCK_DGRAM, 0)) == -1)
747  {
748  perror ("Socket troubles");
749  return 0;
750  }
751  sock6.sin6_family = AF_INET6;
752  sock6.sin6_addr.s6_addr32[0] = dst->s6_addr32[0];
753  sock6.sin6_addr.s6_addr32[1] = dst->s6_addr32[1];
754  sock6.sin6_addr.s6_addr32[2] = dst->s6_addr32[2];
755  sock6.sin6_addr.s6_addr32[3] = dst->s6_addr32[3];
756  sock6.sin6_port = htons (p1);
757  if (connect (sd, (struct sockaddr *) &sock6, sizeof (struct sockaddr_in6))
758  == -1)
759  {
760  close (sd);
761  return 0;
762  }
763  bzero (&sock6, sizeof (struct sockaddr_in6));
764  socklen = sizeof (struct sockaddr_in6);
765  if (getsockname (sd, (struct sockaddr *) &sock6, &socklen) == -1)
766  {
767  perror ("getsockname");
768  close (sd);
769  return 0;
770  }
771 
772  src->s6_addr32[0] = sock6.sin6_addr.s6_addr32[0];
773  src->s6_addr32[1] = sock6.sin6_addr.s6_addr32[1];
774  src->s6_addr32[2] = sock6.sin6_addr.s6_addr32[2];
775  src->s6_addr32[3] = sock6.sin6_addr.s6_addr32[3];
776  memcpy (src, &sock6.sin6_addr, sizeof (struct in6_addr));
777 #ifdef TCPIP_DEBUGGING
778  printf ("source addrss is %s\n",
779  inet_ntop (AF_INET6, src, name, sizeof (name)));
780 #endif
781  close (sd);
782  }
783  return 1; /* Calling function responsible for checking validity */
784 }
785 
786 int
787 getsourceip (struct in_addr *src, struct in_addr *dst)
788 {
789  int sd;
790  struct sockaddr_in sock;
791  unsigned int socklen = sizeof (struct sockaddr_in);
792  unsigned short p1;
793 
794  get_random_bytes (&p1, 2);
795  if (p1 < 5000)
796  p1 += 5000;
797 
798  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
799  {
800  perror ("Socket troubles");
801  return 0;
802  }
803  sock.sin_family = AF_INET;
804  sock.sin_addr = *dst;
805  sock.sin_port = htons (p1);
806  if (connect (sd, (struct sockaddr *) &sock, sizeof (struct sockaddr_in)) ==
807  -1)
808  {
809  close (sd);
810  return 0;
811  }
812  bzero (&sock, sizeof (struct sockaddr_in));
813  if (getsockname (sd, (struct sockaddr *) &sock, &socklen) == -1)
814  {
815  perror ("getsockname");
816  close (sd);
817  return 0;
818  }
819 
820  src->s_addr = sock.sin_addr.s_addr;
821  close (sd);
822  return 1; /* Calling function responsible for checking validity */
823 }
824 
825 int
826 getipv4routes (struct myroute *myroutes, int *numroutes)
827 {
828  struct interface_info *mydevs;
829  int i;
830  int numinterfaces;
831  char buf[1024];
832  char *p, *endptr;
833  char iface[64];
834  FILE *routez;
835  unsigned long dest;
836  struct in_addr inaddr;
837  unsigned long mask;
838  unsigned long ones;
839 
840  /* Dummy socket for ioctl */
841  mydevs = v6_getinterfaces (&numinterfaces);
842 
843  /* Now we must go through several techniques to determine info */
844  routez = fopen ("/proc/net/route", "r");
845 
846  if (routez)
847  {
848  /* OK, linux style /proc/net/route ... we can handle this ... */
849  /* Now that we've got the interfaces, we g0 after the r0ut3Z */
850  if (fgets (buf, sizeof (buf), routez) == NULL) /* Kill the first line */
851  {
852  // /proc/net/route was empty or an error occurred.
853  log_legacy_write ("Could not read from /proc/net/route");
854  fclose (routez);
855  return -1;
856  }
857  while (fgets (buf, sizeof (buf), routez))
858  {
859  p = strtok (buf, " \t\n");
860  if (!p)
861  {
862  log_legacy_write ("Could not find interface in"
863  " /proc/net/route line");
864  continue;
865  }
866  strncpy (iface, p, sizeof (iface));
867  if ((p = strchr (iface, ':')))
868  {
869  *p = '\0'; /* To support IP aliasing */
870  }
871  p = strtok (NULL, " \t\n");
872  endptr = NULL;
873  dest = strtoul (p, &endptr, 16);
874 #ifdef TCPIP_DEBUGGING
875  printf ("ipv4 dest is %s\n", p);
876 #endif
877  if (!endptr || *endptr)
878  {
879  log_legacy_write ("Failed to determine Destination from"
880  " /proc/net/route");
881  continue;
882  }
883  inaddr.s_addr = dest;
884  myroutes[*numroutes].dest6.s6_addr32[0] = 0;
885  myroutes[*numroutes].dest6.s6_addr32[1] = 0;
886  myroutes[*numroutes].dest6.s6_addr32[2] = htonl (0xffff);
887  myroutes[*numroutes].dest6.s6_addr32[3] = inaddr.s_addr;
888  for (i = 0; i < 6; i++)
889  {
890  p = strtok (NULL, " \t\n");
891  if (!p)
892  break;
893  }
894  if (!p)
895  {
896  log_legacy_write ("Failed to find field %d in"
897  " /proc/net/route", i + 2);
898  continue;
899  }
900  endptr = NULL;
901  mask = strtoul (p, &endptr, 16);
902  ones = 0;
903  i = 0;
904  while (mask & (1 << i++) && i < 32)
905  ones++;
906  myroutes[*numroutes].mask = ones + 96;
907 #ifdef TCPIP_DEBUGGING
908  printf ("mask is %lu\n", myroutes[*numroutes].mask);
909 #endif
910  if (!endptr || *endptr)
911  {
912  log_legacy_write ("Failed to determine mask from"
913  " /proc/net/route");
914  continue;
915  }
916 
917 
918 #if TCPIP_DEBUGGING
919  printf ("#%d: for dev %s, The dest is %lX and the mask is %lX\n",
920  *numroutes, iface, myroutes[*numroutes].dest,
921  myroutes[*numroutes].mask);
922 #endif
923  for (i = 0; i < numinterfaces; i++)
924  if (!strcmp (iface, mydevs[i].name))
925  {
926  myroutes[*numroutes].dev = &mydevs[i];
927  break;
928  }
929  if (i == numinterfaces)
931  ("Failed to find interface %s mentioned in /proc/net/route",
932  iface);
933  (*numroutes)++;
934  if (*numroutes >= MAXROUTES)
935  {
936  log_legacy_write ("You seem to have WAY to many routes!");
937  break;
938  }
939  }
940  fclose (routez);
941  return 0;
942  }
943  else
944  return -1;
945 }
946 
947 int
948 getipv6routes (struct myroute *myroutes, int *numroutes)
949 {
950  struct interface_info *mydevs;
951  int i, j;
952  int len;
953  struct in6_addr in6addr;
954  char destaddr[100];
955  int numinterfaces;
956  char buf[1024];
957  char *endptr;
958  char iface[64];
959  FILE *routez;
960  char v6addr[INET6_ADDRSTRLEN];
961  char *token;
962  int cnt;
963 
964  /* Dummy socket for ioctl */
965  mydevs = v6_getinterfaces (&numinterfaces);
966  routez = fopen ("/proc/net/ipv6_route", "r");
967  if (routez)
968  {
969  /* linux style /proc/net/ipv6_route ... we can handle this too... */
970  while (fgets (buf, sizeof (buf), routez) != NULL)
971  {
972 #if TCPIP_DEBUGGING
973  printf ("%s\n", buf);
974 #endif
975  token = strtok (buf, " \t\n");
976  if (token)
977  {
978 #if TCPIP_DEBUGGING
979  printf ("first token is %s\n", token);
980 #endif
981  strcpy (destaddr, token);
982  len = strlen (destaddr);
983  for (i = 0, j = 0; j < len; j++)
984  {
985  v6addr[i++] = destaddr[j];
986  if (j % 4 == 3)
987  v6addr[i++] = ':';
988  }
989  v6addr[--i] = '\0';
990 #if TCPIP_DEBUGGING
991  printf ("ipv6 dest is %s\n", v6addr);
992 #endif
993  if (inet_pton (AF_INET6, v6addr, &in6addr) <= 0)
994  {
995  log_legacy_write ("invalid ipv6 addressd");
996  continue;
997  }
998  memcpy (&myroutes[*numroutes].dest6, &in6addr,
999  sizeof (struct in6_addr));
1000  }
1001  token = strtok (NULL, " \t\n");
1002  if (token)
1003  {
1004  endptr = NULL;
1005  myroutes[*numroutes].mask = strtoul (token, &endptr, 16);
1006  }
1007  cnt = 7;
1008  while (cnt--)
1009  {
1010  token = strtok (NULL, " \t\n");
1011  if (!token)
1012  log_legacy_write ("getipv6routes error");
1013  }
1014 
1015  token = strtok (NULL, " \t\n");
1016  if (token)
1017  {
1018  strcpy (iface, token);
1019 #ifdef _DEBUG
1020  printf ("name token is %s\n", token);
1021 #endif
1022  }
1023  for (i = 0; i < numinterfaces; i++)
1024  if (!strcmp (iface, mydevs[i].name)
1025  && !IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
1026  {
1027  myroutes[*numroutes].dev = &mydevs[i];
1028  break;
1029  }
1030  if (i == numinterfaces)
1032  ("Failed to find interface %s mentioned in /proc/net/route\n",
1033  iface);
1034  (*numroutes)++;
1035  if (*numroutes >= MAXROUTES)
1036  {
1037  log_legacy_write ("You seem to have WAY to many routes!");
1038  break;
1039  }
1040  }
1041  fclose (routez);
1042  return 0;
1043  }
1044  else
1045  {
1046  log_legacy_write ("Didn't find IPv6 routes");
1047  return -1;
1048  }
1049 }
1050 
1060 char *
1061 v6_routethrough (struct in6_addr *dest, struct in6_addr *source)
1062 {
1063  static int initialized = 0;
1064  int i;
1065  struct in6_addr addy;
1066  static enum
1067  { procroutetechnique, connectsockettechnique, guesstechnique } technique =
1068  procroutetechnique;
1069  struct interface_info *mydevs;
1070  static struct myroute myroutes[MAXROUTES];
1071  int numinterfaces = 0;
1072  static int numroutes = 0;
1073  struct in6_addr in6addr;
1074 #ifdef TCPIP_DEBUGGING
1075  char addr1[INET6_ADDRSTRLEN];
1076  char addr2[INET6_ADDRSTRLEN];
1077 #endif
1078  struct in6_addr src;
1079 
1080  if (!dest)
1081  log_legacy_write ("ipaddr2devname passed a NULL dest address");
1082 
1083  if (IN6_IS_ADDR_V4MAPPED (dest))
1085  else
1086  openvas_source_addr6 (&src);
1087 
1088  if (!initialized)
1089  {
1090  /* Dummy socket for ioctl */
1091  initialized = 1;
1092  mydevs = v6_getinterfaces (&numinterfaces);
1093  if (IN6_IS_ADDR_V4MAPPED (dest))
1094  {
1095  if (getipv4routes (myroutes, &numroutes) < 0)
1096  technique = connectsockettechnique;
1097  }
1098  else
1099  {
1100  if (getipv6routes (myroutes, &numroutes) < 0)
1101  technique = connectsockettechnique;
1102  }
1103  }
1104  else
1105  {
1106  mydevs = v6_getinterfaces (&numinterfaces);
1107  }
1108  /* WHEW, that takes care of initializing, now we have the easy job of
1109  finding which route matches */
1110  if (v6_islocalhost (dest))
1111  {
1112  if (source)
1113  {
1114  if (IN6_IS_ADDR_V4MAPPED (source))
1115  {
1116  source->s6_addr32[0] = 0;
1117  source->s6_addr32[1] = 0;
1118  source->s6_addr32[2] = htonl (0xffff);
1119  source->s6_addr32[3] = htonl (0x7F000001);
1120  }
1121  else
1122  {
1123  source->s6_addr32[0] = 0;
1124  source->s6_addr32[1] = 0;
1125  source->s6_addr32[2] = 0;
1126  source->s6_addr32[3] = htonl (1);
1127  }
1128  }
1129  /* Now we find the localhost interface name, assuming 127.0.0.1
1130  or ::1 is localhost (it damn well better be!)... */
1131  for (i = 0; i < numinterfaces; i++)
1132  {
1133  if (IN6_IS_ADDR_V4MAPPED (&mydevs[i].addr6))
1134  {
1135  if (mydevs[i].addr6.s6_addr32[3] == htonl (0x7F000001))
1136  return mydevs[i].name;
1137  }
1138  else
1139  {
1140  if (IN6_ARE_ADDR_EQUAL (&in6addr_any, &mydevs[i].addr6))
1141  return mydevs[i].name;
1142  }
1143  }
1144  return NULL;
1145  }
1146 
1147  if (technique == procroutetechnique)
1148  {
1149  for (i = 0; i < numroutes; i++)
1150  {
1151  memcpy (&in6addr, dest, sizeof (struct in6_addr));
1152  ipv6addrmask (&in6addr, myroutes[i].mask);
1153 #if TCPIP_DEBUGGING
1154  printf ("comparing addresses %s and %s\n",
1155  inet_ntop (AF_INET6, &in6addr, addr1, sizeof (addr1)),
1156  inet_ntop (AF_INET6, &myroutes[i].dest6, addr2,
1157  sizeof (addr2)));
1158 #endif
1159  if (IN6_ARE_ADDR_EQUAL (&in6addr, &myroutes[i].dest6))
1160  {
1161  if (source)
1162  {
1163  if (!IN6_ARE_ADDR_EQUAL (&src, &in6addr_any))
1164  memcpy (source, &src, sizeof (struct in6_addr));
1165  else
1166  {
1167  if (myroutes[i].dev != NULL)
1168  {
1169 #if TCPIP_DEBUGGING
1170  printf ("copying address %s\n",
1171  inet_ntop (AF_INET6, &myroutes[i].dev->addr6,
1172  addr1, sizeof (addr1)));
1173  printf ("dev name is %s\n", myroutes[i].dev->name);
1174 #endif
1175  memcpy (source, &myroutes[i].dev->addr6,
1176  sizeof (struct in6_addr));
1177  }
1178  }
1179  }
1180  return myroutes[i].dev->name;
1181  }
1182  technique = connectsockettechnique;
1183  }
1184  }
1185  if (technique == connectsockettechnique)
1186  {
1187  if (!v6_getsourceip (&addy, dest))
1188  return NULL;
1189  if (IN6_ARE_ADDR_EQUAL (&addy, &in6addr))
1190  {
1191  struct hostent *myhostent = NULL;
1192  char myname[MAXHOSTNAMELEN + 1];
1193 
1194  myhostent = gethostbyname (myname);
1195  if (gethostname (myname, MAXHOSTNAMELEN) || !myhostent)
1196  log_legacy_write ("Cannot get hostname!");
1197  if (myhostent->h_addrtype == AF_INET)
1198  {
1199  addy.s6_addr32[0] = 0;
1200  addy.s6_addr32[1] = 0;
1201  addy.s6_addr32[2] = htonl (0xffff);
1202  memcpy (&addy.s6_addr32[0], myhostent->h_addr_list[0],
1203  sizeof (struct in6_addr));
1204  }
1205  else
1206  memcpy (&addy, myhostent->h_addr_list[0], sizeof (struct in6_addr));
1207  }
1208 
1209  /* Now we insure this claimed address is a real interface ... */
1210  for (i = 0; i < numinterfaces; i++)
1211  {
1212 #ifdef TCPIP_DEBUGGING
1213  printf ("comparing addresses %s and %s\n",
1214  inet_ntop (AF_INET6, &mydevs[i].addr6, addr1, sizeof (addr1)),
1215  inet_ntop (AF_INET6, &addy, addr2, sizeof (addr2)));
1216 #endif
1217  if (IN6_ARE_ADDR_EQUAL (&mydevs[i].addr6, &addy))
1218  {
1219  if (source)
1220  {
1221  memcpy (source, &addy, sizeof (struct in6_addr));
1222  }
1223  return mydevs[i].name;
1224  }
1225  }
1226  return NULL;
1227  }
1228  else
1229  log_legacy_write ("%s: Provided technique is neither proc route nor"
1230  " connect socket", __FUNCTION__);
1231  return NULL;
1232 }
1233 
1243 char *
1244 routethrough (struct in_addr *dest, struct in_addr *source)
1245 {
1246  static int initialized = 0;
1247  int i;
1248  struct in_addr addy;
1249  static enum
1250  { procroutetechnique, connectsockettechnique, guesstechnique } technique =
1251  procroutetechnique;
1252  char buf[10240];
1253  struct interface_info *mydevs;
1254  static struct myroute
1255  {
1256  struct interface_info *dev;
1257  unsigned long mask;
1258  unsigned long dest;
1259  } myroutes[MAXROUTES];
1260  int numinterfaces = 0;
1261  char *p, *endptr;
1262  char iface[64];
1263  static int numroutes = 0;
1264  FILE *routez;
1265  long match = -1;
1266  unsigned long bestmatch = 0;
1267 
1268  struct in_addr src;
1269 
1270  openvas_source_addr (&src);
1271  if (!dest)
1272  log_legacy_write ("ipaddr2devname passed a NULL dest address");
1273 
1274  if (!initialized)
1275  {
1276  /* Dummy socket for ioctl */
1277  initialized = 1;
1278  mydevs = getinterfaces (&numinterfaces);
1279 
1280  /* Now we must go through several techniques to determine info */
1281  routez = fopen ("/proc/net/route", "r");
1282 
1283  if (routez)
1284  {
1285  /* OK, linux style /proc/net/route ... we can handle this ... */
1286  /* Now that we've got the interfaces, we g0 after the r0ut3Z */
1287  if (fgets (buf, sizeof (buf), routez) == NULL) /* Kill the first line */
1288  log_legacy_write ("Could not read from /proc/net/route");
1289  while (fgets (buf, sizeof (buf), routez))
1290  {
1291  p = strtok (buf, " \t\n");
1292  if (!p)
1293  {
1294  log_legacy_write ("Could not find interface in"
1295  " /proc/net/route line");
1296  continue;
1297  }
1298  strncpy (iface, p, sizeof (iface));
1299  if ((p = strchr (iface, ':')))
1300  {
1301  *p = '\0'; /* To support IP aliasing */
1302  }
1303  p = strtok (NULL, " \t\n");
1304  endptr = NULL;
1305  myroutes[numroutes].dest = strtoul (p, &endptr, 16);
1306  if (!endptr || *endptr)
1307  {
1309  ("Failed to determine Destination from /proc/net/route");
1310  continue;
1311  }
1312  for (i = 0; i < 6; i++)
1313  {
1314  p = strtok (NULL, " \t\n");
1315  if (!p)
1316  break;
1317  }
1318  if (!p)
1319  {
1320  log_legacy_write ("Failed to find field %d in"
1321  " /proc/net/route", i + 2);
1322  continue;
1323  }
1324  endptr = NULL;
1325  myroutes[numroutes].mask = strtoul (p, &endptr, 16);
1326  if (!endptr || *endptr)
1327  {
1328  log_legacy_write ("Failed to determine mask"
1329  " from /proc/net/route");
1330  continue;
1331  }
1332 
1333 
1334 #if TCPIP_DEBUGGING
1335  printf ("#%d: for dev %s, The dest is %lX and the mask is %lX\n",
1336  numroutes, iface, myroutes[numroutes].dest,
1337  myroutes[numroutes].mask);
1338 #endif
1339  for (i = 0; i < numinterfaces; i++)
1340  if (!strcmp (iface, mydevs[i].name))
1341  {
1342  myroutes[numroutes].dev = &mydevs[i];
1343  break;
1344  }
1345  if (i == numinterfaces)
1347  ("Failed to find interface %s mentioned in /proc/net/route",
1348  iface);
1349  numroutes++;
1350  if (numroutes >= MAXROUTES)
1351  {
1352  log_legacy_write ("You seem to have WAY to many routes!");
1353  break;
1354  }
1355  }
1356  fclose (routez);
1357  }
1358  else
1359  {
1360  technique = connectsockettechnique;
1361  }
1362  }
1363  else
1364  {
1365  mydevs = getinterfaces (&numinterfaces);
1366  }
1367  /* WHEW, that takes care of initializing, now we have the easy job of
1368  finding which route matches */
1369  if (islocalhost (dest))
1370  {
1371  if (source)
1372  source->s_addr = htonl (0x7F000001);
1373  /* Now we find the localhost interface name, assuming 127.0.0.1 is
1374  localhost (it damn well better be!)... */
1375  for (i = 0; i < numinterfaces; i++)
1376  {
1377  if (mydevs[i].addr.s_addr == htonl (0x7F000001))
1378  {
1379  return mydevs[i].name;
1380  }
1381  }
1382  return NULL;
1383  }
1384 
1385  if (technique == procroutetechnique)
1386  {
1387  for (i = 0; i < numroutes; i++)
1388  {
1389  if ((dest->s_addr & myroutes[i].mask) == myroutes[i].dest && myroutes[i].mask >= bestmatch)
1390  {
1391  if (source)
1392  {
1393  if (src.s_addr != INADDR_ANY)
1394  source->s_addr = src.s_addr;
1395  else
1396  source->s_addr = myroutes[i].dev->addr.s_addr;
1397  }
1398  match = i;
1399  bestmatch = myroutes[i].mask;
1400  }
1401  }
1402  if (match != -1)
1403  return myroutes[match].dev->name;
1404  }
1405  else if (technique == connectsockettechnique)
1406  {
1407  if (!getsourceip (&addy, dest))
1408  return NULL;
1409  if (!addy.s_addr)
1410  { /* Solaris 2.4 */
1411  struct hostent *myhostent = NULL;
1412  char myname[MAXHOSTNAMELEN + 1];
1413  myhostent = gethostbyname (myname);
1414  if (gethostname (myname, MAXHOSTNAMELEN) || !myhostent)
1415  log_legacy_write ("Cannot get hostname!");
1416  memcpy (&(addy.s_addr), myhostent->h_addr_list[0],
1417  sizeof (struct in_addr));
1418  }
1419 
1420  /* Now we insure this claimed address is a real interface ... */
1421  for (i = 0; i < numinterfaces; i++)
1422  if (mydevs[i].addr.s_addr == addy.s_addr)
1423  {
1424  if (source)
1425  {
1426  source->s_addr = addy.s_addr;
1427  }
1428  return mydevs[i].name;
1429  }
1430  return NULL;
1431  }
1432  else
1433  log_legacy_write ("%s: Provided technique is neither proc route"
1434  " nor connect socket", __FUNCTION__);
1435  return NULL;
1436 }
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:378
struct in6_addr mask
Definition: pcap.c:47
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:1061
void openvas_source_addr6(void *addr6)
Gives the source IPv6 address.
struct in_addr addr
Definition: pcap.c:45
struct in6_addr addr6
Definition: pcap.c:46
Definition: pcap.c:50
void openvas_source_addr(void *addr)
Gives the source IPv4 address.
int v6_getsourceip(struct in6_addr *src, struct in6_addr *dst)
Definition: pcap.c:692
int getipv6routes(struct myroute *myroutes, int *numroutes)
Definition: pcap.c:948
struct interface_info * dev
Definition: pcap.c:52
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:415
void log_legacy_write(const char *format,...)
Legacy function to write a log message.
struct interface_info * v6_getinterfaces(int *howmany)
Definition: pcap.c:549
void bpf_close(int bpf)
Definition: bpf_share.c:153
int v6_get_mac_addr(struct in6_addr *addr, char **mac)
We send an empty UDP packet to the remote host, and read back its mac.
Definition: pcap.c:171
int get_datalink_size(int datalink)
Definition: pcap.c:442
int bpf_datalink(int bpf)
Definition: bpf_share.c:146
struct interface_info * getinterfaces(int *howmany)
Definition: pcap.c:630
struct in6_addr dest6
Definition: pcap.c:53
#define MAXHOSTNAMELEN
int bpf_open_live(char *iface, char *filter)
Definition: bpf_share.c:40
int get_random_bytes(void *buf, int numbytes)
Definition: pcap.c:482
const char * name
Definition: nasl_init.c:524
int v6_is_local_ip(struct in6_addr *addr)
Definition: pcap.c:106
unsigned long dest
Definition: pcap.c:55
int getsourceip(struct in_addr *src, struct in_addr *dst)
Definition: pcap.c:787
int getipv4routes(struct myroute *myroutes, int *numroutes)
Definition: pcap.c:826
struct timeval timeval(unsigned long val)
unsigned long mask
Definition: pcap.c:54
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:1244
u_char * bpf_next(int bpf, int *caplen)
Definition: bpf_share.c:137
int ipaddr2devname(char *dev, int sz, struct in_addr *addr)
Definition: pcap.c:351
void openvas_source_addr_as_addr6(struct in6_addr *addr6)
Gives the source IPv4 mapped as an IPv6 address. eg. 192.168.20.10 would map to ::ffff:192....
char name[64]
Definition: pcap.c:44
int v6_ipaddr2devname(char *dev, int sz, struct in6_addr *addr)
Definition: pcap.c:316
#define MAXROUTES
Definition: pcap.c:39