Greenbone Vulnerability Management Libraries  22.8.0
networking.c File Reference

Implementation of GVM Networking related API. More...

#include "networking.h"
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <glib/gstdio.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
Include dependency graph for networking.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  route_entry
 

Macros

#define G_LOG_DOMAIN   "libgvm base"
 GLib log domain. More...
 
#define memdup   g_memdup
 

Typedefs

typedef struct route_entry route_entry_t
 

Functions

int gvm_source_iface_init (const char *iface)
 Initializes the source network interface name and related information. More...
 
int gvm_source_iface_is_set (void)
 Check if global_source global_source_iface is set. More...
 
int gvm_source_set_socket (int socket, int port, int family)
 Binds a socket to use the global source address. More...
 
void gvm_source_addr (void *addr)
 Gives the source IPv4 address. More...
 
void gvm_source_addr6 (void *addr6)
 Gives the source IPv6 address. More...
 
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.168.20.10. More...
 
char * gvm_source_addr_str (void)
 Gives the source IPv4 address in string format. More...
 
char * gvm_source_addr6_str (void)
 Gives the source IPv6 address in string format. More...
 
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.168.10.20. More...
 
void addr6_to_str (const struct in6_addr *addr6, char *str)
 Stringifies an IP address. More...
 
char * addr6_as_str (const struct in6_addr *addr6)
 Stringifies an IP address. More...
 
void sockaddr_as_str (const struct sockaddr_storage *addr, char *str)
 Convert an IP address to string format. More...
 
GSList * gvm_resolve_list (const char *name)
 Returns a list of addresses that a hostname resolves to. More...
 
int gvm_resolve (const char *name, void *dst, int family)
 Resolves a hostname to an IPv4 or IPv6 address. More...
 
int gvm_resolve_as_addr6 (const char *name, struct in6_addr *ip6)
 Resolves a hostname to an IPv4-mapped IPv6 or IPv6 address. More...
 
int validate_port_range (const char *port_range)
 Validate a port range string. More...
 
array_tport_range_ranges (const char *port_range)
 Create a range array from a port_range string. More...
 
int port_in_port_ranges (int pnum, port_protocol_t ptype, array_t *pranges)
 Checks if a port num is in port ranges array. More...
 
int ipv6_is_enabled (void)
 Checks if IPv6 support is enabled. More...
 
static gboolean ip_islocalhost (struct sockaddr_storage *storage)
 Determine if IP is localhost. More...
 
static GSList * get_routes (void)
 Get the entries of /proc/net/route as list of route_entry structs. More...
 
gchar * gvm_routethrough (struct sockaddr_storage *storage_dest, struct sockaddr_storage *storage_source)
 Get Interface which should be used for routing to destination addr. More...
 
static int get_connected_udp_sock (struct sockaddr_storage *target_addr)
 Get a connected UDP socket. More...
 
static int get_sock_addr (int sockfd, struct sockaddr_storage *sock_addr)
 Get address from socket. More...
 
static char * get_ifname_from_ifaddr (struct sockaddr_storage *target_addr)
 Get iface name of iface matching the given interface address. More...
 
char * gvm_get_outgoing_iface (struct sockaddr_storage *target_addr)
 Get the outgoing interface name for a given destination addr. More...
 

Variables

char global_source_iface [IFNAMSIZ] = {'\0'}
 
struct in_addr global_source_addr = {.s_addr = 0}
 
struct in6_addr global_source_addr6 = {.s6_addr32 = {0, 0, 0, 0}}
 

Detailed Description

Implementation of GVM Networking related API.

Definition in file networking.c.

Macro Definition Documentation

◆ G_LOG_DOMAIN

#define G_LOG_DOMAIN   "libgvm base"

GLib log domain.

Definition at line 35 of file networking.c.

◆ memdup

#define memdup   g_memdup

Definition at line 40 of file networking.c.

Typedef Documentation

◆ route_entry_t

typedef struct route_entry route_entry_t

Definition at line 775 of file networking.c.

Function Documentation

◆ addr6_as_str()

char* addr6_as_str ( const struct in6_addr *  addr6)

Stringifies an IP address.

Parameters
[in]addr6IP address.
Returns
IP as string. NULL otherwise.

Definition at line 279 of file networking.c.

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 }

References addr6_to_str().

Here is the call graph for this function:

◆ addr6_to_str()

void addr6_to_str ( const struct in6_addr *  addr6,
char *  str 
)

Stringifies an IP address.

Parameters
[in]addr6IP address.
[out]strBuffer to output IP.

Definition at line 261 of file networking.c.

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 }

Referenced by addr6_as_str(), and host_name_verify().

Here is the caller graph for this function:

◆ get_connected_udp_sock()

static int get_connected_udp_sock ( struct sockaddr_storage *  target_addr)
static

Get a connected UDP socket.

Parameters
target_addrHolds addr for connect call
Returns
Socket number or -1 on error.

Definition at line 1124 of file networking.c.

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 }

Referenced by gvm_get_outgoing_iface().

Here is the caller graph for this function:

◆ get_ifname_from_ifaddr()

static char* get_ifname_from_ifaddr ( struct sockaddr_storage *  target_addr)
static

Get iface name of iface matching the given interface address.

Parameters
[in]target_addrAddress of interface.
Returns
Interface name of matching interface which to be freed by the caller. Null if no interface found or error.

Definition at line 1213 of file networking.c.

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 }

Referenced by gvm_get_outgoing_iface().

Here is the caller graph for this function:

◆ get_routes()

static GSList* get_routes ( void  )
static

Get the entries of /proc/net/route as list of route_entry structs.

Returns
GSList of route_entry structs. NULL if no routes found or Error.

Definition at line 878 of file networking.c.

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 }

References route_entry::dest, route_entry::interface, and route_entry::mask.

Referenced by Ensure(), gvm_routethough(), and gvm_routethrough().

Here is the caller graph for this function:

◆ get_sock_addr()

static int get_sock_addr ( int  sockfd,
struct sockaddr_storage *  sock_addr 
)
static

Get address from socket.

Parameters
[in]sockfdSocket from which to get the address.
[out]sock_addrLocation to write address into.
Returns
0 on success, -1 on error.

Definition at line 1177 of file networking.c.

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 }

Referenced by gvm_get_outgoing_iface().

Here is the caller graph for this function:

◆ gvm_get_outgoing_iface()

char* gvm_get_outgoing_iface ( struct sockaddr_storage *  target_addr)

Get the outgoing interface name for a given destination addr.

A UDP socket is connected and its address retrieved. The address is the address of the interface of the outgoing interface. Its is determined by the kernel. We then search the list of interfaces for this address to determine the interface name. This method has the downside that if two interfaces with same addr are UP, a wrong interface might be returned because we can only retrieve the interface addr which was chosen by the kernel and nothing else (like e.g. interface number).

Parameters
[in]target_addrDestination address.
Returns
Name of outgoing interface which has to be freed by caller. NULL if no interface found or Error.

Definition at line 1282 of file networking.c.

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 }

References get_connected_udp_sock(), get_ifname_from_ifaddr(), and get_sock_addr().

Here is the call graph for this function:

◆ gvm_resolve()

int gvm_resolve ( const char *  name,
void *  dst,
int  family 
)

Resolves a hostname to an IPv4 or IPv6 address.

Parameters
[in]nameHostname to resolve.
[out]dstBuffer to store resolved address. Size must be at least 4 bytes for AF_INET and 16 bytes for AF_INET6.
[in]familyEither AF_INET or AF_INET6.
Returns
-1 if error, 0 otherwise.

Definition at line 389 of file networking.c.

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 }

References ipv4_as_ipv6().

Referenced by gvm_host_resolve(), and gvm_resolve_as_addr6().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gvm_resolve_as_addr6()

int gvm_resolve_as_addr6 ( const char *  name,
struct in6_addr *  ip6 
)

Resolves a hostname to an IPv4-mapped IPv6 or IPv6 address.

Parameters
[in]nameHostname to resolve.
[out]ip6Buffer to store resolved address.
Returns
-1 if error, 0 otherwise.

Definition at line 443 of file networking.c.

444 {
445  return gvm_resolve (name, ip6, AF_UNSPEC);
446 }

References gvm_resolve().

Here is the call graph for this function:

◆ gvm_resolve_list()

GSList* gvm_resolve_list ( const char *  name)

Returns a list of addresses that a hostname resolves to.

Parameters
[in]nameHostname to resolve.
Returns
List of addresses, NULL otherwise.

Definition at line 339 of file networking.c.

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 }

References ipv4_as_ipv6(), and memdup.

Referenced by gvm_hosts_resolve(), and host_name_verify().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gvm_routethrough()

gchar* gvm_routethrough ( struct sockaddr_storage *  storage_dest,
struct sockaddr_storage *  storage_source 
)

Get Interface which should be used for routing to destination addr.

This function should be used sparingly as it parses /proc/net/route for every call.

Parameters
[in]storage_destDestination address.
[out]storage_sourceSource address. Is set to either address of the interface we use or global source address if set. Only gets filled if storage_source != NULL.
Returns
Interface name of interface used for routing to destination address. NULL if no interface found or Error.

Definition at line 994 of file networking.c.

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 }

