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

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.

Referenced by gvm_resolve_list().

Typedef Documentation

◆ route_entry_t

typedef struct route_entry route_entry_t

Definition at line 862 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}
void addr6_to_str(const struct in6_addr *addr6, char *str)
Stringifies an IP address.
Definition networking.c:261

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:

◆ free_routes()

void free_routes ( GSList * routes)
static

Free the list of routes.

Parameters
GSListof route_entry structs, or NULL.

Definition at line 987 of file networking.c.

988{
989 if (routes)
990 {
991 GSList *routes_p;
992
993 for (routes_p = routes; routes_p; routes_p = routes_p->next)
994 {
995 if (((route_entry_t *) (routes_p->data))->interface)
996 g_free (((route_entry_t *) (routes_p->data))->interface);
997 g_free (routes_p->data);
998 }
999 g_slist_free (routes);
1000 }
1001}
struct route_entry route_entry_t
Definition networking.c:862

Referenced by Ensure(), and gvm_routethrough().

Here is the caller graph for this function:

◆ get_connected_udp_sock()

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 1140 of file networking.c.

1141{
1142 int family = target_addr->ss_family;
1143 int sockfd = -1;
1144 if (family == AF_INET)
1145 {
1146 sockfd = socket (AF_INET, SOCK_DGRAM, 0);
1147 if (sockfd < 0)
1148 {
1149 g_warning ("Socket error: %s", strerror (errno));
1150 return -1;
1151 }
1152
1153 ((struct sockaddr_in *) target_addr)->sin_port = htons (9877);
1154 if (connect (sockfd, (struct sockaddr *) target_addr,
1155 sizeof (struct sockaddr_in))
1156 < 0)
1157 {
1158 g_warning ("Connect error: %s", strerror (errno));
1159 close (sockfd);
1160 return -1;
1161 }
1162 }
1163 else if (family == AF_INET6)
1164 {
1165 sockfd = socket (AF_INET6, SOCK_DGRAM, 0);
1166 if (sockfd < 0)
1167 {
1168 g_warning ("Socket error: %s", strerror (errno));
1169 return -1;
1170 }
1171 ((struct sockaddr_in6 *) target_addr)->sin6_port = htons (9877);
1172 if (connect (sockfd, (struct sockaddr *) target_addr,
1173 sizeof (struct sockaddr_in6))
1174 < 0)
1175 {
1176 g_warning ("Connect error: %s", strerror (errno));
1177 close (sockfd);
1178 return -1;
1179 }
1180 }
1181 return sockfd;
1182}

Referenced by gvm_get_outgoing_iface().

Here is the caller graph for this function:

◆ get_ifname_from_ifaddr()

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 1229 of file networking.c.

1230{
1231 struct ifaddrs *ifaddr, *ifa;
1232 int family = target_addr->ss_family;
1233 char *interface_out = NULL;
1234
1235 if (getifaddrs (&ifaddr) == -1)
1236 {
1237 g_warning ("%s: getifaddr failed: %s", __func__, strerror (errno));
1238 return NULL;
1239 }
1240 if (family == AF_INET)
1241 {
1242 struct sockaddr_in *sin;
1243 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1244 {
1245 if (!(ifa->ifa_flags & IFF_UP))
1246 continue;
1247 if (ifa->ifa_addr == NULL)
1248 continue;
1249 if (ifa->ifa_addr->sa_family == AF_INET)
1250 {
1251 sin = (struct sockaddr_in *) (ifa->ifa_addr);
1252 if (((struct sockaddr_in *) target_addr)->sin_addr.s_addr
1253 == sin->sin_addr.s_addr)
1254 interface_out = g_strdup (ifa->ifa_name);
1255 }
1256 }
1257 }
1258 else if (family == AF_INET6)
1259 {
1260 struct sockaddr_in6 *sin6;
1261 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1262 {
1263 if (!(ifa->ifa_flags & IFF_UP))
1264 continue;
1265 if (ifa->ifa_addr == NULL)
1266 continue;
1267 if (ifa->ifa_addr->sa_family == AF_INET6)
1268 {
1269 sin6 = (struct sockaddr_in6 *) (ifa->ifa_addr);
1270 if (IN6_ARE_ADDR_EQUAL (
1271 &(sin6->sin6_addr),
1272 &((struct sockaddr_in6 *) target_addr)->sin6_addr))
1273 interface_out = g_strdup (ifa->ifa_name);
1274 }
1275 }
1276 }
1277 freeifaddrs (ifaddr);
1278 return interface_out;
1279}

Referenced by gvm_get_outgoing_iface().

