diff options
| author | Michael Biebl <biebl@debian.org> | 2025-02-12 13:46:50 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-02-12 13:46:50 +0100 |
| commit | 8bdf070ff046f482f6eb5e2b15ebc216f5d1e3da (patch) | |
| tree | f706478d189d54c6532e8863d4b0d5ff5575af60 /src/libnm-core-aux-intern | |
| parent | 818258cf34b83fbc754633295e1052d4752d7b15 (diff) | |
New upstream version 1.51.90 upstream/1.51.90
Diffstat (limited to 'src/libnm-core-aux-intern')
| -rw-r--r-- | src/libnm-core-aux-intern/meson.build | 1 | ||||
| -rw-r--r-- | src/libnm-core-aux-intern/nm-libnm-core-utils.c | 462 | ||||
| -rw-r--r-- | src/libnm-core-aux-intern/nm-libnm-core-utils.h | 57 | ||||
| -rw-r--r-- | src/libnm-core-aux-intern/tests/meson.build | 34 | ||||
| -rw-r--r-- | src/libnm-core-aux-intern/tests/test-libnm-core-utils.c | 364 |
5 files changed, 825 insertions, 93 deletions
diff --git a/src/libnm-core-aux-intern/meson.build b/src/libnm-core-aux-intern/meson.build index a58921e3..f413cde4 100644 --- a/src/libnm-core-aux-intern/meson.build +++ b/src/libnm-core-aux-intern/meson.build @@ -1,4 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later +libnm_core_aux_intern_inc = include_directories('.') libnm_core_aux_intern = static_library( 'nm-core-aux-intern', diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.c b/src/libnm-core-aux-intern/nm-libnm-core-utils.c index b38accb2..5e7b90a4 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.c +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c @@ -479,6 +479,151 @@ nm_utils_validate_dhcp_dscp(const char *dscp, GError **error) } gboolean +nm_utils_validate_shared_dhcp_range(const char *shared_dhcp_range, + GPtrArray *addresses, + GError **error) +{ + char *start_address_str; + char *end_address_str; + NMIPAddress *interface_address_with_prefix; + NMIPAddr interface_address; + NMIPAddr start_address; + NMIPAddr end_address; + guint32 i; + guint32 mask; + guint32 prefix_length; + guint32 start_network; + guint32 end_network; + guint32 interface_network; + guint32 start_ip_length; + bool range_is_in_interface_network; + gs_free char *to_free = NULL; + + g_return_val_if_fail(!error || !(*error), FALSE); + + if (!shared_dhcp_range) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("NULL DHCP range; it should be provided as <START_IP>,<END_IP>.")); + return FALSE; + } + + if (!*shared_dhcp_range) { + return TRUE; + } + + if (!addresses) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Non-NULL range and NULL addresses detected.")); + return FALSE; + } + + end_address_str = strchr(shared_dhcp_range, ','); + if (!end_address_str) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Invalid DHCP range; it should be provided as <START_IP>,<END_IP>.")); + return FALSE; + } + + start_ip_length = end_address_str - shared_dhcp_range; + if (start_ip_length > 15) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Start IP has invalid length.")); + return FALSE; + } + + start_address_str = nm_strndup_a(200, shared_dhcp_range, start_ip_length, &to_free); + ++end_address_str; /* end address is pointing to ',', shift it to the actual address */ + + if (!nm_inet_parse_bin(AF_INET, start_address_str, NULL, &start_address)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Start IP is invalid.")); + return FALSE; + } + + if (!nm_inet_parse_bin(AF_INET, end_address_str, NULL, &end_address)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("End IP is invalid.")); + return FALSE; + } + + if (ntohl(start_address.addr4) > ntohl(end_address.addr4)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Start IP should be lower than the end IP.")); + return FALSE; + } + + range_is_in_interface_network = FALSE; + for (i = 0; i < (*addresses).len; ++i) { + interface_address_with_prefix = (NMIPAddress *) addresses->pdata[i]; + nm_inet_parse_bin(AF_INET, + nm_ip_address_get_address(interface_address_with_prefix), + NULL, + &interface_address); + prefix_length = nm_ip_address_get_prefix(interface_address_with_prefix); + mask = nm_utils_ip4_prefix_to_netmask(prefix_length); + + interface_network = interface_address.addr4 & mask; + start_network = start_address.addr4 & mask; + end_network = end_address.addr4 & mask; + + if (start_network == interface_network && end_network == interface_network) { + range_is_in_interface_network = TRUE; + break; + } + } + + if (!range_is_in_interface_network) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Requested range is not in any network configured on the interface.")); + return FALSE; + } + + return TRUE; +} + +gboolean +nm_utils_validate_shared_dhcp_lease_time(int shared_dhcp_lease_time, GError **error) +{ + g_return_val_if_fail(!error || !(*error), FALSE); + + if (shared_dhcp_lease_time == 0 || shared_dhcp_lease_time == G_MAXINT32) { + return TRUE; + } + + if (shared_dhcp_lease_time < NM_MIN_FINITE_LEASE_TIME + || NM_MAX_FINITE_LEASE_TIME < shared_dhcp_lease_time) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Invalid DHCP lease time value; it should be either default or a positive " + "number between %u and %u or %s."), + NM_MIN_FINITE_LEASE_TIME, + NM_MAX_FINITE_LEASE_TIME, + NM_INFINITE_LEASE_TIME); + return FALSE; + } + + return TRUE; +} + +gboolean nm_settings_connection_validate_permission_user(const char *item, gssize len) { gsize l; @@ -555,112 +700,295 @@ nm_mptcp_flags_normalize(NMMptcpFlags flags) /*****************************************************************************/ +/* + * nm_dns_uri_parse: + * @addr_family: the address family, or AF_UNSPEC to autodetect it + * @str: the name server URI string to parse + * @dns: the name server descriptor to fill, or %NULL + * + * Parses the given name server URI string. Each name server is represented + * by the following grammar: + * + * NAMESERVER := { PLAIN | TLS_URI | UDP_URI } + * PLAIN := { ipv4address | ipv6address } [ '#' SERVERNAME ] + * TLS_URI := 'dns+tls://' URI_ADDRESS [ ':' PORT ] [ '#' SERVERNAME ] + * UDP_URI := 'dns+udp://' URI_ADDRESS [ ':' PORT ] + * URI_ADDRESS := { ipv4address | '[' ipv6address [ '%' ifname ] ']' } + * + * Examples: + * + * 192.0.2.0 + * 192.0.2.0#example.com + * 2001:db8::1 + * dns+tls://192.0.2.0 + * dns+tls://[2001:db8::1] + * dns+tls://192.0.2.0:53#example.com + * dns+udp://[fe80::1%enp1s0] + * + * Note that on return, the lifetime of the members in the @dns struct is + * the same as the input string @str. + * + * Returns: %TRUE on success, %FALSE on failure + */ gboolean -nm_utils_dnsname_parse(int addr_family, - const char *dns, - int *out_addr_family, - gpointer /* (NMIPAddr **) */ out_addr, - const char **out_servername) +nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns) { - gs_free char *dns_heap = NULL; - const char *s; - NMIPAddr addr; + NMDnsServer dns_stack; + gs_free char *addr_port_heap = NULL; + gs_free char *addr_heap = NULL; + const char *addr_port; + const char *addr; + const char *name; + const char *port; nm_assert_addr_family_or_unspec(addr_family); - nm_assert(!out_addr || out_addr_family || NM_IN_SET(addr_family, AF_INET, AF_INET6)); if (!dns) + dns = &dns_stack; + + if (!str) return FALSE; - s = strchr(dns, '#'); + *dns = (NMDnsServer) { + .port = -1, + }; - if (s) { - dns = nm_strndup_a(200, dns, s - dns, &dns_heap); - s++; + if (NM_STR_HAS_PREFIX(str, "dns+tls://")) { + dns->scheme = NM_DNS_URI_SCHEME_TLS; + str += NM_STRLEN("dns+tls://"); + } else if (NM_STR_HAS_PREFIX(str, "dns+udp://")) { + dns->scheme = NM_DNS_URI_SCHEME_UDP; + str += NM_STRLEN("dns+udp://"); + } else { + name = strchr(str, '#'); + if (name) { + str = nm_strndup_a(200, str, name - str, &addr_heap); + name++; + } + + if (name && name[0] == '\0') { + /* empty DoT server name is not allowed */ + return FALSE; + } + + if (!nm_inet_parse_bin(addr_family, str, &dns->addr_family, &dns->addr)) + return FALSE; + + dns->servername = name; + dns->scheme = NM_DNS_URI_SCHEME_NONE; + + return TRUE; + } + + addr_port = str; + name = strrchr(addr_port, '#'); + if (name) { + addr_port = nm_strndup_a(100, addr_port, name - addr_port, &addr_port_heap); + name++; + if (*name == '\0') { + /* empty DoT server name not allowed */ + return FALSE; + } + dns->servername = name; } - if (s && s[0] == '\0') { - /* "ADDR#" empty DoT SNI name is not allowed. */ + if (addr_family != AF_INET && *addr_port == '[') { + const char *end; + char *perc; + + addr_family = AF_INET6; + addr_port++; + end = strchr(addr_port, ']'); + if (!end) + return FALSE; + addr = nm_strndup_a(100, addr_port, end - addr_port, &addr_heap); + + /* IPv6 link-local scope-id */ + perc = strchr(addr, '%'); + if (perc) { + *perc = '\0'; + if (g_strlcpy(dns->interface, perc + 1, sizeof(dns->interface)) + >= sizeof(dns->interface)) + return FALSE; + } + + /* port */ + end++; + if (*end == ':') { + end++; + dns->port = _nm_utils_ascii_str_to_int64(end, 10, 0, 65535, G_MAXINT32); + if (dns->port == G_MAXINT32) + return FALSE; + } + } else if (addr_family != AF_INET6) { + /* square brackets are mandatory for IPv6, so it must be IPv4 */ + + addr_family = AF_INET; + addr = addr_port; + + /* port */ + port = strchr(addr_port, ':'); + if (port) { + addr = nm_strndup_a(100, addr_port, port - addr_port, &addr_heap); + port++; + dns->port = _nm_utils_ascii_str_to_int64(port, 10, 0, 65535, G_MAXINT32); + if (dns->port == G_MAXINT32) + return FALSE; + } + } else { return FALSE; } - if (!nm_inet_parse_bin(addr_family, dns, &addr_family, out_addr ? &addr : NULL)) + if (!nm_inet_parse_bin(addr_family, addr, &dns->addr_family, &dns->addr)) + return FALSE; + + if (dns->scheme != NM_DNS_URI_SCHEME_TLS && dns->servername) + return FALSE; + + /* For now, allow the interface only for IPv6 link-local addresses */ + if (dns->interface[0] + && (dns->addr_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&dns->addr.addr6))) return FALSE; - NM_SET_OUT(out_addr_family, addr_family); - if (out_addr) - nm_ip_addr_set(addr_family, out_addr, &addr); - NM_SET_OUT(out_servername, s); return TRUE; } -const char * -nm_utils_dnsname_construct(int addr_family, - gconstpointer /* (const NMIPAddr *) */ addr, - const char *server_name, - char *result, - gsize result_len) +/* @nm_dns_uri_parse_plain: + * @addr_family: the address family, or AF_UNSPEC to autodetect it + * @str: the name server URI string + * @out_addrstr: the buffer to fill with the address string on return, + * or %NULL. Must be of size at least NM_INET_ADDRSTRLEN. + * @out_addr: the %NMIPAddr struct to fill on return, or %NULL + * + * Returns whether the string contains a "plain" (DNS over UDP on port 53) + * name server. In such case, it fills the arguments with the address + * of the name server. + * + * Returns: %TRUE on success, %FALSE if the string can't be parsed or + * if it's not a plain name server. + */ +gboolean +nm_dns_uri_parse_plain(int addr_family, const char *str, char *out_addrstr, NMIPAddr *out_addr) { - char sbuf[NM_INET_ADDRSTRLEN]; - gsize l; - int d; + NMDnsServer dns; - nm_assert_addr_family(addr_family); - nm_assert(addr); - nm_assert(!server_name || !nm_str_is_empty(server_name)); - - nm_inet_ntop(addr_family, addr, sbuf); + if (!nm_dns_uri_parse(addr_family, str, &dns)) + return FALSE; - if (!server_name) { - l = g_strlcpy(result, sbuf, result_len); - } else { - d = g_snprintf(result, result_len, "%s#%s", sbuf, server_name); - nm_assert(d >= 0); - l = (gsize) d; + switch (dns.scheme) { + case NM_DNS_URI_SCHEME_TLS: + return FALSE; + case NM_DNS_URI_SCHEME_NONE: + NM_SET_OUT(out_addr, dns.addr); + if (out_addrstr) { + nm_inet_ntop(dns.addr_family, &dns.addr, out_addrstr); + } + return TRUE; + case NM_DNS_URI_SCHEME_UDP: + if (dns.port != -1 && dns.port != 53) + return FALSE; + if (dns.interface[0]) + return FALSE; + NM_SET_OUT(out_addr, dns.addr); + if (out_addrstr) { + nm_inet_ntop(dns.addr_family, &dns.addr, out_addrstr); + } + return TRUE; + case NM_DNS_URI_SCHEME_UNKNOWN: + default: + return FALSE; } - - return l < result_len ? result : NULL; } +/* @nm_dns_uri_normalize: + * @addr_family: the address family, or AF_UNSPEC to autodetect it + * @str: the name server URI string + * @out_free: the newly-allocated string to set on return, or %NULL + * + * Returns the "normal" representation for the given name server URI. + * Note that a plain name server (DNS over UDP on port 53) is always + * represented in the "legacy" (non-URI) form. + * + * Returns: the normalized DNS URI + */ const char * -nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free) +nm_dns_uri_normalize(int addr_family, const char *str, char **out_free) { - char sbuf[NM_INET_ADDRSTRLEN]; - const char *server_name; - char *s; - NMIPAddr a; - gsize l; + NMDnsServer dns; + char addrstr[NM_INET_ADDRSTRLEN]; + char portstr[32]; + char *ret; + gsize len; nm_assert_addr_family_or_unspec(addr_family); - nm_assert(dns); + nm_assert(str); nm_assert(out_free && !*out_free); - if (!nm_utils_dnsname_parse(addr_family, dns, &addr_family, &a, &server_name)) + if (!nm_dns_uri_parse(addr_family, str, &dns)) return NULL; - nm_inet_ntop(addr_family, &a, sbuf); + nm_inet_ntop(dns.addr_family, &dns.addr, addrstr); - l = strlen(sbuf); + if (dns.port != -1) { + nm_assert(dns.port >= 0 && dns.port <= 65535); + g_snprintf(portstr, sizeof(portstr), "%d", dns.port); + } - /* In the vast majority of cases, the name is in fact normalized. Check - * whether it is, and don't duplicate the string. */ - if (strncmp(dns, sbuf, l) == 0) { - if (server_name) { - if (dns[l] == '#' && nm_streq(&dns[l + 1], server_name)) - return dns; - } else { - if (dns[l] == '\0') - return dns; + switch (dns.scheme) { + case NM_DNS_URI_SCHEME_NONE: + len = strlen(addrstr); + /* In the vast majority of cases, the name is in fact normalized. Check + * whether it is, and don't duplicate the string. */ + if (strncmp(str, addrstr, len) == 0) { + if (dns.servername) { + if (str[len] == '#' && nm_streq(&str[len + 1], dns.servername)) + return str; + } else { + if (str[len] == '\0') + return str; + } + } + + if (!dns.servername) + ret = g_strdup(addrstr); + else + ret = g_strconcat(addrstr, "#", dns.servername, NULL); + break; + case NM_DNS_URI_SCHEME_UDP: + if (dns.interface[0] || dns.port != -1) { + ret = g_strdup_printf("dns+udp://%s%s%s%s%s%s%s", + dns.addr_family == AF_INET6 ? "[" : "", + addrstr, + dns.interface[0] ? "%" : "", + dns.interface[0] ? dns.interface : "", + dns.addr_family == AF_INET6 ? "]" : "", + dns.port != -1 ? ":" : "", + dns.port != -1 ? portstr : ""); + break; } + ret = g_strdup_printf("%s%s%s", addrstr, dns.servername ? "#" : "", dns.servername ?: ""); + break; + case NM_DNS_URI_SCHEME_TLS: + ret = g_strdup_printf("dns+tls://%s%s%s%s%s%s%s%s%s", + dns.addr_family == AF_INET6 ? "[" : "", + addrstr, + dns.interface[0] ? "%%" : "", + dns.interface[0] ? dns.interface : "", + dns.addr_family == AF_INET6 ? "]" : "", + dns.port != -1 ? ":" : "", + dns.port != -1 ? portstr : "", + dns.servername ? "#" : "", + dns.servername ?: ""); + break; + case NM_DNS_URI_SCHEME_UNKNOWN: + default: + nm_assert_not_reached(); + ret = NULL; } - if (!server_name) - s = g_strdup(sbuf); - else - s = g_strconcat(sbuf, "#", server_name, NULL); + *out_free = ret; - *out_free = s; - return s; + return ret; } /*****************************************************************************/ diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.h b/src/libnm-core-aux-intern/nm-libnm-core-utils.h index 454fe4b3..9d1637a2 100644 --- a/src/libnm-core-aux-intern/nm-libnm-core-utils.h +++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h @@ -277,6 +277,17 @@ gboolean nm_utils_validate_dhcp_dscp(const char *dscp, GError **error); /*****************************************************************************/ +#define NM_MIN_FINITE_LEASE_TIME 120 +#define NM_MAX_FINITE_LEASE_TIME (3600 * 24 * 365) +#define NM_INFINITE_LEASE_TIME "infinity" + +gboolean nm_utils_validate_shared_dhcp_range(const char *shared_dhcp_range, + GPtrArray *addresses, + GError **error); +gboolean nm_utils_validate_shared_dhcp_lease_time(int shared_dhcp_lease_time, GError **error); + +/*****************************************************************************/ + #define NM_SETTINGS_CONNECTION_PERMISSION_USER "user" #define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:" @@ -301,32 +312,26 @@ NMMptcpFlags nm_mptcp_flags_normalize(NMMptcpFlags flags); /*****************************************************************************/ -gboolean nm_utils_dnsname_parse(int addr_family, - const char *dns, - int *out_addr_family, - gpointer /* (NMIPAddr **) */ out_addr, - const char **out_servername); - -#define nm_utils_dnsname_parse_assert(addr_family, dns, out_addr_family, out_addr, out_servername) \ - ({ \ - gboolean _good; \ - \ - _good = nm_utils_dnsname_parse((addr_family), \ - (dns), \ - (out_addr_family), \ - (out_addr), \ - (out_servername)); \ - nm_assert(_good); \ - _good; \ - }) - -const char *nm_utils_dnsname_construct(int addr_family, - gconstpointer /* (const NMIPAddr *) */ addr, - const char *server_name, - char *result, - gsize result_len); - -const char *nm_utils_dnsname_normalize(int addr_family, const char *dns, char **out_free); +typedef enum { + NM_DNS_URI_SCHEME_UNKNOWN, + NM_DNS_URI_SCHEME_NONE, + NM_DNS_URI_SCHEME_UDP, + NM_DNS_URI_SCHEME_TLS, +} NMDnsUriScheme; + +typedef struct { + NMIPAddr addr; + const char *servername; + char interface[NM_IFNAMSIZ]; + NMDnsUriScheme scheme; + int addr_family; + int port; +} NMDnsServer; + +gboolean nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *out_dns); +gboolean +nm_dns_uri_parse_plain(int addr_family, const char *str, char *out_addrstr, NMIPAddr *out_addr); +const char *nm_dns_uri_normalize(int addr_family, const char *str, char **out_free); /*****************************************************************************/ diff --git a/src/libnm-core-aux-intern/tests/meson.build b/src/libnm-core-aux-intern/tests/meson.build new file mode 100644 index 00000000..5f2670b9 --- /dev/null +++ b/src/libnm-core-aux-intern/tests/meson.build @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +exe = executable( + 'test-libnm-core-utils', + 'test-libnm-core-utils.c', + include_directories: [ + libnm_core_aux_intern_inc + ], + link_with: [ + libnm_core_aux_intern, + libnm_core_impl, + libnm_base, + libnm_crypto, + libnm_systemd_shared, + libnm_log_null, + libnm_glib_aux, + libnm_std_aux, + libc_siphash, + ], + dependencies: [ + libnm_client_public_dep, + libnm_core_public_dep, + uuid_dep, + glib_dep, + dl_dep, + ], +) + +test( + 'src/libnm-core-aux-intern/tests/test-libnm-core-utils', + exe, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, +) diff --git a/src/libnm-core-aux-intern/tests/test-libnm-core-utils.c b/src/libnm-core-aux-intern/tests/test-libnm-core-utils.c new file mode 100644 index 00000000..1df36841 --- /dev/null +++ b/src/libnm-core-aux-intern/tests/test-libnm-core-utils.c @@ -0,0 +1,364 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Advantech Czech s.r.o. + */ + +#include "libnm-glib-aux/nm-default-glib-i18n-prog.h" +#include "libnm-glib-aux/nm-test-utils.h" + +#include "nm-libnm-core-utils.h" +#include "nm-errors.h" + +static void +empty_range_valid_for_null_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_range("", addresses, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +empty_range_valid_for_empty_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + result = nm_utils_validate_shared_dhcp_range("", addresses, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +valid_range_for_single_address(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("192.168.0.2,192.168.0.254", addresses, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +valid_range_for_second_address(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, &error)); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.1.254", 24, &error)); + + result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +invalid_null_range_for_null_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_range(NULL, addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_null_range_for_empty_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +any_range_invalid_for_null_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +any_range_invalid_for_empty_addresses(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + + result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_range_xyz(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("xyz", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_range_single_comma(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range(",", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_first_address_of_range(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("xyz,192.168.0.100", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_second_address_of_range(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("192.168.0.100,xyz", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_inverted_range(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("192.168.0.200,192.168.0.100", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +invalid_range_outside_address_space(void) +{ + gs_unref_ptrarray GPtrArray *addresses = NULL; + gs_free_error GError *error = NULL; + gboolean result; + + addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL)); + + result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.100", addresses, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +/*****************************************************************************/ + +static void +valid_zero_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(0, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +minimal_valid_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(NM_MIN_FINITE_LEASE_TIME, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +middle_valid_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time( + (NM_MIN_FINITE_LEASE_TIME + NM_MAX_FINITE_LEASE_TIME) / 2, + &error); + + g_assert(result); + g_assert_null(error); +} + +static void +maximal_valid_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(NM_MAX_FINITE_LEASE_TIME, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +infinite_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(G_MAXINT32, &error); + + g_assert(result); + g_assert_null(error); +} + +static void +too_small_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(1, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +static void +too_large_lease_time(void) +{ + gs_free_error GError *error = NULL; + gboolean result; + + result = nm_utils_validate_shared_dhcp_lease_time(NM_MAX_FINITE_LEASE_TIME + 1, &error); + + g_assert_false(result); + g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/core/utils/shared_dhcp_range/empty_range_valid_for_null_addresses", + empty_range_valid_for_null_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/empty_range_valid_for_empty_addresses", + empty_range_valid_for_empty_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/valid_range_for_single_address", + valid_range_for_single_address); + g_test_add_func("/core/utils/shared_dhcp_range/valid_range_for_second_address", + valid_range_for_second_address); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_null_range_for_null_addresses", + invalid_null_range_for_null_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_null_range_for_empty_addresses", + invalid_null_range_for_empty_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/any_range_invalid_for_null_addresses", + any_range_invalid_for_null_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/any_range_invalid_for_empty_addresses", + any_range_invalid_for_empty_addresses); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_xyz", invalid_range_xyz); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_single_comma", + invalid_range_single_comma); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_first_address_of_range", + invalid_first_address_of_range); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_second_address_of_range", + invalid_second_address_of_range); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_inverted_range", invalid_inverted_range); + g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_outside_address_space", + invalid_range_outside_address_space); + + g_test_add_func("/core/utils/shared_dhcp_lease_time/valid_zero_lease_time", + valid_zero_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/minimal_valid_lease_time", + minimal_valid_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/middle_valid_lease_time", + middle_valid_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/maximal_valid_lease_time", + maximal_valid_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/infinite_lease_time", infinite_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/too_small_lease_time", + too_small_lease_time); + g_test_add_func("/core/utils/shared_dhcp_lease_time/too_large_lease_time", + too_large_lease_time); + + return g_test_run(); +} |