References get_routes(), gvm_source_addr(), and ip_islocalhost().

Referenced by Ensure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gvm_source_addr()

void gvm_source_addr ( void *  addr)

Gives the source IPv4 address.

Parameters
[out]addrBuffer of at least 4 bytes.

Definition at line 174 of file networking.c.

175 {
176  if (addr)
177  memcpy (addr, &global_source_addr.s_addr, 4);
178 }

References global_source_addr.

Referenced by Ensure(), gvm_routethrough(), gvm_source_set_socket(), and main().

Here is the caller graph for this function:

◆ gvm_source_addr6()

void gvm_source_addr6 ( void *  addr6)

Gives the source IPv6 address.

Parameters
[out]addr6Buffer of at least 16 bytes.

Definition at line 186 of file networking.c.

187 {
188  if (addr6)
189  memcpy (addr6, &global_source_addr6.s6_addr, 16);
190 }

References global_source_addr6.

Referenced by gvm_source_set_socket().

Here is the caller graph for this function:

◆ gvm_source_addr6_str()

char* gvm_source_addr6_str ( void  )

Gives the source IPv6 address in string format.

Returns
Source IPv6 string. Free with g_free().

Definition at line 225 of file networking.c.

226 {
227  char *str = g_malloc0 (INET6_ADDRSTRLEN);
228 
229  inet_ntop (AF_INET6, &global_source_addr6, str, INET6_ADDRSTRLEN);
230  return str;
231 }

References global_source_addr6.

◆ gvm_source_addr_as_addr6()

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.168.20.10.

Parameters
[out]addr6Buffer of at least 16 bytes.

Definition at line 199 of file networking.c.

200 {
201  if (addr6)
203 }

References global_source_addr, and ipv4_as_ipv6().

Here is the call graph for this function:

◆ gvm_source_addr_str()

char* gvm_source_addr_str ( void  )

Gives the source IPv4 address in string format.

Returns
Source IPv4 string. Free with g_free().

Definition at line 211 of file networking.c.

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 }

References global_source_addr.

◆ gvm_source_iface_init()

int gvm_source_iface_init ( const char *  iface)

Initializes the source network interface name and related information.

Parameters
[in]ifaceName of network interface to use as source interface.
Returns
0 if success. If error, return 1 and reset source values to default.

Definition at line 64 of file networking.c.

65 {
66  struct ifaddrs *ifaddr, *ifa;
67  int ret = 1;
68 
69  bzero (global_source_iface, sizeof (global_source_iface));
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 }

References global_source_addr, global_source_addr6, and global_source_iface.

Referenced by Ensure().

Here is the caller graph for this function:

◆ gvm_source_iface_is_set()

int gvm_source_iface_is_set ( void  )

Check if global_source global_source_iface is set.

Returns
1 if set, 0 otherwise.

Definition at line 121 of file networking.c.

122 {
123  return *global_source_iface != '\0';
124 }

References global_source_iface.

◆ gvm_source_set_socket()

int gvm_source_set_socket ( int  socket,
int  port,
int  family 
)

Binds a socket to use the global source address.

Parameters
[in]socketSocket to set source address for.
[in]portNetwork port for socket.
[in]familyFamily of socket. AF_INET or AF_INET6.
Returns
0 if success, -1 if error.

Definition at line 136 of file networking.c.

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 }

References gvm_source_addr(), and gvm_source_addr6().

Here is the call graph for this function:

◆ ip_islocalhost()

static gboolean ip_islocalhost ( struct sockaddr_storage *  storage)
static

Determine if IP is localhost.

Returns
True if IP is localhost, else false.

Definition at line 775 of file networking.c.

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 }

Referenced by Ensure(), gvm_routethough(), and gvm_routethrough().

Here is the caller graph for this function:

◆ ipv4_as_ipv6()

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.168.10.20.

Parameters
[in]ip4IPv4 address to map.
[out]ip6Buffer to store the IPv6 address.

Definition at line 243 of file networking.c.

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 }

Referenced by gvm_host_get_addr6(), gvm_resolve(), gvm_resolve_list(), and gvm_source_addr_as_addr6().

Here is the caller graph for this function:

◆ ipv6_is_enabled()

int ipv6_is_enabled ( void  )

Checks if IPv6 support is enabled.

Returns
1 if IPv6 is enabled, 0 if disabled.

Definition at line 752 of file networking.c.

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 }

◆ port_in_port_ranges()

int port_in_port_ranges ( int  pnum,
port_protocol_t  ptype,
array_t pranges 
)

Checks if a port num is in port ranges array.

