Greenbone Vulnerability Management Libraries 22.8.0
networking.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013-2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
11#include "networking.h"
12
13#include <arpa/inet.h> /* for inet_ntop */
14#include <assert.h> /* for assert */
15#include <ctype.h> /* for isblank */
16#include <errno.h> /* for errno, EAFNOSUPPORT */
17#include <glib/gstdio.h>
18#include <ifaddrs.h> /* for ifaddrs, freeifaddrs, getifaddrs */
19#include <net/if.h> /* for IFNAMSIZ */
20#include <stdint.h> /* for uint32_t, uint8_t */
21#include <stdlib.h> /* for atoi, strtol */
22#include <string.h> /* for memcpy, bzero, strchr, strlen, strcmp, strncpy */
23#include <sys/socket.h> /* for AF_INET, AF_INET6, AF_UNSPEC, sockaddr_storage */
24#include <unistd.h> /* for close */
25
26#ifdef __FreeBSD__
27#include <netinet/in.h>
28#define s6_addr32 __u6_addr.__u6_addr32
29#endif
30
31#undef G_LOG_DOMAIN
35#define G_LOG_DOMAIN "libgvm base"
36
37#if GLIB_CHECK_VERSION(2, 67, 3)
38#define memdup g_memdup2
39#else
40#define memdup g_memdup
41#endif
42
43/* Global variables */
44
45/* Source interface name eg. eth1. */
46char global_source_iface[IFNAMSIZ] = {'\0'};
47
48/* Source IPv4 address. */
49struct in_addr global_source_addr = {.s_addr = 0};
50
51/* Source IPv6 address. */
52struct in6_addr global_source_addr6 = {.s6_addr32 = {0, 0, 0, 0}};
53
54/* Source Interface/Address related functions. */
55
63int
64gvm_source_iface_init (const char *iface)
65{
66 struct ifaddrs *ifaddr, *ifa;
67 int ret = 1;
68
70 global_source_addr.s_addr = INADDR_ANY;
71 global_source_addr6 = in6addr_any;
72
73 if (iface == NULL)
74 return ret;
75
76 if (strlen (iface) >= sizeof (global_source_iface))
77 return ret;
78
79 if (getifaddrs (&ifaddr) == -1)
80 return ret;
81
82 /* Search for the adequate interface/family. */
83 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
84 {
85 if (ifa->ifa_addr && strcmp (iface, ifa->ifa_name) == 0)
86 {
87 if (ifa->ifa_addr->sa_family == AF_INET)
88 {
89 struct in_addr *addr =
90 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
91
92 memcpy (&global_source_addr, addr, sizeof (global_source_addr));
93 ret = 0;
94 }
95 else if (ifa->ifa_addr->sa_family == AF_INET6)
96 {
97 struct sockaddr_in6 *addr;
98
99 addr = (struct sockaddr_in6 *) ifa->ifa_addr;
100 memcpy (&global_source_addr6.s6_addr, &addr->sin6_addr,
101 sizeof (struct in6_addr));
102 ret = 0;
103 }
104 }
105 }
106
107 /* At least one address for the interface was found. */
108 if (ret == 0)
109 memcpy (global_source_iface, iface, strlen (iface));
110
111 freeifaddrs (ifaddr);
112 return ret;
113}
114
120int
122{
123 return *global_source_iface != '\0';
124}
125
135int
136gvm_source_set_socket (int socket, int port, int family)
137{
138 if (family == AF_INET)
139 {
140 struct sockaddr_in addr;
141
142 bzero (&addr, sizeof (addr));
143 gvm_source_addr (&addr.sin_addr);
144 addr.sin_port = htons (port);
145 addr.sin_family = AF_INET;
146
147 if (bind (socket, (struct sockaddr *) &addr, sizeof (addr)) < 0)
148 return -1;
149 }
150 else if (family == AF_INET6)
151 {
152 struct sockaddr_in6 addr6;
153
154 bzero (&addr6, sizeof (addr6));
155 gvm_source_addr6 (&addr6.sin6_addr);
156 addr6.sin6_port = htons (port);
157 addr6.sin6_family = AF_INET6;
158
159 if (bind (socket, (struct sockaddr *) &addr6, sizeof (addr6)) < 0)
160 return -1;
161 }
162 else
163 return -1;
164
165 return 0;
166}
167
173void
174gvm_source_addr (void *addr)
175{
176 if (addr)
177 memcpy (addr, &global_source_addr.s_addr, 4);
178}
179
185void
186gvm_source_addr6 (void *addr6)
187{
188 if (addr6)
189 memcpy (addr6, &global_source_addr6.s6_addr, 16);
190}
191
198void
199gvm_source_addr_as_addr6 (struct in6_addr *addr6)
200{
201 if (addr6)
203}
204
210char *
212{
213 char *str = g_malloc0 (INET_ADDRSTRLEN);
214
215 inet_ntop (AF_INET, &global_source_addr.s_addr, str, INET_ADDRSTRLEN);
216 return str;
217}
218
224char *
226{
227 char *str = g_malloc0 (INET6_ADDRSTRLEN);
228
229 inet_ntop (AF_INET6, &global_source_addr6, str, INET6_ADDRSTRLEN);
230 return str;
231}
232
233/* Miscellaneous functions. */
234
242void
243ipv4_as_ipv6 (const struct in_addr *ip4, struct in6_addr *ip6)
244{
245 if (ip4 == NULL || ip6 == NULL)
246 return;
247
248 ip6->s6_addr32[0] = 0;
249 ip6->s6_addr32[1] = 0;
250 ip6->s6_addr32[2] = htonl (0xffff);
251 memcpy (&ip6->s6_addr32[3], ip4, sizeof (struct in_addr));
252}
253
260void
261addr6_to_str (const struct in6_addr *addr6, char *str)
262{
263 if (!addr6)
264 return;
265 if (IN6_IS_ADDR_V4MAPPED (addr6))
266 inet_ntop (AF_INET, &addr6->s6_addr32[3], str, INET6_ADDRSTRLEN);
267 else
268 inet_ntop (AF_INET6, addr6, str, INET6_ADDRSTRLEN);
269}
270
278char *
279addr6_as_str (const struct in6_addr *addr6)
280{
281 char *str;
282
283 if (!addr6)
284 return NULL;
285
286 str = g_malloc0 (INET6_ADDRSTRLEN);
287 addr6_to_str (addr6, str);
288 return str;
289}
290
297void
298sockaddr_as_str (const struct sockaddr_storage *addr, char *str)
299{
300 if (!addr || !str)
301 return;
302
303 if (addr->ss_family == AF_INET)
304 {
305 struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
306 inet_ntop (AF_INET, &saddr->sin_addr, str, INET6_ADDRSTRLEN);
307 }
308 else if (addr->ss_family == AF_INET6)
309 {
310 struct sockaddr_in6 *s6addr = (struct sockaddr_in6 *) addr;
311 if (IN6_IS_ADDR_V4MAPPED (&s6addr->sin6_addr))
312 inet_ntop (AF_INET, &s6addr->sin6_addr.s6_addr[12], str,
313 INET6_ADDRSTRLEN);
314 else
315 inet_ntop (AF_INET6, &s6addr->sin6_addr, str, INET6_ADDRSTRLEN);
316 }
317 else if (addr->ss_family == AF_UNIX)
318 {
319 g_snprintf (str, INET6_ADDRSTRLEN, "unix_socket");
320 }
321 else if (addr->ss_family == AF_UNSPEC)
322 {
323 g_snprintf (str, INET6_ADDRSTRLEN, "unknown_socket");
324 }
325 else
326 {
327 g_snprintf (str, INET6_ADDRSTRLEN, "type_%d_socket", addr->ss_family);
328 }
329}
330
338GSList *
339gvm_resolve_list (const char *name)
340{
341 struct addrinfo hints, *info, *p;
342 GSList *list = NULL;
343
344 if (name == NULL)
345 return NULL;
346
347 bzero (&hints, sizeof (hints));
348 hints.ai_family = AF_UNSPEC;
349 hints.ai_socktype = SOCK_STREAM;
350 hints.ai_protocol = 0;
351 if ((getaddrinfo (name, NULL, &hints, &info)) != 0)
352 return NULL;
353
354 p = info;
355 while (p)
356 {
357 struct in6_addr dst;
358
359 if (p->ai_family == AF_INET)
360 {
361 struct sockaddr_in *addrin = (struct sockaddr_in *) p->ai_addr;
362 ipv4_as_ipv6 (&(addrin->sin_addr), &dst);
363 list = g_slist_prepend (list, memdup (&dst, sizeof (dst)));
364 }
365 else if (p->ai_family == AF_INET6)
366 {
367 struct sockaddr_in6 *addrin = (struct sockaddr_in6 *) p->ai_addr;
368 memcpy (&dst, &(addrin->sin6_addr), sizeof (struct in6_addr));
369 list = g_slist_prepend (list, memdup (&dst, sizeof (dst)));
370 }
371 p = p->ai_next;
372 }
373
374 freeaddrinfo (info);
375 return list;
376}
377
388int
389gvm_resolve (const char *name, void *dst, int family)
390{
391 struct addrinfo hints, *info, *p;
392
393 if (name == NULL || dst == NULL
394 || (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC))
395 return -1;
396
397 bzero (&hints, sizeof (hints));
398 hints.ai_family = family;
399 hints.ai_socktype = SOCK_STREAM;
400 hints.ai_protocol = 0;
401 if ((getaddrinfo (name, NULL, &hints, &info)) != 0)
402 return -1;
403
404 p = info;
405 while (p)
406 {
407 if (p->ai_family == family || family == AF_UNSPEC)
408 {
409 if (p->ai_family == AF_INET && family == AF_UNSPEC)
410 {
411 struct sockaddr_in *addrin = (struct sockaddr_in *) p->ai_addr;
412 ipv4_as_ipv6 (&(addrin->sin_addr), dst);
413 }
414 else if (p->ai_family == AF_INET)
415 {
416 struct sockaddr_in *addrin = (struct sockaddr_in *) p->ai_addr;
417 memcpy (dst, &(addrin->sin_addr), sizeof (struct in_addr));
418 }
419 else if (p->ai_family == AF_INET6)
420 {
421 struct sockaddr_in6 *addrin = (struct sockaddr_in6 *) p->ai_addr;
422 memcpy (dst, &(addrin->sin6_addr), sizeof (struct in6_addr));
423 }
424 break;
425 }
426
427 p = p->ai_next;
428 }
429
430 freeaddrinfo (info);
431 return 0;
432}
433
442int
443gvm_resolve_as_addr6 (const char *name, struct in6_addr *ip6)
444{
445 return gvm_resolve (name, ip6, AF_UNSPEC);
446}
447
448/* Ports related. */
449
459int
460validate_port_range (const char *port_range)
461{
462 gchar **split, **point, *range, *range_start;
463
464 if (!port_range)
465 return 1;
466
467 while (*port_range && isblank (*port_range))
468 port_range++;
469 if (*port_range == '\0')
470 return 1;
471
472 /* Treat newlines like commas. */
473 range = range_start = g_strdup (port_range);
474 while (*range)
475 {
476 if (*range == '\n')
477 *range = ',';
478 range++;
479 }
480
481 split = g_strsplit (range_start, ",", 0);
482 g_free (range_start);
483 point = split;
484
485 while (*point)
486 {
487 gchar *hyphen, *element;
488
489 /* Strip off any outer whitespace. */
490
491 element = g_strstrip (*point);
492
493 /* Strip off any leading type specifier and following whitespace. */
494
495 if ((strlen (element) >= 2)
496 && ((element[0] == 'T') || (element[0] == 'U')))
497 {
498 element++;
499 while (*element && isblank (*element))
500 element++;
501 if (*element == ':')
502 element++;
503 }
504
505 /* Look for a hyphen. */
506
507 hyphen = strchr (element, '-');
508 if (hyphen)
509 {
510 long int number1, number2;
511 const char *first;
512 char *end;
513
514 hyphen++;
515
516 /* Check the first number. */
517
518 first = element;
519 while (*first && isblank (*first))
520 first++;
521 if (*first == '-')
522 goto fail;
523
524 errno = 0;
525 number1 = strtol (first, &end, 10);
526 while (*end && isblank (*end))
527 end++;
528 if (errno || (*end != '-'))
529 goto fail;
530 if (number1 == 0)
531 goto fail;
532 if (number1 > 65535)
533 goto fail;
534
535 /* Check the second number. */
536
537 while (*hyphen && isblank (*hyphen))
538 hyphen++;
539 if (*hyphen == '\0')
540 goto fail;
541
542 errno = 0;
543 number2 = strtol (hyphen, &end, 10);
544 while (*end && isblank (*end))
545 end++;
546 if (errno || *end)
547 goto fail;
548 if (number2 == 0)
549 goto fail;
550 if (number2 > 65535)
551 goto fail;
552
553 if (number1 > number2)
554 goto fail;
555 }
556 else
557 {
558 long int number;
559 const char *only;
560 char *end;
561
562 /* Check the single number. */
563
564 only = element;
565 while (*only && isblank (*only))
566 only++;
567 /* Empty ranges are OK. */
568 if (*only)
569 {
570 errno = 0;
571 number = strtol (only, &end, 10);
572 while (*end && isblank (*end))
573 end++;
574 if (errno || *end)
575 goto fail;
576 if (number == 0)
577 goto fail;
578 if (number > 65535)
579 goto fail;
580 }
581 }
582 point += 1;
583 }
584
585 g_strfreev (split);
586 return 0;
587
588fail:
589 g_strfreev (split);
590 return 1;
591}
592
600array_t *
601port_range_ranges (const char *port_range)
602{
603 gchar **split, **point, *range_start, *current;
604 array_t *ranges;
605 int tcp, err;
606
607 if (!port_range)
608 return NULL;
609
610 /* port_range needs to be a valid port_range string. */
611 err = validate_port_range (port_range);
612 if (err)
613 return NULL;
614
615 ranges = make_array ();
616
617 while (*port_range && isblank (*port_range))
618 port_range++;
619
620 /* Accepts T: and U: before any of the ranges. This toggles the remaining
621 * ranges, as in nmap. Treats a leading naked range as TCP, whereas nmap
622 * treats it as TCP and UDP. */
623
624 /* Treat newlines like commas. */
625 range_start = current = g_strdup (port_range);
626 while (*current)
627 {
628 if (*current == '\n')
629 *current = ',';
630 current++;
631 }
632
633 tcp = 1;
634 split = g_strsplit (range_start, ",", 0);
635 g_free (range_start);
636 point = split;
637
638 while (*point)
639 {
640 gchar *hyphen, *element;
641 range_t *range;
642 int element_strlen;
643
644 element = g_strstrip (*point);
645 element_strlen = strlen (element);
646
647 if (element_strlen >= 2)
648 {
649 if (element[0] == 'T')
650 {
651 element++;
652 while (*element && isblank (*element))
653 element++;
654 if (*element == ':')
655 {
656 element++;
657 tcp = 1;
658 }
659 }
660 else if (element[0] == 'U')
661 {
662 element++;
663 while (*element && isblank (*element))
664 element++;
665 if (*element == ':')
666 {
667 element++;
668 tcp = 0;
669 }
670 }
671 /* Else tcp stays as it is. */
672 }
673
674 /* Skip any space that followed the type specifier. */
675 while (*element && isblank (*element))
676 element++;
677
678 hyphen = strchr (element, '-');
679 if (hyphen)
680 {
681 *hyphen = '\0';
682 hyphen++;
683 while (*hyphen && isblank (*hyphen))
684 hyphen++;
685 assert (*hyphen); /* Validation checks this. */
686
687 /* A range. */
688
689 range = (range_t *) g_malloc0 (sizeof (range_t));
690
691 range->start = atoi (element);
692 range->end = atoi (hyphen);
694 range->exclude = 0;
695
696 array_add (ranges, range);
697 }
698 else if (*element)
699 {
700 /* A single port. */
701
702 range = (range_t *) g_malloc0 (sizeof (range_t));
703
704 range->start = atoi (element);
705 range->end = range->start;
707 range->exclude = 0;
708
709 array_add (ranges, range);
710 }
711 /* Else skip over empty range. */
712 point += 1;
713 }
714 g_strfreev (split);
715 return ranges;
716}
717
727int
728port_in_port_ranges (int pnum, port_protocol_t ptype, array_t *pranges)
729{
730 unsigned int i;
731
732 if (pranges == NULL || pnum < 0 || pnum > 65536)
733 return 0;
734
735 for (i = 0; i < pranges->len; i++)
736 {
737 range_t *range = (range_t *) g_ptr_array_index (pranges, i);
738 if (range->type != ptype)
739 continue;
740 if (range->start <= pnum && pnum <= range->end)
741 return 1;
742 }
743 return 0;
744}
745
751int
753{
754 int sock = socket (PF_INET6, SOCK_STREAM, 0);
755
756 if (sock < 0)
757 {
758 if (errno == EAFNOSUPPORT)
759 return 0;
760 }
761 else
762 close (sock);
763
764 return 1;
765}
766
767/* Functions used by alive detection module (Boreas). */
768
774static gboolean
775ip_islocalhost (struct sockaddr_storage *storage)
776{
777 struct in_addr addr;
778 struct in_addr *addr_p;
779 struct in6_addr addr6 = IN6ADDR_ANY_INIT;
780 struct in6_addr *addr6_p;
781 struct sockaddr_in *sin_p;
782 struct sockaddr_in6 *sin6_p;
783 struct ifaddrs *ifaddr, *ifa;
784 int family;
785
786 family = storage->ss_family;
787 addr6_p = &addr6;
788 addr_p = &addr;
789 addr.s_addr = 0;
790
791 if (family == AF_INET)
792 {
793 sin_p = (struct sockaddr_in *) storage;
794 addr = sin_p->sin_addr;
795
796 if (addr_p == NULL)
797 return FALSE;
798 /* addr is 0.0.0.0 */
799 if ((addr_p)->s_addr == 0)
800 return TRUE;
801 /* addr starts with 127.0.0.1 */
802 if (((addr_p)->s_addr & htonl (0xFF000000)) == htonl (0x7F000000))
803 return TRUE;
804 }
805 if (family == AF_INET6)
806 {
807 sin6_p = (struct sockaddr_in6 *) storage;
808 addr6 = sin6_p->sin6_addr;
809
810 if (IN6_IS_ADDR_V4MAPPED (&addr6))
811 {
812 /* addr is 0.0.0.0 */
813 if (addr6_p->s6_addr32[3] == 0)
814 return 1;
815
816 /* addr starts with 127.0.0.1 */
817 if ((addr6_p->s6_addr32[3] & htonl (0xFF000000))
818 == htonl (0x7F000000))
819 return 1;
820 }
821 if (IN6_IS_ADDR_LOOPBACK (addr6_p))
822 return 1;
823 }
824
825 if (getifaddrs (&ifaddr) == -1)
826 {
827 g_debug ("%s: getifaddr failed: %s", __func__, strerror (errno));
828 return FALSE;
829 }
830 else
831 {
832 struct sockaddr_in *sin;
833 struct sockaddr_in6 *sin6;
834
835 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
836 {
837 if (ifa->ifa_addr == NULL)
838 continue;
839 if (ifa->ifa_addr->sa_family == AF_INET)
840 {
841 sin = (struct sockaddr_in *) (ifa->ifa_addr);
842 /* Check if same address as local interface. */
843 if (addr_p->s_addr == sin->sin_addr.s_addr)
844 return TRUE;
845 }
846 if (ifa->ifa_addr->sa_family == AF_INET6)
847 {
848 sin6 = (struct sockaddr_in6 *) (ifa->ifa_addr);
849
850 /* Check if same address as local interface. */
851 if (family == AF_INET6
852 && IN6_ARE_ADDR_EQUAL (&(sin6->sin6_addr), addr6_p))
853 return TRUE;
854 }
855 }
856 freeifaddrs (ifaddr);
857 }
858
859 return FALSE;
860}
861
863
866{
867 gchar *interface;
868 unsigned long mask;
869 unsigned long dest;
870};
871
877static GSList *
879{
880 GSList *routes;
881 GError *err;
882 GIOChannel *file_channel;
883 gchar *line;
884 gchar **items_in_line;
885 int status;
886 route_entry_t *entry;
887
888 err = NULL;
889 routes = NULL;
890 line = NULL;
891
892 /* Open "/proc/net/route". */
893 file_channel = g_io_channel_new_file ("/proc/net/route", "r", &err);
894 if (file_channel == NULL)
895 {
896 g_warning ("%s: %s. ", __func__,
897 err ? err->message : "Error opening /proc/net/ipv6_route");
898 err = NULL;
899 return NULL;
900 }
901
902 /* Skip first first line of file. */
903 status = g_io_channel_read_line (file_channel, &line, NULL, NULL, &err);
904 if (status != G_IO_STATUS_NORMAL || !line || err)
905 {
906 g_warning ("%s: %s", __func__,
907 err ? err->message
908 : "g_io_channel_read_line() status != G_IO_STATUS_NORMAL");
909 err = NULL;
910 }
911 g_free (line);
912
913 /* Until EOF or err we go through lines of file and extract Iface, Mask and
914 * Destination and put it into the to be returned list of routes.*/
915 while (1)
916 {
917 gchar *interface, *char_p;
918 unsigned long mask, dest;
919 int count;
920
921 /* Get new line. */
922 line = NULL;
923 status = g_io_channel_read_line (file_channel, &line, NULL, NULL, &err);
924 if ((status != G_IO_STATUS_NORMAL) || !line || err)
925 {
926 if (status == G_IO_STATUS_AGAIN)
927 g_warning ("%s: /proc/net/route unavailable.", __func__);
928 if (err || status == G_IO_STATUS_ERROR)
929 g_warning (
930 "%s: %s", __func__,
931 err ? err->message
932 : "g_io_channel_read_line() status == G_IO_STATUS_ERROR");
933 err = NULL;
934 g_free (line);
935 break;
936 }
937
938 /* Get items in line. */
939 items_in_line = g_strsplit (line, "\t", -1);
940 /* Check for missing entries in line of "/proc/net/route". */
941 for (count = 0; items_in_line[count]; count++)
942 ;
943 if (11 != count)
944 {
945 g_strfreev (items_in_line);
946 g_free (line);
947 continue;
948 }
949
950 interface = g_strndup (items_in_line[0], 64);
951 /* Cut interface str after ":" if IP aliasing is used. */
952 if ((char_p = strchr (interface, ':')))
953 {
954 *char_p = '\0';
955 }
956 dest = strtoul (items_in_line[1], NULL, 16);
957 mask = strtoul (items_in_line[7], NULL, 16);
958
959 /* Fill GSList entry. */
960 entry = g_malloc0 (sizeof (route_entry_t));
961 entry->interface = interface;
962 entry->dest = dest;
963 entry->mask = mask;
964 routes = g_slist_append (routes, entry);
965
966 g_strfreev (items_in_line);
967 g_free (line);
968 }
969
970 status = g_io_channel_shutdown (file_channel, TRUE, &err);
971 if ((G_IO_STATUS_NORMAL != status) || err)
972 g_warning ("%s: %s", __func__,
973 err ? err->message
974 : "g_io_channel_shutdown() was not successful");
975
976 return routes;
977}
978
993gchar *
994gvm_routethrough (struct sockaddr_storage *storage_dest,
995 struct sockaddr_storage *storage_source)
996{
997 struct ifaddrs *ifaddr, *ifa;
998 gchar *interface_out;
999
1000 interface_out = NULL;
1001
1002 if (!storage_dest)
1003 return NULL;
1004
1005 if (getifaddrs (&ifaddr) == -1)
1006 {
1007 g_debug ("%s: getifaddr failed: %s", __func__, strerror (errno));
1008 return NULL;
1009 }
1010
1011 /* IPv4. */
1012 if (storage_dest->ss_family == AF_INET)
1013 {
1014 GSList *routes;
1015 GSList *routes_p;
1016
1017 routes = get_routes ();
1018
1019 /* Set storage_source to localhost if storage_source was supplied and
1020 * return name of loopback interface. */
1021 if (ip_islocalhost (storage_dest))
1022 {
1023 // TODO: check for (storage_source->ss_family == AF_INET)
1024 if (storage_source)
1025 {
1026 struct sockaddr_in *sin_p = (struct sockaddr_in *) storage_source;
1027 sin_p->sin_addr.s_addr = htonl (0x7F000001);
1028 }
1029
1030 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1031 {
1032 if (ifa->ifa_addr && (ifa->ifa_addr->sa_family == AF_INET)
1033 && (ifa->ifa_flags & (IFF_LOOPBACK)))
1034 {
1035 interface_out = g_strdup (ifa->ifa_name);
1036 break;
1037 }
1038 }
1039 }
1040 else
1041 {
1042 struct sockaddr_in *sin_dest_p, *sin_src_p;
1043 struct in_addr global_src;
1044 unsigned long best_match;
1045
1046 /* Check if global_source_addr in use. */
1047 gvm_source_addr (&global_src);
1048
1049 sin_dest_p = (struct sockaddr_in *) storage_dest;
1050 sin_src_p = (struct sockaddr_in *) storage_source;
1051 /* Check routes for matching address. Get interface name and set
1052 * storage_source*/
1053 for (best_match = 0, routes_p = routes; routes_p;
1054 routes_p = routes_p->next)
1055 {
1056 if (((sin_dest_p->sin_addr.s_addr
1057 & ((route_entry_t *) (routes_p->data))->mask)
1058 == ((route_entry_t *) (routes_p->data))->dest)
1059 && (((route_entry_t *) (routes_p->data))->mask >= best_match))
1060 {
1061 /* Interface of matching route.*/
1062 g_free (interface_out);
1063 interface_out =
1064 g_strdup (((route_entry_t *) (routes_p->data))->interface);
1065 best_match = ((route_entry_t *) (routes_p->data))->mask;
1066
1067 if (!storage_source)
1068 continue;
1069
1070 /* Set storage_source to global source if global source
1071 * present.*/
1072 if (global_src.s_addr != INADDR_ANY)
1073 sin_src_p->sin_addr.s_addr = global_src.s_addr;
1074 /* Set storage_source to addr of matching interface if no
1075 * global source present.*/
1076 else
1077 {
1078 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1079 {
1080 if (ifa->ifa_addr
1081 && (ifa->ifa_addr->sa_family == AF_INET)
1082 && (g_strcmp0 (interface_out, ifa->ifa_name)
1083 == 0))
1084 {
1085 sin_src_p->sin_addr.s_addr =
1086 ((struct sockaddr_in *) (ifa->ifa_addr))
1087 ->sin_addr.s_addr;
1088 break;
1089 }
1090 }
1091 }
1092 }
1093 }
1094 }
1095 /* Free GSList. */
1096 if (routes)
1097 {
1098 for (routes_p = routes; routes_p; routes_p = routes_p->next)
1099 {
1100 if (((route_entry_t *) (routes_p->data))->interface)
1101 g_free (((route_entry_t *) (routes_p->data))->interface);
1102 }
1103 g_slist_free (routes);
1104 }
1105 }
1106 else if (storage_dest->ss_family == AF_INET6)
1107 {
1108 g_warning ("%s: IPv6 not yet implemented for this function. Will be "
1109 "implemented soon. Thanks for your patience.",
1110 __func__);
1111 }
1112
1113 return interface_out != NULL ? interface_out : NULL;
1114}
1115
1123static int
1124get_connected_udp_sock (struct sockaddr_storage *target_addr)
1125{
1126 int family = target_addr->ss_family;
1127 int sockfd = -1;
1128 if (family == AF_INET)
1129 {
1130 sockfd = socket (AF_INET, SOCK_DGRAM, 0);
1131 if (sockfd < 0)
1132 {
1133 g_warning ("Socket error: %s", strerror (errno));
1134 return -1;
1135 }
1136
1137 ((struct sockaddr_in *) target_addr)->sin_port = htons (9877);
1138 if (connect (sockfd, (struct sockaddr *) target_addr,
1139 sizeof (struct sockaddr_in))
1140 < 0)
1141 {
1142 g_warning ("Connect error: %s", strerror (errno));
1143 close (sockfd);
1144 return -1;
1145 }
1146 }
1147 else if (family == AF_INET6)
1148 {
1149 sockfd = socket (AF_INET6, SOCK_DGRAM, 0);
1150 if (sockfd < 0)
1151 {
1152 g_warning ("Socket error: %s", strerror (errno));
1153 return -1;
1154 }
1155 ((struct sockaddr_in6 *) target_addr)->sin6_port = htons (9877);
1156 if (connect (sockfd, (struct sockaddr *) target_addr,
1157 sizeof (struct sockaddr_in6))
1158 < 0)
1159 {
1160 g_warning ("Connect error: %s", strerror (errno));
1161 close (sockfd);
1162 return -1;
1163 }
1164 }
1165 return sockfd;
1166}
1167
1176static int
1177get_sock_addr (int sockfd, struct sockaddr_storage *sock_addr)
1178{
1179 socklen_t len;
1180 int family = sock_addr->ss_family;
1181 if (family == AF_INET)
1182 {
1183 len = sizeof (struct sockaddr_in);
1184 if (getsockname (sockfd, (struct sockaddr *) sock_addr, &len) < 0)
1185 {
1186 g_warning ("getsockname error: %s", strerror (errno));
1187 close (sockfd);
1188 return -1;
1189 }
1190 }
1191 else if (family == AF_INET6)
1192 {
1193 len = sizeof (struct sockaddr_in6);
1194 if (getsockname (sockfd, (struct sockaddr *) sock_addr, &len) < 0)
1195 {
1196 g_warning ("getsockname error:%s", strerror (errno));
1197 close (sockfd);
1198 return -1;
1199 }
1200 }
1201 return 0;
1202}
1203
1212static char *
1213get_ifname_from_ifaddr (struct sockaddr_storage *target_addr)
1214{
1215 struct ifaddrs *ifaddr, *ifa;
1216 int family = target_addr->ss_family;
1217 char *interface_out = NULL;
1218
1219 if (getifaddrs (&ifaddr) == -1)
1220 {
1221 g_warning ("%s: getifaddr failed: %s", __func__, strerror (errno));
1222 return NULL;
1223 }
1224 if (family == AF_INET)
1225 {
1226 struct sockaddr_in *sin;
1227 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1228 {
1229 if (!(ifa->ifa_flags & IFF_UP))
1230 continue;
1231 if (ifa->ifa_addr == NULL)
1232 continue;
1233 if (ifa->ifa_addr->sa_family == AF_INET)
1234 {
1235 sin = (struct sockaddr_in *) (ifa->ifa_addr);
1236 if (((struct sockaddr_in *) target_addr)->sin_addr.s_addr
1237 == sin->sin_addr.s_addr)
1238 interface_out = g_strdup (ifa->ifa_name);
1239 }
1240 }
1241 }
1242 else if (family == AF_INET6)
1243 {
1244 struct sockaddr_in6 *sin6;
1245 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1246 {
1247 if (!(ifa->ifa_flags & IFF_UP))
1248 continue;
1249 if (ifa->ifa_addr == NULL)
1250 continue;
1251 if (ifa->ifa_addr->sa_family == AF_INET6)
1252 {
1253 sin6 = (struct sockaddr_in6 *) (ifa->ifa_addr);
1254 if (IN6_ARE_ADDR_EQUAL (
1255 &(sin6->sin6_addr),
1256 &((struct sockaddr_in6 *) target_addr)->sin6_addr))
1257 interface_out = g_strdup (ifa->ifa_name);
1258 }
1259 }
1260 }
1261 freeifaddrs (ifaddr);
1262 return interface_out;
1263}
1264
1281char *
1282gvm_get_outgoing_iface (struct sockaddr_storage *target_addr)
1283{
1284 int family, sockfd;
1285 struct sockaddr_storage out_iface_addr;
1286 char *out_iface_str;
1287
1288 out_iface_str = NULL;
1289 family = target_addr->ss_family;
1290
1291 if (!target_addr)
1292 return NULL;
1293
1294 // get a connected udp socket
1295 if ((sockfd = get_connected_udp_sock (target_addr)) < 0)
1296 return NULL;
1297 // get socked address which is the addr of the interface we want to get
1298 out_iface_addr.ss_family = family;
1299 if (get_sock_addr (sockfd, &out_iface_addr) < 0)
1300 return NULL;
1301 // get interface name form interface address
1302 out_iface_str = get_ifname_from_ifaddr (&out_iface_addr);
1303 return out_iface_str;
1304}
GPtrArray * make_array(void)
Make a global array.
Definition array.c:25
void array_add(array_t *array, gpointer pointer)
Push a generic pointer onto an array.
Definition array.c:68
GPtrArray array_t
Definition array.h:16
void addr6_to_str(const struct in6_addr *addr6, char *str)
Stringifies an IP address.
Definition networking.c:261
int ipv6_is_enabled(void)
Checks if IPv6 support is enabled.
Definition networking.c:752
void ipv4_as_ipv6(const struct in_addr *ip4, struct in6_addr *ip6)
Maps an IPv4 address as an IPv6 address. eg. 192.168.10.20 would map to ::ffff:192....
Definition networking.c:243
static int get_connected_udp_sock(struct sockaddr_storage *target_addr)
Get a connected UDP socket.
Definition networking.c:1124
struct in6_addr global_source_addr6
Definition networking.c:52
char * gvm_get_outgoing_iface(struct sockaddr_storage *target_addr)
Get the outgoing interface name for a given destination addr.
Definition networking.c:1282
array_t * port_range_ranges(const char *port_range)
Create a range array from a port_range string.
Definition networking.c:601
void gvm_source_addr6(void *addr6)
Gives the source IPv6 address.
Definition networking.c:186
void gvm_source_addr(void *addr)
Gives the source IPv4 address.
Definition networking.c:174
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition networking.c:389
void gvm_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....
Definition networking.c:199
#define memdup
Definition networking.c:40
static int get_sock_addr(int sockfd, struct sockaddr_storage *sock_addr)
Get address from socket.
Definition networking.c:1177
static gboolean ip_islocalhost(struct sockaddr_storage *storage)
Determine if IP is localhost.
Definition networking.c:775
char global_source_iface[IFNAMSIZ]
Definition networking.c:46
static char * get_ifname_from_ifaddr(struct sockaddr_storage *target_addr)
Get iface name of iface matching the given interface address.
Definition networking.c:1213
void sockaddr_as_str(const struct sockaddr_storage *addr, char *str)
Convert an IP address to string format.
Definition networking.c:298
int validate_port_range(const char *port_range)
Validate a port range string.
Definition networking.c:460
char * addr6_as_str(const struct in6_addr *addr6)
Stringifies an IP address.
Definition networking.c:279
int gvm_resolve_as_addr6(const char *name, struct in6_addr *ip6)
Resolves a hostname to an IPv4-mapped IPv6 or IPv6 address.
Definition networking.c:443
int gvm_source_iface_init(const char *iface)
Initializes the source network interface name and related information.
Definition networking.c:64
gchar * gvm_routethrough(struct sockaddr_storage *storage_dest, struct sockaddr_storage *storage_source)
Get Interface which should be used for routing to destination addr.
Definition networking.c:994
char * gvm_source_addr6_str(void)
Gives the source IPv6 address in string format.
Definition networking.c:225
int gvm_source_set_socket(int socket, int port, int family)
Binds a socket to use the global source address.
Definition networking.c:136
int port_in_port_ranges(int pnum, port_protocol_t ptype, array_t *pranges)
Checks if a port num is in port ranges array.
Definition networking.c:728
struct in_addr global_source_addr
Definition networking.c:49
GSList * gvm_resolve_list(const char *name)
Returns a list of addresses that a hostname resolves to.
Definition networking.c:339
int gvm_source_iface_is_set(void)
Check if global_source global_source_iface is set.
Definition networking.c:121
char * gvm_source_addr_str(void)
Gives the source IPv4 address in string format.
Definition networking.c:211
static GSList * get_routes(void)
Get the entries of /proc/net/route as list of route_entry structs.
Definition networking.c:878
GVM Networking related API.
port_protocol_t
Possible port types.
Definition networking.h:25
@ PORT_PROTOCOL_TCP
Definition networking.h:26
@ PORT_PROTOCOL_UDP
Definition networking.h:27
A port range.
Definition networking.h:35
int start
Definition networking.h:40
int exclude
Definition networking.h:39
port_protocol_t type
Definition networking.h:41
int end
Definition networking.h:38
Definition networking.c:866
unsigned long dest
Definition networking.c:869
unsigned long mask
Definition networking.c:868
gchar * interface
Definition networking.c:867