Here is the caller graph for this function:

◆ get_routes()

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 char_p = strchr (interface, ':');
953 if (char_p)
954 {
955 *char_p = '\0';
956 }
957 dest = strtoul (items_in_line[1], NULL, 16);
958 mask = strtoul (items_in_line[7], NULL, 16);
959
960 /* Fill GSList entry. */
961 entry = g_malloc0 (sizeof (route_entry_t));
962 entry->interface = interface;
963 entry->dest = dest;
964 entry->mask = mask;
965 routes = g_slist_append (routes, entry);
966
967 g_strfreev (items_in_line);
968 g_free (line);
969 }
970
971 status = g_io_channel_shutdown (file_channel, TRUE, &err);
972 g_io_channel_unref (file_channel);
973 if ((G_IO_STATUS_NORMAL != status) || err)
974 g_warning ("%s: %s", __func__,
975 err ? err->message
976 : "g_io_channel_shutdown() was not successful");
977
978 return routes;
979}
unsigned long dest
Definition networking.c:869
unsigned long mask
Definition networking.c:868
gchar * interface
Definition networking.c:867

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()

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 1193 of file networking.c.

1194{
1195 socklen_t len;
1196 int family = sock_addr->ss_family;
1197 if (family == AF_INET)
1198 {
1199 len = sizeof (struct sockaddr_in);
1200 if (getsockname (sockfd, (struct sockaddr *) sock_addr, &len) < 0)
1201 {
1202 g_warning ("getsockname error: %s", strerror (errno));
1203 close (sockfd);
1204 return -1;
1205 }
1206 }
1207 else if (family == AF_INET6)
1208 {
1209 len = sizeof (struct sockaddr_in6);
1210 if (getsockname (sockfd, (struct sockaddr *) sock_addr, &len) < 0)
1211 {
1212 g_warning ("getsockname error:%s", strerror (errno));
1213 close (sockfd);
1214 return -1;
1215 }
1216 }
1217 return 0;
1218}

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 1298 of file networking.c.

1299{
1300 int family, sockfd;
1301 struct sockaddr_storage out_iface_addr;
1302 char *out_iface_str;
1303
1304 out_iface_str = NULL;
1305 family = target_addr->ss_family;
1306
1307 if (!target_addr)
1308 return NULL;
1309
1310 // get a connected udp socket
1311 sockfd = get_connected_udp_sock (target_addr);
1312 if (sockfd < 0)
1313 return NULL;
1314 // get socked address which is the addr of the interface we want to get
1315 out_iface_addr.ss_family = family;
1316 if (get_sock_addr (sockfd, &out_iface_addr) < 0)
1317 return NULL;
1318 // get interface name form interface address
1319 out_iface_str = get_ifname_from_ifaddr (&out_iface_addr);
1320 return out_iface_str;
1321}
static int get_connected_udp_sock(struct sockaddr_storage *target_addr)
Get a connected UDP socket.
static int get_sock_addr(int sockfd, struct sockaddr_storage *sock_addr)
Get address from socket.
static char * get_ifname_from_ifaddr(struct sockaddr_storage *target_addr)
Get iface name of iface matching the given interface address.

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}
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

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}
int gvm_resolve(const char *name, void *dst, int family)
Resolves a hostname to an IPv4 or IPv6 address.
Definition networking.c:389

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}
#define memdup
Definition networking.c:40

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 1018 of file networking.c.