Parameters
[in]pnumPort number.
[in]ptypePort type.
[in]prangesArray of port ranges.
Returns
1 if port in port ranges, 0 otherwise.

Definition at line 728 of file networking.c.

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 }

References range::start, and range::type.

Referenced by Ensure(), and main().

Here is the caller graph for this function:

◆ port_range_ranges()

array_t* port_range_ranges ( const char *  port_range)

Create a range array from a port_range string.

Parameters
[in]port_rangeValid port_range string.
Returns
Range array or NULL if port_range invalid or NULL.

Definition at line 601 of file networking.c.

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 }

References array_add(), range::end, range::exclude, make_array(), PORT_PROTOCOL_TCP, PORT_PROTOCOL_UDP, range::start, range::type, and validate_port_range().

Referenced by Ensure(), and main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sockaddr_as_str()

void sockaddr_as_str ( const struct sockaddr_storage *  addr,
char *  str 
)

Convert an IP address to string format.

Parameters
[in]addrAddress to convert.
[out]strBuffer of INET6_ADDRSTRLEN size.

Definition at line 298 of file networking.c.

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 }

◆ validate_port_range()

int validate_port_range ( const char *  port_range)

Validate a port range string.

Accepts ranges in form of "103,U:200-1024,3000-4000,T:3-4,U:7".

Parameters
[in]port_rangeA port range.
Returns
0 success, 1 failed.

Definition at line 460 of file networking.c.

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 
588 fail:
589  g_strfreev (split);
590  return 1;
591 }

Referenced by Ensure(), main(), and port_range_ranges().

Here is the caller graph for this function:

Variable Documentation

◆ global_source_addr

struct in_addr global_source_addr = {.s_addr = 0}

◆ global_source_addr6

struct in6_addr global_source_addr6 = {.s6_addr32 = {0, 0, 0, 0}}

Definition at line 46 of file networking.c.

Referenced by gvm_source_addr6(), gvm_source_addr6_str(), and gvm_source_iface_init().

◆ global_source_iface

char global_source_iface[IFNAMSIZ] = {'\0'}

Definition at line 46 of file networking.c.

Referenced by gvm_source_iface_init(), and gvm_source_iface_is_set().

global_source_iface
char global_source_iface[IFNAMSIZ]
Definition: networking.c:46
addr6_to_str
void addr6_to_str(const struct in6_addr *addr6, char *str)
Stringifies an IP address.
Definition: networking.c:261
memdup
#define memdup
Definition: networking.c:40
get_sock_addr
static int get_sock_addr(int sockfd, struct sockaddr_storage *sock_addr)
Get address from socket.
Definition: networking.c:1177
get_connected_udp_sock
static int get_connected_udp_sock(struct sockaddr_storage *target_addr)
Get a connected UDP socket.
Definition: networking.c:1124
array_t
GPtrArray array_t
Definition: array.h:16
route_entry::mask
unsigned long mask
Definition: networking.c:868
route_entry::dest
unsigned long dest
Definition: networking.c:869
ipv4_as_ipv6
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
range::type
port_protocol_t type
Definition: networking.h:41
route_entry
Definition: networking.c:866
gvm_resolve
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition: networking.c:389
make_array
GPtrArray * make_array(void)
Make a global array.
Definition: array.c:25
ip_islocalhost
static gboolean ip_islocalhost(struct sockaddr_storage *storage)
Determine if IP is localhost.
Definition: networking.c:775
PORT_PROTOCOL_UDP
@ PORT_PROTOCOL_UDP
Definition: networking.h:27
array_add
void array_add(array_t *array, gpointer pointer)
Push a generic pointer onto an array.
Definition: array.c:68
global_source_addr
struct in_addr global_source_addr
Definition: networking.c:49
range::exclude
int exclude
Definition: networking.h:39
get_routes
static GSList * get_routes(void)
Get the entries of /proc/net/route as list of route_entry structs.
Definition: networking.c:878
get_ifname_from_ifaddr
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
gvm_source_addr
void gvm_source_addr(void *addr)
Gives the source IPv4 address.
Definition: networking.c:174
validate_port_range
int validate_port_range(const char *port_range)
Validate a port range string.
Definition: networking.c:460
PORT_PROTOCOL_TCP
@ PORT_PROTOCOL_TCP
Definition: networking.h:26
range::end
int end
Definition: networking.h:38
global_source_addr6
struct in6_addr global_source_addr6
Definition: networking.c:52
range
A port range.
Definition: networking.h:35
gvm_source_addr6
void gvm_source_addr6(void *addr6)
Gives the source IPv6 address.
Definition: networking.c:186
range::start
int start
Definition: networking.h:40
route_entry::interface
gchar * interface
Definition: networking.c:867