1020{
1021 struct ifaddrs *ifaddr, *ifa;
1022 gchar *interface_out;
1023
1024 interface_out = NULL;
1025
1026 if (!storage_dest)
1027 return NULL;
1028
1029 if (getifaddrs (&ifaddr) == -1)
1030 {
1031 g_debug ("%s: getifaddr failed: %s", __func__, strerror (errno));
1032 return NULL;
1033 }
1034
1035 /* IPv4. */
1036 if (storage_dest->ss_family == AF_INET)
1037 {
1038 GSList *routes;
1039
1040 routes = get_routes ();
1041
1042 /* Set storage_source to localhost if storage_source was supplied and
1043 * return name of loopback interface. */
1044 if (ip_islocalhost (storage_dest))
1045 {
1046 // TODO: check for (storage_source->ss_family == AF_INET)
1047 if (storage_source)
1048 {
1049 struct sockaddr_in *sin_p = (struct sockaddr_in *) storage_source;
1050 sin_p->sin_addr.s_addr = htonl (0x7F000001);
1051 }
1052
1053 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1054 {
1055 if (ifa->ifa_addr && (ifa->ifa_addr->sa_family == AF_INET)
1056 && (ifa->ifa_flags & (IFF_LOOPBACK)))
1057 {
1058 interface_out = g_strdup (ifa->ifa_name);
1059 break;
1060 }
1061 }
1062 }
1063 else
1064 {
1065 struct sockaddr_in *sin_dest_p, *sin_src_p;
1066 struct in_addr global_src;
1067 unsigned long best_match;
1068 GSList *routes_p;
1069
1070 /* Check if global_source_addr in use. */
1071 gvm_source_addr (&global_src);
1072
1073 sin_dest_p = (struct sockaddr_in *) storage_dest;
1074 sin_src_p = (struct sockaddr_in *) storage_source;
1075 /* Check routes for matching address. Get interface name and set
1076 * storage_source*/
1077 for (best_match = 0, routes_p = routes; routes_p;
1078 routes_p = routes_p->next)
1079 {
1080 if (((sin_dest_p->sin_addr.s_addr
1081 & ((route_entry_t *) (routes_p->data))->mask)
1082 == ((route_entry_t *) (routes_p->data))->dest)
1083 && (((route_entry_t *) (routes_p->data))->mask >= best_match))
1084 {
1085 /* Interface of matching route.*/
1086 g_free (interface_out);
1087 interface_out =
1088 g_strdup (((route_entry_t *) (routes_p->data))->interface);
1089 best_match = ((route_entry_t *) (routes_p->data))->mask;
1090
1091 if (!storage_source)
1092 continue;
1093
1094 /* Set storage_source to global source if global source
1095 * present.*/
1096 if (global_src.s_addr != INADDR_ANY)
1097 sin_src_p->sin_addr.s_addr = global_src.s_addr;
1098 /* Set storage_source to addr of matching interface if no
1099 * global source present.*/
1100 else
1101 {
1102 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
1103 {
1104 if (ifa->ifa_addr
1105 && (ifa->ifa_addr->sa_family == AF_INET)
1106 && (g_strcmp0 (interface_out, ifa->ifa_name)
1107 == 0))
1108 {
1109 sin_src_p->sin_addr.s_addr =
1110 ((struct sockaddr_in *) (ifa->ifa_addr))
1111 ->sin_addr.s_addr;
1112 break;
1113 }
1114 }
1115 }
1116 }
1117 }
1118 }
1119 free_routes (routes);
1120 }
1121 else if (storage_dest->ss_family == AF_INET6)
1122 {
1123 g_warning ("%s: IPv6 not yet implemented for this function. Will be "
1124 "implemented soon. Thanks for your patience.",
1125 __func__);
1126 }
1127
1128 freeifaddrs (ifaddr);
1129 return interface_out != NULL ? interface_out : NULL;
1130}
static void free_routes(GSList *routes)
Free the list of routes.
Definition networking.c:987
void gvm_source_addr(void *addr)
Gives the source IPv4 address.
Definition networking.c:174
static gboolean ip_islocalhost(struct sockaddr_storage *storage)
Determine if IP is localhost.
Definition networking.c:775
static GSList * get_routes(void)
Get the entries of /proc/net/route as list of route_entry structs.
Definition networking.c:878

References free_routes(), 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}
struct in_addr global_source_addr
Definition networking.c:49

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}
struct in6_addr global_source_addr6
Definition networking.c:52

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
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}
char global_source_iface[IFNAMSIZ]
Definition networking.c:46

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}
void gvm_source_addr6(void *addr6)
Gives the source IPv6 address.
Definition networking.c:186

References gvm_source_addr(), and gvm_source_addr6().

Here is the call graph for this function:

◆ ip_islocalhost()

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}
struct range range_t
Definition networking.h:43
A port range.
Definition networking.h:35
int start
Definition networking.h:40
port_protocol_t type
Definition networking.h:41

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}
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
int validate_port_range(const char *port_range)
Validate a port range string.
Definition networking.c:460
@ PORT_PROTOCOL_TCP
Definition networking.h:26
@ PORT_PROTOCOL_UDP
Definition networking.h:27
int exclude
Definition networking.h:39
int end
Definition networking.h:38

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

Referenced by Ensure(), Ensure(), 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}

Definition at line 49 of file networking.c.

49{.s_addr = 0};

Referenced by gvm_source_addr(), gvm_source_addr_as_addr6(), gvm_source_addr_str(), and gvm_source_iface_init().

◆ global_source_addr6

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

Definition at line 52 of file networking.c.

52{.s6_addr32 = {0, 0, 0, 0}};

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.

46{'\0'};

Referenced by gvm_source_iface_init(), and gvm_source_iface_is_set().