diff options
Diffstat (limited to 'libnm-core/nm-setting-ip-config.c')
| -rw-r--r-- | libnm-core/nm-setting-ip-config.c | 6285 |
1 files changed, 0 insertions, 6285 deletions
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c deleted file mode 100644 index 1addf8c6..00000000 --- a/libnm-core/nm-setting-ip-config.c +++ /dev/null @@ -1,6285 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2007 - 2017 Red Hat, Inc. - * Copyright (C) 2007 - 2008 Novell, Inc. - */ - -#include "libnm-core/nm-default-libnm-core.h" - -#include "nm-setting-ip-config.h" - -#include <arpa/inet.h> -#include <linux/fib_rules.h> - -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" -#include "nm-utils.h" -#include "nm-setting-private.h" -#include "nm-utils-private.h" - -/** - * SECTION:nm-setting-ip-config - * @short_description: Abstract base class for IPv4 and IPv6 - * addressing, routing, and name service properties - * @include: nm-setting-ip-config.h - * @see_also: #NMSettingIP4Config, #NMSettingIP6Config - * - * #NMSettingIPConfig is the abstract base class of - * #NMSettingIP4Config and #NMSettingIP6Config, providing properties - * related to IP addressing, routing, and Domain Name Service. - **/ - -/*****************************************************************************/ - -const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[] = { - {NM_SETTING_DNS_OPTION_DEBUG, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NDOTS, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_TIMEOUT, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_ATTEMPTS, TRUE, FALSE}, - {NM_SETTING_DNS_OPTION_ROTATE, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_CHECK_NAMES, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_INET6, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_IP6_BYTESTRING, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_IP6_DOTINT, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_NO_IP6_DOTINT, FALSE, TRUE}, - {NM_SETTING_DNS_OPTION_EDNS0, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_SINGLE_REQUEST, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_TLD_QUERY, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_USE_VC, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_NO_RELOAD, FALSE, FALSE}, - {NM_SETTING_DNS_OPTION_TRUST_AD, FALSE, FALSE}, - {NULL, FALSE, FALSE}}; - -static char * -canonicalize_ip(int family, const char *ip, gboolean null_any) -{ - guint8 addr_bytes[sizeof(struct in6_addr)]; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - int ret; - - if (!ip) { - if (null_any) - return NULL; - if (family == AF_INET) - return g_strdup("0.0.0.0"); - if (family == AF_INET6) - return g_strdup("::"); - g_return_val_if_reached(NULL); - } - - ret = inet_pton(family, ip, addr_bytes); - g_return_val_if_fail(ret == 1, NULL); - - if (null_any) { - if (!memcmp(addr_bytes, &in6addr_any, nm_utils_addr_family_to_size(family))) - return NULL; - } - - return g_strdup(inet_ntop(family, addr_bytes, addr_str, sizeof(addr_str))); -} - -static char * -canonicalize_ip_binary(int family, gconstpointer ip, gboolean null_any) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - if (!ip) { - if (null_any) - return NULL; - if (family == AF_INET) - return g_strdup("0.0.0.0"); - if (family == AF_INET6) - return g_strdup("::"); - g_return_val_if_reached(NULL); - } - if (null_any) { - if (!memcmp(ip, &in6addr_any, nm_utils_addr_family_to_size(family))) - return NULL; - } - return g_strdup(inet_ntop(family, ip, string, sizeof(string))); -} - -static gboolean -valid_ip(int family, const char *ip, GError **error) -{ - if (!ip) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Missing IPv4 address") : _("Missing IPv6 address")); - return FALSE; - } - if (!nm_utils_ipaddr_is_valid(family, ip)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Invalid IPv4 address '%s'") - : _("Invalid IPv6 address '%s'"), - ip); - return FALSE; - } else - return TRUE; -} - -static gboolean -valid_prefix(int family, guint prefix, GError **error) -{ - if ((family == AF_INET && prefix <= 32) || (family == AF_INET6 && prefix <= 128)) - return TRUE; - - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("Invalid IPv4 address prefix '%u'") - : _("Invalid IPv6 address prefix '%u'"), - prefix); - return FALSE; -} - -static gboolean -valid_metric(gint64 metric, GError **error) -{ - if (metric < -1 || metric > G_MAXUINT32) { - if (error) { - char buf[64]; - - /* We can't concatenate G_GINT64_FORMAT into a translatable string */ - g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, metric); - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Invalid routing metric '%s'"), - buf); - } - return FALSE; - } - - return TRUE; -} - -/***************************************************************************** - * NMIPAddress - *****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMIPAddress, nm_ip_address, nm_ip_address_dup, nm_ip_address_unref) - -struct NMIPAddress { - guint refcount; - - char *address; - int prefix, family; - - GHashTable *attributes; -}; - -/** - * nm_ip_address_new: - * @family: the IP address family (<literal>AF_INET</literal> or - * <literal>AF_INET6</literal>) - * @addr: the IP address - * @prefix: the address prefix length - * @error: location to store error, or %NULL - * - * Creates a new #NMIPAddress object. - * - * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error - **/ -NMIPAddress * -nm_ip_address_new(int family, const char *addr, guint prefix, GError **error) -{ - NMIPAddress *address; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(addr != NULL, NULL); - - if (!valid_ip(family, addr, error)) - return NULL; - if (!valid_prefix(family, prefix, error)) - return NULL; - - address = g_slice_new0(NMIPAddress); - address->refcount = 1; - - address->family = family; - address->address = canonicalize_ip(family, addr, FALSE); - address->prefix = prefix; - - return address; -} - -/** - * nm_ip_address_new_binary: - * @family: the IP address family (<literal>AF_INET</literal> or - * <literal>AF_INET6</literal>) - * @addr: the IP address - * @prefix: the address prefix length - * @error: location to store error, or %NULL - * - * Creates a new #NMIPAddress object. @addr must point to a buffer of the - * correct size for @family. - * - * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error - **/ -NMIPAddress * -nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError **error) -{ - NMIPAddress *address; - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(addr != NULL, NULL); - - if (!valid_prefix(family, prefix, error)) - return NULL; - - address = g_slice_new0(NMIPAddress); - address->refcount = 1; - - address->family = family; - address->address = g_strdup(inet_ntop(family, addr, string, sizeof(string))); - address->prefix = prefix; - - return address; -} - -/** - * nm_ip_address_ref: - * @address: the #NMIPAddress - * - * Increases the reference count of the object. - **/ -void -nm_ip_address_ref(NMIPAddress *address) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(address->refcount > 0); - - address->refcount++; -} - -/** - * nm_ip_address_unref: - * @address: the #NMIPAddress - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - **/ -void -nm_ip_address_unref(NMIPAddress *address) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(address->refcount > 0); - - address->refcount--; - if (address->refcount == 0) { - g_free(address->address); - if (address->attributes) - g_hash_table_unref(address->attributes); - g_slice_free(NMIPAddress, address); - } -} - -/** - * nm_ip_address_cmp_full: - * @a: the #NMIPAddress - * @b: the #NMIPAddress to compare @address to. - * @cmp_flags: the #NMIPAddressCmpFlags that indicate what to compare. - * - * Note that with @cmp_flags #NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS, there - * is no total order for comparing GVariant. That means, if the two addresses - * only differ by their attributes, the sort order is undefined and the return - * value only indicates equality. - * - * Returns: 0 if the two objects have the same values (according to their flags) - * or a integer indicating the compare order. - **/ -int -nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags) -{ - g_return_val_if_fail(!a || a->refcount > 0, 0); - g_return_val_if_fail(!b || b->refcount > 0, 0); - g_return_val_if_fail(!NM_FLAGS_ANY(cmp_flags, ~NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS), 0); - - NM_CMP_SELF(a, b); - - NM_CMP_FIELD(a, b, family); - NM_CMP_FIELD(a, b, prefix); - NM_CMP_FIELD_STR(a, b, address); - - if (NM_FLAGS_HAS(cmp_flags, NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS)) { - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - n = a->attributes ? g_hash_table_size(a->attributes) : 0u; - NM_CMP_DIRECT(n, (b->attributes ? g_hash_table_size(b->attributes) : 0u)); - - if (n > 0) { - g_hash_table_iter_init(&iter, a->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(b->attributes, key); - /* We cannot really compare GVariants, because g_variant_compare() does - * not work in general. So, don't bother. NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS is - * documented to not provide a total order for the attribute contents. - * - * Theoretically, we can implement also a total order. However we should - * not do that by default because it would require us to sort the keys - * first. Most callers don't care about total order, so they shouldn't - * pay the overhead. */ - if (!value2) - return -2; - if (!g_variant_equal(value, value2)) - return -2; - } - } - } - - return 0; -} - -/** - * nm_ip_address_equal: - * @address: the #NMIPAddress - * @other: the #NMIPAddress to compare @address to. - * - * Determines if two #NMIPAddress objects contain the same address and prefix - * (attributes are not compared). - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - **/ -gboolean -nm_ip_address_equal(NMIPAddress *address, NMIPAddress *other) -{ - return nm_ip_address_cmp_full(address, other, NM_IP_ADDRESS_CMP_FLAGS_NONE) == 0; -} - -/** - * nm_ip_address_dup: - * @address: the #NMIPAddress - * - * Creates a copy of @address - * - * Returns: (transfer full): a copy of @address - **/ -NMIPAddress * -nm_ip_address_dup(NMIPAddress *address) -{ - NMIPAddress *copy; - - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(address->refcount > 0, NULL); - - copy = nm_ip_address_new(address->family, address->address, address->prefix, NULL); - if (address->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, address->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_ip_address_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_ip_address_get_family: - * @address: the #NMIPAddress - * - * Gets the IP address family (eg, AF_INET) property of this address - * object. - * - * Returns: the IP address family - **/ -int -nm_ip_address_get_family(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, 0); - g_return_val_if_fail(address->refcount > 0, 0); - - return address->family; -} - -/** - * nm_ip_address_get_address: - * @address: the #NMIPAddress - * - * Gets the IP address property of this address object. - * - * Returns: the IP address - **/ -const char * -nm_ip_address_get_address(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(address->refcount > 0, NULL); - - return address->address; -} - -/** - * nm_ip_address_set_address: - * @address: the #NMIPAddress - * @addr: the IP address, as a string - * - * Sets the IP address property of this address object. - * - * @addr must be a valid address of @address's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_valid() to check it. - **/ -void -nm_ip_address_set_address(NMIPAddress *address, const char *addr) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - g_return_if_fail(nm_utils_ipaddr_is_valid(address->family, addr)); - - g_free(address->address); - address->address = canonicalize_ip(address->family, addr, FALSE); -} - -/** - * nm_ip_address_get_address_binary: (skip) - * @address: the #NMIPAddress - * @addr: a buffer in which to store the address in binary format. - * - * Gets the IP address property of this address object. - * - * @addr must point to a buffer that is the correct size for @address's family. - **/ -void -nm_ip_address_get_address_binary(NMIPAddress *address, gpointer addr) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - - inet_pton(address->family, address->address, addr); -} - -/** - * nm_ip_address_set_address_binary: (skip) - * @address: the #NMIPAddress - * @addr: the address, in binary format - * - * Sets the IP address property of this address object. - * - * @addr must point to a buffer that is the correct size for @address's family. - **/ -void -nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_if_fail(address != NULL); - g_return_if_fail(addr != NULL); - - g_free(address->address); - address->address = g_strdup(inet_ntop(address->family, addr, string, sizeof(string))); -} - -/** - * nm_ip_address_get_prefix: - * @address: the #NMIPAddress - * - * Gets the IP address prefix (ie "24" or "30" etc) property of this address - * object. - * - * Returns: the IP address prefix - **/ -guint -nm_ip_address_get_prefix(NMIPAddress *address) -{ - g_return_val_if_fail(address != NULL, 0); - g_return_val_if_fail(address->refcount > 0, 0); - - return address->prefix; -} - -/** - * nm_ip_address_set_prefix: - * @address: the #NMIPAddress - * @prefix: the IP address prefix - * - * Sets the IP address prefix property of this address object. - **/ -void -nm_ip_address_set_prefix(NMIPAddress *address, guint prefix) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(valid_prefix(address->family, prefix, NULL)); - - address->prefix = prefix; -} - -const char ** -_nm_ip_address_get_attribute_names(const NMIPAddress *address, gboolean sorted, guint *out_length) -{ - nm_assert(address); - - return nm_utils_strdict_get_keys(address->attributes, sorted, out_length); -} - -/** - * nm_ip_address_get_attribute_names: - * @address: the #NMIPAddress - * - * Gets an array of attribute names defined on @address. - * - * Returns: (transfer full): a %NULL-terminated array of attribute names, - **/ -char ** -nm_ip_address_get_attribute_names(NMIPAddress *address) -{ - const char **names; - - g_return_val_if_fail(address, NULL); - - names = _nm_ip_address_get_attribute_names(address, TRUE, NULL); - return nm_utils_strv_make_deep_copied_nonnull(names); -} - -/** - * nm_ip_address_get_attribute: - * @address: the #NMIPAddress - * @name: the name of an address attribute - * - * Gets the value of the attribute with name @name on @address - * - * Returns: (transfer none): the value of the attribute with name @name on - * @address, or %NULL if @address has no such attribute. - **/ -GVariant * -nm_ip_address_get_attribute(NMIPAddress *address, const char *name) -{ - g_return_val_if_fail(address != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (address->attributes) - return g_hash_table_lookup(address->attributes, name); - else - return NULL; -} - -/** - * nm_ip_address_set_attribute: - * @address: the #NMIPAddress - * @name: the name of an address attribute - * @value: (transfer none) (allow-none): the value - * - * Sets or clears the named attribute on @address to the given value. - **/ -void -nm_ip_address_set_attribute(NMIPAddress *address, const char *name, GVariant *value) -{ - g_return_if_fail(address != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "address") != 0 && strcmp(name, "prefix") != 0); - - if (!address->attributes) { - address->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(address->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(address->attributes, name); -} - -/***************************************************************************** - * NMIPRoute - *****************************************************************************/ - -G_DEFINE_BOXED_TYPE(NMIPRoute, nm_ip_route, nm_ip_route_dup, nm_ip_route_unref) - -struct NMIPRoute { - guint refcount; - - int family; - char * dest; - guint prefix; - char * next_hop; - gint64 metric; - - GHashTable *attributes; -}; - -/** - * nm_ip_route_new: - * @family: the IP address family (<literal>AF_INET</literal> or - * <literal>AF_INET6</literal>) - * @dest: the IP address of the route's destination - * @prefix: the address prefix length - * @next_hop: (allow-none): the IP address of the next hop (or %NULL) - * @metric: the route metric (or -1 for "default") - * @error: location to store error, or %NULL - * - * Creates a new #NMIPRoute object. - * - * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error - **/ -NMIPRoute * -nm_ip_route_new(int family, - const char *dest, - guint prefix, - const char *next_hop, - gint64 metric, - GError ** error) -{ - NMIPRoute *route; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(dest, NULL); - - if (!valid_ip(family, dest, error)) - return NULL; - if (!valid_prefix(family, prefix, error)) - return NULL; - if (next_hop && !valid_ip(family, next_hop, error)) - return NULL; - if (!valid_metric(metric, error)) - return NULL; - - route = g_slice_new0(NMIPRoute); - route->refcount = 1; - - route->family = family; - route->dest = canonicalize_ip(family, dest, FALSE); - route->prefix = prefix; - route->next_hop = canonicalize_ip(family, next_hop, TRUE); - route->metric = metric; - - return route; -} - -/** - * nm_ip_route_new_binary: - * @family: the IP address family (<literal>AF_INET</literal> or - * <literal>AF_INET6</literal>) - * @dest: the IP address of the route's destination - * @prefix: the address prefix length - * @next_hop: (allow-none): the IP address of the next hop (or %NULL) - * @metric: the route metric (or -1 for "default") - * @error: location to store error, or %NULL - * - * Creates a new #NMIPRoute object. @dest and @next_hop (if non-%NULL) must - * point to buffers of the correct size for @family. - * - * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error - **/ -NMIPRoute * -nm_ip_route_new_binary(int family, - gconstpointer dest, - guint prefix, - gconstpointer next_hop, - gint64 metric, - GError ** error) -{ - NMIPRoute *route; - - g_return_val_if_fail(family == AF_INET || family == AF_INET6, NULL); - g_return_val_if_fail(dest, NULL); - - if (!valid_prefix(family, prefix, error)) - return NULL; - if (!valid_metric(metric, error)) - return NULL; - - route = g_slice_new0(NMIPRoute); - route->refcount = 1; - - route->family = family; - route->dest = canonicalize_ip_binary(family, dest, FALSE); - route->prefix = prefix; - route->next_hop = canonicalize_ip_binary(family, next_hop, TRUE); - route->metric = metric; - - return route; -} - -/** - * nm_ip_route_ref: - * @route: the #NMIPRoute - * - * Increases the reference count of the object. - **/ -void -nm_ip_route_ref(NMIPRoute *route) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(route->refcount > 0); - - route->refcount++; -} - -/** - * nm_ip_route_unref: - * @route: the #NMIPRoute - * - * Decreases the reference count of the object. If the reference count - * reaches zero, the object will be destroyed. - **/ -void -nm_ip_route_unref(NMIPRoute *route) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(route->refcount > 0); - - route->refcount--; - if (route->refcount == 0) { - g_free(route->dest); - g_free(route->next_hop); - if (route->attributes) - g_hash_table_unref(route->attributes); - g_slice_free(NMIPRoute, route); - } -} - -/** - * nm_ip_route_equal_full: - * @route: the #NMIPRoute - * @other: the #NMIPRoute to compare @route to. - * @cmp_flags: tune how to compare attributes. Currently, only - * NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE (0) and NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS (1) - * is supported. - * - * Determines if two #NMIPRoute objects contain the same destination, prefix, - * next hop, and metric. - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - * - * Since: 1.10 - **/ -gboolean -nm_ip_route_equal_full(NMIPRoute *route, NMIPRoute *other, guint cmp_flags) -{ - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(route->refcount > 0, FALSE); - - g_return_val_if_fail(other != NULL, FALSE); - g_return_val_if_fail(other->refcount > 0, FALSE); - - g_return_val_if_fail(NM_IN_SET(cmp_flags, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS), - FALSE); - - if (route->prefix != other->prefix || route->metric != other->metric - || strcmp(route->dest, other->dest) != 0 - || g_strcmp0(route->next_hop, other->next_hop) != 0) - return FALSE; - if (cmp_flags == NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS) { - GHashTableIter iter; - const char * key; - GVariant * value, *value2; - guint n; - - n = route->attributes ? g_hash_table_size(route->attributes) : 0u; - if (n != (other->attributes ? g_hash_table_size(other->attributes) : 0u)) - return FALSE; - if (n) { - g_hash_table_iter_init(&iter, route->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) { - value2 = g_hash_table_lookup(other->attributes, key); - if (!value2) - return FALSE; - if (!g_variant_equal(value, value2)) - return FALSE; - } - } - } - return TRUE; -} - -/** - * nm_ip_route_equal: - * @route: the #NMIPRoute - * @other: the #NMIPRoute to compare @route to. - * - * Determines if two #NMIPRoute objects contain the same destination, prefix, - * next hop, and metric. (Attributes are not compared.) - * - * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. - **/ -gboolean -nm_ip_route_equal(NMIPRoute *route, NMIPRoute *other) -{ - return nm_ip_route_equal_full(route, other, NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE); -} - -/** - * nm_ip_route_dup: - * @route: the #NMIPRoute - * - * Creates a copy of @route - * - * Returns: (transfer full): a copy of @route - **/ -NMIPRoute * -nm_ip_route_dup(NMIPRoute *route) -{ - NMIPRoute *copy; - - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - copy = nm_ip_route_new(route->family, - route->dest, - route->prefix, - route->next_hop, - route->metric, - NULL); - if (route->attributes) { - GHashTableIter iter; - const char * key; - GVariant * value; - - g_hash_table_iter_init(&iter, route->attributes); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) - nm_ip_route_set_attribute(copy, key, value); - } - - return copy; -} - -/** - * nm_ip_route_get_family: - * @route: the #NMIPRoute - * - * Gets the IP address family (eg, AF_INET) property of this route - * object. - * - * Returns: the IP address family - **/ -int -nm_ip_route_get_family(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->family; -} - -/** - * nm_ip_route_get_dest: - * @route: the #NMIPRoute - * - * Gets the IP destination address property of this route object. - * - * Returns: the IP address of the route's destination - **/ -const char * -nm_ip_route_get_dest(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - return route->dest; -} - -/** - * nm_ip_route_set_dest: - * @route: the #NMIPRoute - * @dest: the route's destination, as a string - * - * Sets the destination property of this route object. - * - * @dest must be a valid address of @route's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_is_valid() to check it. - **/ -void -nm_ip_route_set_dest(NMIPRoute *route, const char *dest) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(nm_utils_ipaddr_is_valid(route->family, dest)); - - g_free(route->dest); - route->dest = canonicalize_ip(route->family, dest, FALSE); -} - -/** - * nm_ip_route_get_dest_binary: (skip) - * @route: the #NMIPRoute - * @dest: a buffer in which to store the destination in binary format. - * - * Gets the destination property of this route object. - * - * @dest must point to a buffer that is the correct size for @route's family. - **/ -void -nm_ip_route_get_dest_binary(NMIPRoute *route, gpointer dest) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(dest != NULL); - - inet_pton(route->family, route->dest, dest); -} - -/** - * nm_ip_route_set_dest_binary: (skip) - * @route: the #NMIPRoute - * @dest: the route's destination, in binary format - * - * Sets the destination property of this route object. - * - * @dest must point to a buffer that is the correct size for @route's family. - **/ -void -nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest) -{ - char string[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_if_fail(route != NULL); - g_return_if_fail(dest != NULL); - - g_free(route->dest); - route->dest = g_strdup(inet_ntop(route->family, dest, string, sizeof(string))); -} - -/** - * nm_ip_route_get_prefix: - * @route: the #NMIPRoute - * - * Gets the IP prefix (ie "24" or "30" etc) of this route. - * - * Returns: the IP prefix - **/ -guint -nm_ip_route_get_prefix(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->prefix; -} - -/** - * nm_ip_route_set_prefix: - * @route: the #NMIPRoute - * @prefix: the route prefix - * - * Sets the prefix property of this route object. - **/ -void -nm_ip_route_set_prefix(NMIPRoute *route, guint prefix) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(valid_prefix(route->family, prefix, NULL)); - - route->prefix = prefix; -} - -/** - * nm_ip_route_get_next_hop: - * @route: the #NMIPRoute - * - * Gets the IP address of the next hop of this route; this will be %NULL if the - * route has no next hop. - * - * Returns: the IP address of the next hop, or %NULL if this is a device route. - **/ -const char * -nm_ip_route_get_next_hop(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(route->refcount > 0, NULL); - - return route->next_hop; -} - -/** - * nm_ip_route_set_next_hop: - * @route: the #NMIPRoute - * @next_hop: (allow-none): the route's next hop, as a string - * - * Sets the next-hop property of this route object. - * - * @next_hop (if non-%NULL) must be a valid address of @route's family. If you - * aren't sure you have a valid address, use nm_utils_ipaddr_valid() to check - * it. - **/ -void -nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(!next_hop || nm_utils_ipaddr_is_valid(route->family, next_hop)); - - g_free(route->next_hop); - route->next_hop = canonicalize_ip(route->family, next_hop, TRUE); -} - -/** - * nm_ip_route_get_next_hop_binary: (skip) - * @route: the #NMIPRoute - * @next_hop: a buffer in which to store the next hop in binary format. - * - * Gets the next hop property of this route object. - * - * @next_hop must point to a buffer that is the correct size for @route's family. - * - * Returns: %TRUE if @route has a next hop, %FALSE if not (in which case - * @next_hop will be zeroed out) - **/ -gboolean -nm_ip_route_get_next_hop_binary(NMIPRoute *route, gpointer next_hop) -{ - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(next_hop != NULL, FALSE); - - if (route->next_hop) { - inet_pton(route->family, route->next_hop, next_hop); - return TRUE; - } else { - memset(next_hop, 0, nm_utils_addr_family_to_size(route->family)); - return FALSE; - } -} - -/** - * nm_ip_route_set_next_hop_binary: (skip) - * @route: the #NMIPRoute - * @next_hop: the route's next hop, in binary format - * - * Sets the destination property of this route object. - * - * @next_hop (if non-%NULL) must point to a buffer that is the correct size for - * @route's family. - **/ -void -nm_ip_route_set_next_hop_binary(NMIPRoute *route, gconstpointer next_hop) -{ - g_return_if_fail(route != NULL); - - g_free(route->next_hop); - route->next_hop = canonicalize_ip_binary(route->family, next_hop, TRUE); -} - -/** - * nm_ip_route_get_metric: - * @route: the #NMIPRoute - * - * Gets the route metric property of this route object; lower values - * indicate "better" or more preferred routes; -1 indicates "default" - * (meaning NetworkManager will set it appropriately). - * - * Returns: the route metric - **/ -gint64 -nm_ip_route_get_metric(NMIPRoute *route) -{ - g_return_val_if_fail(route != NULL, 0); - g_return_val_if_fail(route->refcount > 0, 0); - - return route->metric; -} - -/** - * nm_ip_route_set_metric: - * @route: the #NMIPRoute - * @metric: the route metric (or -1 for "default") - * - * Sets the metric property of this route object. - **/ -void -nm_ip_route_set_metric(NMIPRoute *route, gint64 metric) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(valid_metric(metric, NULL)); - - route->metric = metric; -} - -GHashTable * -_nm_ip_route_get_attributes(NMIPRoute *route) -{ - nm_assert(route); - - return route->attributes; -} - -/** - * _nm_ip_route_get_attribute_names: - * @route: the #NMIPRoute - * @sorted: whether to sort the names. Otherwise, their order is - * undefined and unstable. - * @out_length: (allow-none) (out): the number of elements - * - * Gets an array of attribute names defined on @route. - * - * Returns: (array length=out_length) (transfer container): a %NULL-terminated array - * of attribute names or %NULL if there are no attributes. The order of the returned - * names depends on @sorted. - **/ -const char ** -_nm_ip_route_get_attribute_names(const NMIPRoute *route, gboolean sorted, guint *out_length) -{ - nm_assert(route); - - return nm_utils_strdict_get_keys(route->attributes, sorted, out_length); -} - -/** - * nm_ip_route_get_attribute_names: - * @route: the #NMIPRoute - * - * Gets an array of attribute names defined on @route. - * - * Returns: (transfer full): a %NULL-terminated array of attribute names - **/ -char ** -nm_ip_route_get_attribute_names(NMIPRoute *route) -{ - const char **names; - - g_return_val_if_fail(route != NULL, NULL); - - names = _nm_ip_route_get_attribute_names(route, TRUE, NULL); - return nm_utils_strv_make_deep_copied_nonnull(names); -} - -/** - * nm_ip_route_get_attribute: - * @route: the #NMIPRoute - * @name: the name of an route attribute - * - * Gets the value of the attribute with name @name on @route - * - * Returns: (transfer none): the value of the attribute with name @name on - * @route, or %NULL if @route has no such attribute. - **/ -GVariant * -nm_ip_route_get_attribute(NMIPRoute *route, const char *name) -{ - g_return_val_if_fail(route != NULL, NULL); - g_return_val_if_fail(name != NULL && *name != '\0', NULL); - - if (route->attributes) - return g_hash_table_lookup(route->attributes, name); - else - return NULL; -} - -/** - * nm_ip_route_set_attribute: - * @route: the #NMIPRoute - * @name: the name of a route attribute - * @value: (transfer none) (allow-none): the value - * - * Sets the named attribute on @route to the given value. - **/ -void -nm_ip_route_set_attribute(NMIPRoute *route, const char *name, GVariant *value) -{ - g_return_if_fail(route != NULL); - g_return_if_fail(name != NULL && *name != '\0'); - g_return_if_fail(strcmp(name, "dest") != 0 && strcmp(name, "prefix") != 0 - && strcmp(name, "next-hop") != 0 && strcmp(name, "metric") != 0); - - if (!route->attributes) { - route->attributes = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_variant_unref); - } - - if (value) - g_hash_table_insert(route->attributes, g_strdup(name), g_variant_ref_sink(value)); - else - g_hash_table_remove(route->attributes, name); -} - -static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_CWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_FROM, - G_VARIANT_TYPE_STRING, - .v6 = TRUE, - .str_type = 'p', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITCWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_INITRWND, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_MTU, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_ONLINK, - G_VARIANT_TYPE_BOOLEAN, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SCOPE, - G_VARIANT_TYPE_BYTE, - .v4 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_SRC, - G_VARIANT_TYPE_STRING, - .v4 = TRUE, - .v6 = TRUE, - .str_type = 'a', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TABLE, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_TYPE, - G_VARIANT_TYPE_STRING, - .v4 = TRUE, - .v6 = TRUE, - .str_type = 'T', ), - NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WINDOW, - G_VARIANT_TYPE_UINT32, - .v4 = TRUE, - .v6 = TRUE, ), - NULL, -}; - -/** - * nm_ip_route_get_variant_attribute_spec: - * - * Returns: the specifiers for route attributes - * - * Since: 1.8 - */ -const NMVariantAttributeSpec *const * -nm_ip_route_get_variant_attribute_spec(void) -{ - return ip_route_attribute_spec; -} - -/** - * nm_ip_route_attribute_validate: - * @name: the attribute name - * @value: the attribute value - * @family: IP address family of the route - * @known: (out): on return, whether the attribute name is a known one - * @error: (allow-none): return location for a #GError, or %NULL - * - * Validates a route attribute, i.e. checks that the attribute is a known one - * and the value is of the correct type and well-formed. - * - * Returns: %TRUE if the attribute is valid, %FALSE otherwise - * - * Since: 1.8 - */ -gboolean -nm_ip_route_attribute_validate(const char *name, - GVariant * value, - int family, - gboolean * known, - GError ** error) -{ - const NMVariantAttributeSpec *spec; - - g_return_val_if_fail(name, FALSE); - g_return_val_if_fail(value, FALSE); - g_return_val_if_fail(family == AF_INET || family == AF_INET6, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - spec = _nm_variant_attribute_spec_find_binary_search(ip_route_attribute_spec, - G_N_ELEMENTS(ip_route_attribute_spec) - 1, - name); - if (!spec) { - NM_SET_OUT(known, FALSE); - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unknown attribute")); - return FALSE; - } - - NM_SET_OUT(known, TRUE); - - if (!g_variant_is_of_type(value, spec->type)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid attribute type '%s'"), - g_variant_get_type_string(value)); - return FALSE; - } - - if ((family == AF_INET && !spec->v4) || (family == AF_INET6 && !spec->v6)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("attribute is not valid for a IPv4 route") - : _("attribute is not valid for a IPv6 route")); - return FALSE; - } - - if (g_variant_type_equal(spec->type, G_VARIANT_TYPE_STRING)) { - const char *string = g_variant_get_string(value, NULL); - - switch (spec->str_type) { - case 'a': /* IP address */ - if (!nm_utils_ipaddr_is_valid(family, string)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("'%s' is not a valid IPv4 address") - : _("'%s' is not a valid IPv6 address"), - string); - return FALSE; - } - break; - case 'p': /* IP address + optional prefix */ - { - gs_free char *addr_free = NULL; - const char * addr = string; - const char * str; - - str = strchr(addr, '/'); - if (str) { - addr = nm_strndup_a(200, addr, str - addr, &addr_free); - str++; - if (_nm_utils_ascii_str_to_int64(str, 10, 0, family == AF_INET ? 32 : 128, -1) - < 0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid prefix %s"), - str); - return FALSE; - } - } - if (!nm_utils_ipaddr_is_valid(family, addr)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - family == AF_INET ? _("'%s' is not a valid IPv4 address") - : _("'%s' is not a valid IPv6 address"), - string); - return FALSE; - } - break; - } - case 'T': /* route type. */ - if (!NM_IN_SET(nm_utils_route_type_by_name(string), RTN_UNICAST, RTN_LOCAL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%s is not a valid route type"), - string); - return FALSE; - } - break; - default: - break; - } - } - - return TRUE; -} - -gboolean -_nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) -{ - NMUtilsNamedValue attrs_static[G_N_ELEMENTS(ip_route_attribute_spec)]; - gs_free NMUtilsNamedValue *attrs_free = NULL; - const NMUtilsNamedValue * attrs; - guint attrs_len; - GVariant * val; - guint i; - guint8 u8; - - g_return_val_if_fail(route, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - if (!route->attributes) - return TRUE; - - attrs = nm_utils_named_values_from_strdict(route->attributes, - &attrs_len, - attrs_static, - &attrs_free); - for (i = 0; i < attrs_len; i++) { - const char *key = attrs[i].name; - GVariant * val2 = attrs[i].value_ptr; - - if (!nm_ip_route_attribute_validate(key, val2, route->family, NULL, NULL)) - return FALSE; - } - - if ((val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_TYPE))) { - nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_STRING)); - u8 = nm_utils_route_type_by_name(g_variant_get_string(val, NULL)); - - if (u8 == RTN_LOCAL && route->family == AF_INET - && (val = g_hash_table_lookup(route->attributes, NM_IP_ROUTE_ATTRIBUTE_SCOPE))) { - nm_assert(g_variant_is_of_type(val, G_VARIANT_TYPE_BYTE)); - u8 = g_variant_get_byte(val); - - if (!NM_IN_SET(u8, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("route scope is invalid")); - return FALSE; - } - } - } - - return TRUE; -} - -/*****************************************************************************/ - -struct NMIPRoutingRule { - NMIPAddr from_bin; - NMIPAddr to_bin; - char * from_str; - char * to_str; - char * iifname; - char * oifname; - guint ref_count; - guint32 priority; - guint32 table; - gint32 suppress_prefixlength; - guint32 fwmark; - guint32 fwmask; - guint16 sport_start; - guint16 sport_end; - guint16 dport_start; - guint16 dport_end; - guint8 action; - guint8 from_len; - guint8 to_len; - guint8 tos; - guint8 ipproto; - bool is_v4 : 1; - bool sealed : 1; - bool priority_has : 1; - bool from_has : 1; - bool from_valid : 1; - bool to_has : 1; - bool to_valid : 1; - bool invert : 1; -}; - -static NMIPRoutingRule *_ip_routing_rule_dup(const NMIPRoutingRule *rule); - -G_DEFINE_BOXED_TYPE(NMIPRoutingRule, - nm_ip_routing_rule, - _ip_routing_rule_dup, - nm_ip_routing_rule_unref) - -static gboolean -NM_IS_IP_ROUTING_RULE(const NMIPRoutingRule *self, gboolean also_sealed) -{ - return self && self->ref_count > 0 && (also_sealed || !self->sealed); -} - -static int -_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) -{ - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - return self->is_v4 ? AF_INET : AF_INET6; -} - -static int -_ip_routing_rule_get_addr_size(const NMIPRoutingRule *self) -{ - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - return self->is_v4 ? sizeof(struct in_addr) : sizeof(struct in6_addr); -} - -static NMIPRoutingRule * -_ip_routing_rule_dup(const NMIPRoutingRule *rule) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); - - if (rule->sealed) - return nm_ip_routing_rule_ref((NMIPRoutingRule *) rule); - return nm_ip_routing_rule_new_clone(rule); -} - -/** - * nm_ip_routing_rule_new: - * @addr_family: the address family of the routing rule. Must be either - * %AF_INET (2) or %AF_INET6 (10). - * - * Returns: (transfer full): a newly created rule instance with the - * provided address family. The instance is unsealed. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_new(int addr_family) -{ - NMIPRoutingRule *self; - - g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); - - self = g_slice_new(NMIPRoutingRule); - *self = (NMIPRoutingRule){ - .ref_count = 1, - .is_v4 = (addr_family == AF_INET), - .action = FR_ACT_TO_TBL, - .table = RT_TABLE_MAIN, - .suppress_prefixlength = -1, - }; - return self; -} - -/** - * nm_ip_routing_rule_new_clone: - * @rule: the #NMIPRoutingRule to clone. - * - * Returns: (transfer full): a newly created rule instance with - * the same settings as @rule. Note that the instance will - * always be unsealred. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule) -{ - NMIPRoutingRule *self; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), NULL); - - self = g_slice_new(NMIPRoutingRule); - *self = (NMIPRoutingRule){ - .ref_count = 1, - .sealed = FALSE, - .is_v4 = rule->is_v4, - - .priority = rule->priority, - .priority_has = rule->priority_has, - - .invert = rule->invert, - - .tos = rule->tos, - - .fwmark = rule->fwmark, - .fwmask = rule->fwmask, - - .sport_start = rule->sport_start, - .sport_end = rule->sport_end, - .dport_start = rule->dport_start, - .dport_end = rule->dport_end, - - .ipproto = rule->ipproto, - - .from_len = rule->from_len, - .from_bin = rule->from_bin, - .from_str = (rule->from_has && !rule->from_valid) ? g_strdup(rule->from_str) : NULL, - .from_has = rule->from_has, - .from_valid = rule->from_valid, - - .to_len = rule->to_len, - .to_bin = rule->to_bin, - .to_str = (rule->to_has && !rule->to_valid) ? g_strdup(rule->to_str) : NULL, - .to_has = rule->to_has, - .to_valid = rule->to_valid, - - .iifname = g_strdup(rule->iifname), - .oifname = g_strdup(rule->oifname), - - .action = rule->action, - .table = rule->table, - - .suppress_prefixlength = rule->suppress_prefixlength, - }; - return self; -} - -/** - * nm_ip_routing_rule_ref: - * @self: (allow-none): the #NMIPRoutingRule instance - * - * Increases the reference count of the instance. - * This is not thread-safe. - * - * Returns: (transfer full): the @self argument with incremented - * reference count. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_ref(NMIPRoutingRule *self) -{ - if (!self) - return NULL; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - nm_assert(self->ref_count < G_MAXUINT); - self->ref_count++; - return self; -} - -/** - * nm_ip_routing_rule_unref: - * @self: (allow-none): the #NMIPRoutingRule instance - * - * Decreases the reference count of the instance and destroys - * the instance if the reference count reaches zero. - * This is not thread-safe. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_unref(NMIPRoutingRule *self) -{ - if (!self) - return; - - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - if (--self->ref_count > 0) - return; - - g_free(self->from_str); - g_free(self->to_str); - g_free(self->iifname); - g_free(self->oifname); - - g_slice_free(NMIPRoutingRule, self); -} - -/** - * nm_ip_routing_rule_is_sealed: - * @self: the #NMIPRoutingRule instance - * - * Returns: whether @self is sealed. Once sealed, an instance - * cannot be modified nor unsealed. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_is_sealed(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - - return self->sealed; -} - -/** - * nm_ip_routing_rule_seal: - * @self: the #NMIPRoutingRule instance - * - * Seals the routing rule. Afterwards, the instance can no longer be - * modified, and it is a bug to call any of the accessors that would - * modify the rule. If @self was already sealed, this has no effect. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_seal(NMIPRoutingRule *self) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); - - self->sealed = TRUE; -} - -/** - * nm_ip_routing_rule_get_addr_family: - * @self: the #NMIPRoutingRule instance - * - * Returns: the address family of the rule. Either %AF_INET or %AF_INET6. - * - * Since: 1.18 - */ -int -nm_ip_routing_rule_get_addr_family(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), AF_UNSPEC); - - return _ip_routing_rule_get_addr_family(self); -} - -/** - * nm_ip_routing_rule_get_priority: - * @self: the #NMIPRoutingRule instance - * - * Returns: the priority. A valid priority is in the range from - * 0 to %G_MAXUINT32. If unset, -1 is returned. - * - * Since: 1.18 - */ -gint64 -nm_ip_routing_rule_get_priority(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); - - return self->priority_has ? (gint64) self->priority : (gint64) -1; -} - -/** - * nm_ip_routing_rule_set_priority: - * @self: the #NMIPRoutingRule instance - * @priority: the priority to set - * - * A valid priority ranges from 0 to %G_MAXUINT32. "-1" is also allowed - * to reset the priority. It is a bug calling this function with any - * other value. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_priority(NMIPRoutingRule *self, gint64 priority) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (priority >= 0 && priority <= (gint64) G_MAXUINT32) { - self->priority = (guint32) priority; - self->priority_has = TRUE; - } else { - g_return_if_fail(priority == -1); - self->priority = 0; - self->priority_has = FALSE; - } -} - -/** - * nm_ip_routing_rule_get_invert: - * @self: the #NMIPRoutingRule instance - * - * Returns: the "invert" setting of the rule. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_get_invert(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - - return self->invert; -} - -/** - * nm_ip_routing_rule_set_invert: - * @self: the #NMIPRoutingRule instance - * @invert: the new value to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_invert(NMIPRoutingRule *self, gboolean invert) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->invert = invert; -} - -/** - * nm_ip_routing_rule_get_from_len: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set prefix length for the from/src parameter. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_from_len(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->from_len; -} - -/** - * nm_ip_routing_rule_get_from: - * @self: the #NMIPRoutingRule instance - * - * Returns: (transfer none): the set from/src parameter or - * %NULL, if no value is set. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_from(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!self->from_has) - return NULL; - if (!self->from_str) { - nm_assert(self->from_valid); - ((NMIPRoutingRule *) self)->from_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->from_bin); - } - return self->from_str; -} - -const NMIPAddr * -nm_ip_routing_rule_get_from_bin(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return (self->from_has && self->from_valid) ? &self->from_bin : NULL; -} - -void -nm_ip_routing_rule_set_from_bin(NMIPRoutingRule *self, gconstpointer from, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - nm_clear_g_free(&self->from_str); - - if (!from) { - self->from_has = FALSE; - self->from_len = len; - return; - } - - self->from_has = TRUE; - self->from_len = len; - self->from_valid = TRUE; - nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->from_bin, from); -} - -/** - * nm_ip_routing_rule_set_from: - * @self: the #NMIPRoutingRule instance - * @from: (allow-none): the from/src address to set. - * The address family must match. - * @len: the corresponding prefix length of the address. - * - * Setting invalid values is accepted, but will later fail - * during nm_ip_routing_rule_validate(). - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (!from) { - nm_clear_g_free(&self->from_str); - self->from_has = FALSE; - self->from_len = len; - return; - } - - nm_clear_g_free(&self->from_str); - self->from_has = TRUE; - self->from_len = len; - self->from_valid = nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), - from, - NULL, - &self->from_bin); - if (!self->from_valid) - self->from_str = g_strdup(from); -} - -/** - * nm_ip_routing_rule_get_to_len: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set prefix length for the to/dst parameter. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_to_len(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->to_len; -} - -/** - * nm_ip_routing_rule_get_to: - * @self: the #NMIPRoutingRule instance - * - * Returns: (transfer none): the set to/dst parameter or - * %NULL, if no value is set. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_to(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!self->to_has) - return NULL; - if (!self->to_str) { - nm_assert(self->to_valid); - ((NMIPRoutingRule *) self)->to_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->to_bin); - } - return self->to_str; -} - -const NMIPAddr * -nm_ip_routing_rule_get_to_bin(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return (self->to_has && self->to_valid) ? &self->to_bin : NULL; -} - -void -nm_ip_routing_rule_set_to_bin(NMIPRoutingRule *self, gconstpointer to, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - nm_clear_g_free(&self->to_str); - - if (!to) { - self->to_has = FALSE; - self->to_len = len; - return; - } - - self->to_has = TRUE; - self->to_len = len; - self->to_valid = TRUE; - nm_ip_addr_set(_ip_routing_rule_get_addr_family(self), &self->to_bin, to); -} - -/** - * nm_ip_routing_rule_set_to: - * @self: the #NMIPRoutingRule instance - * @to: (allow-none): the to/dst address to set. - * The address family must match. - * @len: the corresponding prefix length of the address. - * If @to is %NULL, this valid is ignored. - * - * Setting invalid values is accepted, but will later fail - * during nm_ip_routing_rule_validate(). - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - if (!to) { - nm_clear_g_free(&self->to_str); - self->to_has = FALSE; - self->to_len = len; - return; - } - - nm_clear_g_free(&self->to_str); - self->to_has = TRUE; - self->to_len = len; - self->to_valid = - nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), to, NULL, &self->to_bin); - if (!self->to_valid) - self->to_str = g_strdup(to); -} - -/** - * nm_ip_routing_rule_get_tos: - * @self: the #NMIPRoutingRule instance - * - * Returns: the tos of the rule. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_tos(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->tos; -} - -/** - * nm_ip_routing_rule_set_tos: - * @self: the #NMIPRoutingRule instance - * @tos: the tos to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_tos(NMIPRoutingRule *self, guint8 tos) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->tos = tos; -} - -/** - * nm_ip_routing_rule_get_ipproto: - * @self: the #NMIPRoutingRule instance - * - * Returns: the ipproto of the rule. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_ipproto(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->ipproto; -} - -/** - * nm_ip_routing_rule_set_ipproto: - * @self: the #NMIPRoutingRule instance - * @ipproto: the ipproto to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_ipproto(NMIPRoutingRule *self, guint8 ipproto) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->ipproto = ipproto; -} - -/** - * nm_ip_routing_rule_get_source_port_start: - * @self: the #NMIPRoutingRule instance - * - * Returns: the source port start setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_source_port_start(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->sport_start; -} - -/** - * nm_ip_routing_rule_get_source_port_end: - * @self: the #NMIPRoutingRule instance - * - * Returns: the source port end setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_source_port_end(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->sport_end; -} - -/** - * nm_ip_routing_rule_set_source_port: - * @self: the #NMIPRoutingRule instance - * @start: the start port to set. - * @end: the end port to set. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_source_port(NMIPRoutingRule *self, guint16 start, guint16 end) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->sport_start = start; - self->sport_end = end; -} - -/** - * nm_ip_routing_rule_get_destination_port_start: - * @self: the #NMIPRoutingRule instance - * - * Returns: the destination port start setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_destination_port_start(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->dport_start; -} - -/** - * nm_ip_routing_rule_get_destination_port_end: - * @self: the #NMIPRoutingRule instance - * - * Returns: the destination port end setting. - * - * Since: 1.18 - */ -guint16 -nm_ip_routing_rule_get_destination_port_end(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->dport_end; -} - -/** - * nm_ip_routing_rule_set_destination_port: - * @self: the #NMIPRoutingRule instance - * @start: the start port to set. - * @end: the end port to set. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_destination_port(NMIPRoutingRule *self, guint16 start, guint16 end) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->dport_start = start; - self->dport_end = end; -} - -/** - * nm_ip_routing_rule_get_fwmark: - * @self: the #NMIPRoutingRule instance - * - * Returns: the fwmark setting. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_fwmark(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->fwmark; -} - -/** - * nm_ip_routing_rule_get_fwmask: - * @self: the #NMIPRoutingRule instance - * - * Returns: the fwmask setting. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_fwmask(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->fwmask; -} - -/** - * nm_ip_routing_rule_set_fwmark: - * @self: the #NMIPRoutingRule instance - * @fwmark: the fwmark - * @fwmask: the fwmask - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_fwmark(NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->fwmark = fwmark; - self->fwmask = fwmask; -} - -/** - * nm_ip_routing_rule_get_iifname: - * @self: the #NMIPRoutingRule instance. - * - * Returns: (transfer none): the set iifname or %NULL if unset. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_iifname(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return self->iifname; -} - -gboolean -nm_ip_routing_rule_get_xifname_bin(const NMIPRoutingRule *self, - gboolean iif /* or else oif */, - char out_xifname[static 16 /* IFNAMSIZ */]) -{ - gs_free gpointer bin_to_free = NULL; - const char * xifname; - gconstpointer bin; - gsize len; - - nm_assert(NM_IS_IP_ROUTING_RULE(self, TRUE)); - nm_assert(out_xifname); - - xifname = iif ? self->iifname : self->oifname; - - if (!xifname) - return FALSE; - - bin = nm_utils_buf_utf8safe_unescape(xifname, - NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, - &len, - &bin_to_free); - - strncpy(out_xifname, bin, 16 /* IFNAMSIZ */); - out_xifname[15] = '\0'; - return TRUE; -} - -/** - * nm_ip_routing_rule_set_iifname: - * @self: the #NMIPRoutingRule instance. - * @iifname: (allow-none): the iifname to set or %NULL to unset. - * - * The name supports C backslash escaping for non-UTF-8 characters. - * Note that nm_ip_routing_rule_from_string() too uses backslash - * escaping when tokenizing the words by whitespace. So, in string - * representation you'd get double backslashes. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_iifname(NMIPRoutingRule *self, const char *iifname) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - g_free(self->iifname); - self->iifname = g_strdup(iifname); -} - -/** - * nm_ip_routing_rule_get_oifname: - * @self: the #NMIPRoutingRule instance. - * - * Returns: (transfer none): the set oifname or %NULL if unset. - * - * Since: 1.18 - */ -const char * -nm_ip_routing_rule_get_oifname(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - return self->oifname; -} - -/** - * nm_ip_routing_rule_set_oifname: - * @self: the #NMIPRoutingRule instance. - * @oifname: (allow-none): the oifname to set or %NULL to unset. - * - * The name supports C backslash escaping for non-UTF-8 characters. - * Note that nm_ip_routing_rule_from_string() too uses backslash - * escaping when tokenizing the words by whitespace. So, in string - * representation you'd get double backslashes. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_oifname(NMIPRoutingRule *self, const char *oifname) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - g_free(self->oifname); - self->oifname = g_strdup(oifname); -} - -/** - * nm_ip_routing_rule_get_action: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set action. - * - * Since: 1.18 - */ -guint8 -nm_ip_routing_rule_get_action(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->action; -} - -/** - * nm_ip_routing_rule_set_action: - * @self: the #NMIPRoutingRule instance - * @action: the action to set - * - * Note that currently only certain actions are allowed. nm_ip_routing_rule_validate() - * will reject unsupported actions as invalid. - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_action(NMIPRoutingRule *self, guint8 action) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->action = action; -} - -/** - * nm_ip_routing_rule_get_table: - * @self: the #NMIPRoutingRule instance - * - * Returns: the set table. - * - * Since: 1.18 - */ -guint32 -nm_ip_routing_rule_get_table(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), 0); - - return self->table; -} - -/** - * nm_ip_routing_rule_set_table: - * @self: the #NMIPRoutingRule instance - * @table: the table to set - * - * Since: 1.18 - */ -void -nm_ip_routing_rule_set_table(NMIPRoutingRule *self, guint32 table) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->table = table; -} - -/** - * nm_ip_routing_rule_get_suppress_prefixlength: - * @self: the #NMIPRoutingRule instance - * - * Returns: the suppress_prefixlength of the rule. -1 means that the value is unset. - * - * Since: 1.20 - */ -gint32 -nm_ip_routing_rule_get_suppress_prefixlength(const NMIPRoutingRule *self) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), -1); - - return self->suppress_prefixlength; -} - -/** - * nm_ip_routing_rule_set_suppress_prefixlength: - * @self: the #NMIPRoutingRule instance - * @suppress_prefixlength: the suppress_prefixlength to set. The value -1 means - * unset. - * - * Since: 1.20 - */ -void -nm_ip_routing_rule_set_suppress_prefixlength(NMIPRoutingRule *self, gint32 suppress_prefixlength) -{ - g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, FALSE)); - - self->suppress_prefixlength = suppress_prefixlength; -} - -/** - * nm_ip_routing_rule_cmp: - * @rule: (allow-none): the #NMIPRoutingRule instance to compare - * @other: (allow-none): the other #NMIPRoutingRule instance to compare - * - * Returns: zero, a positive, or a negative integer to indicate - * equality or how the arguments compare. - * - * Since: 1.18 - */ -int -nm_ip_routing_rule_cmp(const NMIPRoutingRule *rule, const NMIPRoutingRule *other) -{ - NM_CMP_SELF(rule, other); - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(rule, TRUE), 0); - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(other, TRUE), 0); - - NM_CMP_FIELD_UNSAFE(rule, other, priority_has); - if (rule->priority_has) - NM_CMP_FIELD(rule, other, priority); - - NM_CMP_FIELD_UNSAFE(rule, other, is_v4); - - NM_CMP_FIELD_UNSAFE(rule, other, invert); - - NM_CMP_FIELD(rule, other, tos); - - NM_CMP_FIELD(rule, other, fwmark); - NM_CMP_FIELD(rule, other, fwmask); - - NM_CMP_FIELD(rule, other, action); - - NM_CMP_FIELD(rule, other, table); - - NM_CMP_FIELD(rule, other, suppress_prefixlength); - - NM_CMP_FIELD(rule, other, sport_start); - NM_CMP_FIELD(rule, other, sport_end); - NM_CMP_FIELD(rule, other, dport_start); - NM_CMP_FIELD(rule, other, dport_end); - - NM_CMP_FIELD(rule, other, ipproto); - - /* We compare the plain strings, not the binary values after utf8safe unescaping. - * - * The reason is, that the rules differ already when the direct strings differ, not - * only when the unescaped names differ. */ - NM_CMP_FIELD_STR0(rule, other, iifname); - NM_CMP_FIELD_STR0(rule, other, oifname); - - NM_CMP_FIELD(rule, other, from_len); - - NM_CMP_FIELD_UNSAFE(rule, other, from_has); - if (rule->from_has) { - NM_CMP_FIELD_UNSAFE(rule, other, from_valid); - if (rule->from_valid) { - NM_CMP_RETURN( - memcmp(&rule->from_bin, &other->from_bin, _ip_routing_rule_get_addr_size(rule))); - } else - NM_CMP_FIELD_STR(rule, other, from_str); - } - - NM_CMP_FIELD(rule, other, to_len); - - NM_CMP_FIELD_UNSAFE(rule, other, to_has); - if (rule->to_has) { - NM_CMP_FIELD_UNSAFE(rule, other, to_valid); - if (rule->to_valid) { - NM_CMP_RETURN( - memcmp(&rule->to_bin, &other->to_bin, _ip_routing_rule_get_addr_size(rule))); - } else - NM_CMP_FIELD_STR(rule, other, to_str); - } - - return 0; -} - -static gboolean -_rr_xport_range_valid(guint16 xport_start, guint16 xport_end) -{ - if (xport_start == 0) - return (xport_end == 0); - - return xport_start <= xport_end && xport_end < 0xFFFFu; -} - -static gboolean -_rr_xport_range_parse(char *str, gint64 *out_start, guint16 *out_end) -{ - guint16 start, end; - gint64 i64; - char * s; - - s = strchr(str, '-'); - if (s) - *(s++) = '\0'; - - i64 = _nm_utils_ascii_str_to_int64(str, 10, 0, 0xFFFF, -1); - if (i64 == -1) - return FALSE; - - start = i64; - if (s) { - i64 = _nm_utils_ascii_str_to_int64(s, 10, 0, 0xFFFF, -1); - if (i64 == -1) - return FALSE; - end = i64; - } else - end = start; - - *out_start = start; - *out_end = end; - return TRUE; -} - -/** - * nm_ip_routing_rule_validate: - * @self: the #NMIPRoutingRule instance to validate - * @error: (allow-none) (out): the error result if validation fails. - * - * Returns: %TRUE if the rule validates. - * - * Since: 1.18 - */ -gboolean -nm_ip_routing_rule_validate(const NMIPRoutingRule *self, GError **error) -{ - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - /* Kernel may be more flexible about validating. We do a strict validation - * here and reject certain settings eagerly. We can always relax it later. */ - - if (!self->priority_has) { - /* iproute2 accepts not specifying the priority, in which case kernel will select - * an unused priority. We don't allow for that, and will always require the user to - * select a priority. - * - * Note that if the user selects priority 0 or a non-unique priority, this is problematic - * due to kernel bugs rh#1685816 and rh#1685816. It may result in NetworkManager wrongly being - * unable to add a rule or deleting the wrong rule. - * This problem is not at all specific to the priority, it affects all rules that - * have default values which confuse kernel. But setting a unique priority avoids - * this problem nicely. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid priority")); - return FALSE; - } - - if (NM_IN_SET(self->action, FR_ACT_TO_TBL)) { - if (self->table == 0) { - /* with IPv4, kernel allows a table (in RTM_NEWRULE) of zero to automatically select - * an unused table. We don't. The user needs to specify the table. - * - * For IPv6, kernel doesn't allow a table of zero, so we are consistent here. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing table")); - return FALSE; - } - } else { - /* whitelist the actions that we currently. */ - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid action")); - return FALSE; - } - - if (self->from_len == 0) { - if (self->from_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has from/src but the prefix-length is zero")); - return FALSE; - } - } else if (self->from_len > 0 && self->from_len <= 8 * _ip_routing_rule_get_addr_size(self)) { - if (!self->from_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing from/src for a non zero prefix-length")); - return FALSE; - } - if (!self->from_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid from/src")); - return FALSE; - } - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid prefix length for from/src")); - return FALSE; - } - - if (self->to_len == 0) { - if (self->to_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("has to/dst but the prefix-length is zero")); - return FALSE; - } - } else if (self->to_len > 0 && self->to_len <= 8 * _ip_routing_rule_get_addr_size(self)) { - if (!self->to_has) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing to/dst for a non zero prefix-length")); - return FALSE; - } - if (!self->to_valid) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid to/dst")); - return FALSE; - } - } else { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid prefix length for to/dst")); - return FALSE; - } - - if (self->iifname - && (!g_utf8_validate(self->iifname, -1, NULL) - || !nm_utils_is_valid_iface_name_utf8safe(self->iifname))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid iifname")); - return FALSE; - } - - if (self->oifname - && (!g_utf8_validate(self->oifname, -1, NULL) - || !nm_utils_is_valid_iface_name_utf8safe(self->oifname))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid oifname")); - return FALSE; - } - - if (!_rr_xport_range_valid(self->sport_start, self->sport_end)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid source port range")); - return FALSE; - } - - if (!_rr_xport_range_valid(self->dport_start, self->dport_end)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid destination port range")); - return FALSE; - } - - if (self->suppress_prefixlength != -1) { - if (self->suppress_prefixlength < -1 - || self->suppress_prefixlength > (self->is_v4 ? 32 : 128)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("suppress_prefixlength out of range")); - return FALSE; - } - if (self->action != FR_ACT_TO_TBL) { - g_set_error_literal( - error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("suppress_prefixlength is only allowed with the to-table action")); - return FALSE; - } - } - - return TRUE; -} - -/*****************************************************************************/ - -typedef enum { - RR_DBUS_ATTR_ACTION, - RR_DBUS_ATTR_DPORT_END, - RR_DBUS_ATTR_DPORT_START, - RR_DBUS_ATTR_FAMILY, - RR_DBUS_ATTR_FROM, - RR_DBUS_ATTR_FROM_LEN, - RR_DBUS_ATTR_FWMARK, - RR_DBUS_ATTR_FWMASK, - RR_DBUS_ATTR_IIFNAME, - RR_DBUS_ATTR_INVERT, - RR_DBUS_ATTR_IPPROTO, - RR_DBUS_ATTR_OIFNAME, - RR_DBUS_ATTR_PRIORITY, - RR_DBUS_ATTR_SPORT_END, - RR_DBUS_ATTR_SPORT_START, - RR_DBUS_ATTR_TABLE, - RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - RR_DBUS_ATTR_TO, - RR_DBUS_ATTR_TOS, - RR_DBUS_ATTR_TO_LEN, - - _RR_DBUS_ATTR_NUM, -} RRDbusAttr; - -typedef struct { - const char * name; - const GVariantType *dbus_type; -} RRDbusData; - -static const RRDbusData rr_dbus_data[_RR_DBUS_ATTR_NUM] = { -#define _D(attr, _name, type) \ - [attr] = { \ - .name = _name, \ - .dbus_type = type, \ - } - _D(RR_DBUS_ATTR_ACTION, NM_IP_ROUTING_RULE_ATTR_ACTION, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_DPORT_END, NM_IP_ROUTING_RULE_ATTR_DPORT_END, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_DPORT_START, NM_IP_ROUTING_RULE_ATTR_DPORT_START, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_FAMILY, NM_IP_ROUTING_RULE_ATTR_FAMILY, G_VARIANT_TYPE_INT32), - _D(RR_DBUS_ATTR_FROM, NM_IP_ROUTING_RULE_ATTR_FROM, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_FROM_LEN, NM_IP_ROUTING_RULE_ATTR_FROM_LEN, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_FWMARK, NM_IP_ROUTING_RULE_ATTR_FWMARK, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_FWMASK, NM_IP_ROUTING_RULE_ATTR_FWMASK, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_IIFNAME, NM_IP_ROUTING_RULE_ATTR_IIFNAME, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_INVERT, NM_IP_ROUTING_RULE_ATTR_INVERT, G_VARIANT_TYPE_BOOLEAN), - _D(RR_DBUS_ATTR_IPPROTO, NM_IP_ROUTING_RULE_ATTR_IPPROTO, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_OIFNAME, NM_IP_ROUTING_RULE_ATTR_OIFNAME, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_PRIORITY, NM_IP_ROUTING_RULE_ATTR_PRIORITY, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_SPORT_END, NM_IP_ROUTING_RULE_ATTR_SPORT_END, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_SPORT_START, NM_IP_ROUTING_RULE_ATTR_SPORT_START, G_VARIANT_TYPE_UINT16), - _D(RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - NM_IP_ROUTING_RULE_ATTR_SUPPRESS_PREFIXLENGTH, - G_VARIANT_TYPE_INT32), - _D(RR_DBUS_ATTR_TABLE, NM_IP_ROUTING_RULE_ATTR_TABLE, G_VARIANT_TYPE_UINT32), - _D(RR_DBUS_ATTR_TO, NM_IP_ROUTING_RULE_ATTR_TO, G_VARIANT_TYPE_STRING), - _D(RR_DBUS_ATTR_TOS, NM_IP_ROUTING_RULE_ATTR_TOS, G_VARIANT_TYPE_BYTE), - _D(RR_DBUS_ATTR_TO_LEN, NM_IP_ROUTING_RULE_ATTR_TO_LEN, G_VARIANT_TYPE_BYTE), -#undef _D -}; - -static void -_rr_variants_free(GVariant *(*p_variants)[]) -{ - int i; - - for (i = 0; i < _RR_DBUS_ATTR_NUM; i++) { - if ((*p_variants)[i]) - g_variant_unref((*p_variants)[i]); - } -} - -NMIPRoutingRule * -nm_ip_routing_rule_from_dbus(GVariant *variant, gboolean strict, GError **error) -{ - nm_auto(_rr_variants_free) GVariant *variants[_RR_DBUS_ATTR_NUM] = {}; - nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; - RRDbusAttr attr; - GVariantIter iter; - const char * iter_key; - GVariant * iter_val; - int addr_family; - int i; - - g_variant_iter_init(&iter, variant); - -#if NM_MORE_ASSERTS > 10 - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - nm_assert(rr_dbus_data[attr].name); - nm_assert(g_variant_type_string_is_valid((const char *) rr_dbus_data[attr].dbus_type)); - } -#endif - - while (g_variant_iter_next(&iter, "{&sv}", &iter_key, &iter_val)) { - gs_unref_variant GVariant *iter_val2 = iter_val; - - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - if (nm_streq(iter_key, rr_dbus_data[attr].name)) { - if (variants[attr]) { - if (strict) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("duplicate key %s"), - iter_key); - return NULL; - } - g_variant_unref(variants[attr]); - } - variants[attr] = g_steal_pointer(&iter_val2); - break; - } - } - - if (attr >= _RR_DBUS_ATTR_NUM && strict) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid key \"%s\""), - iter_key); - return NULL; - } - } - - for (attr = 0; attr < _RR_DBUS_ATTR_NUM; attr++) { - if (!variants[attr]) - continue; - if (!g_variant_is_of_type(variants[attr], rr_dbus_data[attr].dbus_type)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid variant type '%s' for \"%s\""), - (const char *) rr_dbus_data[attr].dbus_type, - rr_dbus_data[attr].name); - return NULL; - } - } - - if (!variants[RR_DBUS_ATTR_FAMILY]) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("missing \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); - return NULL; - } - addr_family = g_variant_get_int32(variants[RR_DBUS_ATTR_FAMILY]); - if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid \"" NM_IP_ROUTING_RULE_ATTR_FAMILY "\"")); - return NULL; - } - - self = nm_ip_routing_rule_new(addr_family); - - if (variants[RR_DBUS_ATTR_PRIORITY]) - nm_ip_routing_rule_set_priority(self, - g_variant_get_uint32(variants[RR_DBUS_ATTR_PRIORITY])); - - if (variants[RR_DBUS_ATTR_INVERT]) - nm_ip_routing_rule_set_invert(self, g_variant_get_boolean(variants[RR_DBUS_ATTR_INVERT])); - - if (variants[RR_DBUS_ATTR_TOS]) - nm_ip_routing_rule_set_tos(self, g_variant_get_byte(variants[RR_DBUS_ATTR_TOS])); - - if (variants[RR_DBUS_ATTR_IPPROTO]) - nm_ip_routing_rule_set_ipproto(self, g_variant_get_byte(variants[RR_DBUS_ATTR_IPPROTO])); - - for (i = 0; i < 2; i++) { - GVariant *v_start = variants[i ? RR_DBUS_ATTR_SPORT_START : RR_DBUS_ATTR_DPORT_START]; - GVariant *v_end = variants[i ? RR_DBUS_ATTR_SPORT_END : RR_DBUS_ATTR_DPORT_END]; - guint16 start, end; - - if (!v_start && !v_end) - continue; - - /* if start or end is missing, it defaults to the other parameter, respectively. */ - if (v_start) - start = g_variant_get_uint16(v_start); - else - start = g_variant_get_uint16(v_end); - if (v_end) - end = g_variant_get_uint16(v_end); - else - end = g_variant_get_uint16(v_start); - - if (i) - nm_ip_routing_rule_set_source_port(self, start, end); - else - nm_ip_routing_rule_set_destination_port(self, start, end); - } - - if (variants[RR_DBUS_ATTR_FWMARK] || variants[RR_DBUS_ATTR_FWMASK]) { - nm_ip_routing_rule_set_fwmark( - self, - variants[RR_DBUS_ATTR_FWMARK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMARK]) - : 0u, - variants[RR_DBUS_ATTR_FWMASK] ? g_variant_get_uint32(variants[RR_DBUS_ATTR_FWMASK]) - : 0u); - } - - if (variants[RR_DBUS_ATTR_FROM] || variants[RR_DBUS_ATTR_FROM_LEN]) { - nm_ip_routing_rule_set_from( - self, - variants[RR_DBUS_ATTR_FROM] ? g_variant_get_string(variants[RR_DBUS_ATTR_FROM], NULL) - : NULL, - variants[RR_DBUS_ATTR_FROM_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_FROM_LEN]) - : 0u); - } - - if (variants[RR_DBUS_ATTR_TO] || variants[RR_DBUS_ATTR_TO_LEN]) { - nm_ip_routing_rule_set_to( - self, - variants[RR_DBUS_ATTR_TO] ? g_variant_get_string(variants[RR_DBUS_ATTR_TO], NULL) - : NULL, - variants[RR_DBUS_ATTR_TO_LEN] ? g_variant_get_byte(variants[RR_DBUS_ATTR_TO_LEN]) : 0u); - } - - if (variants[RR_DBUS_ATTR_IIFNAME]) - nm_ip_routing_rule_set_iifname(self, - g_variant_get_string(variants[RR_DBUS_ATTR_IIFNAME], NULL)); - - if (variants[RR_DBUS_ATTR_OIFNAME]) - nm_ip_routing_rule_set_oifname(self, - g_variant_get_string(variants[RR_DBUS_ATTR_OIFNAME], NULL)); - - if (variants[RR_DBUS_ATTR_ACTION]) - nm_ip_routing_rule_set_action(self, g_variant_get_byte(variants[RR_DBUS_ATTR_ACTION])); - - if (variants[RR_DBUS_ATTR_TABLE]) - nm_ip_routing_rule_set_table(self, g_variant_get_uint32(variants[RR_DBUS_ATTR_TABLE])); - - if (variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH]) - nm_ip_routing_rule_set_suppress_prefixlength( - self, - g_variant_get_int32(variants[RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH])); - - if (strict && !nm_ip_routing_rule_validate(self, error)) - return NULL; - - return g_steal_pointer(&self); -} - -static void -_rr_to_dbus_add(GVariantBuilder *builder, RRDbusAttr attr, GVariant *value) -{ - nm_assert(builder); - nm_assert(value); - nm_assert(g_variant_is_floating(value)); - nm_assert(g_variant_is_of_type(value, rr_dbus_data[attr].dbus_type)); - - g_variant_builder_add(builder, "{sv}", rr_dbus_data[attr].name, value); -} - -GVariant * -nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) -{ - GVariantBuilder builder; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_FAMILY, - g_variant_new_int32(_ip_routing_rule_get_addr_family(self))); - - if (self->invert) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_INVERT, g_variant_new_boolean(TRUE)); - - if (self->priority_has) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_PRIORITY, g_variant_new_uint32(self->priority)); - - if (self->tos != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TOS, g_variant_new_byte(self->tos)); - - if (self->ipproto != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IPPROTO, g_variant_new_byte(self->ipproto)); - - if (self->fwmark != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMARK, g_variant_new_uint32(self->fwmark)); - - if (self->fwmask != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FWMASK, g_variant_new_uint32(self->fwmask)); - - if (self->sport_start != 0 || self->sport_end != 0) { - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SPORT_START, - g_variant_new_uint16(self->sport_start)); - if (self->sport_start != self->sport_end) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SPORT_END, - g_variant_new_uint16(self->sport_end)); - } - - if (self->dport_start != 0 || self->dport_end != 0) { - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_DPORT_START, - g_variant_new_uint16(self->dport_start)); - if (self->dport_start != self->dport_end) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_DPORT_END, - g_variant_new_uint16(self->dport_end)); - } - - if (self->from_has || self->from_len != 0) { - _rr_to_dbus_add( - &builder, - RR_DBUS_ATTR_FROM, - g_variant_new_string(self->from_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->from_bin, - addr_str))); - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FROM_LEN, g_variant_new_byte(self->from_len)); - } - - if (self->to_has || self->to_len != 0) { - _rr_to_dbus_add( - &builder, - RR_DBUS_ATTR_TO, - g_variant_new_string(self->to_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->to_bin, - addr_str))); - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TO_LEN, g_variant_new_byte(self->to_len)); - } - - if (self->iifname) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_IIFNAME, g_variant_new_string(self->iifname)); - - if (self->oifname) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_OIFNAME, g_variant_new_string(self->oifname)); - - if (self->action != FR_ACT_TO_TBL) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_ACTION, g_variant_new_byte(self->action)); - - if (self->table != 0) - _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TABLE, g_variant_new_uint32(self->table)); - - if (self->suppress_prefixlength != -1) - _rr_to_dbus_add(&builder, - RR_DBUS_ATTR_SUPPRESS_PREFIXLENGTH, - g_variant_new_int32(self->suppress_prefixlength)); - - return g_variant_builder_end(&builder); -} - -/*****************************************************************************/ - -static gboolean -_rr_string_validate(gboolean for_from /* or else to-string */, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - if (NM_FLAGS_ANY(to_string_flags, - ~(NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET - | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 - | NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unsupported to-string-flags argument")); - return FALSE; - } - - if (extra_args && g_hash_table_size(extra_args) > 0) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("Unsupported extra-argument")); - return FALSE; - } - - return TRUE; -} - -static int -_rr_string_addr_family_from_flags(NMIPRoutingRuleAsStringFlags to_string_flags) -{ - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)) { - if (!NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) - return AF_INET; - } else if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)) - return AF_INET6; - return AF_UNSPEC; -} - -/** - * nm_ip_routing_rule_from_string: - * @str: the string representation to convert to an #NMIPRoutingRule - * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the - * string conversion. - * @extra_args: (allow-none): extra arguments for controlling the string - * conversion. Currently, not extra arguments are supported. - * @error: (allow-none) (out): the error reason. - * - * Returns: (transfer full): the new #NMIPRoutingRule or %NULL on error. - * - * Since: 1.18 - */ -NMIPRoutingRule * -nm_ip_routing_rule_from_string(const char * str, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - nm_auto_unref_ip_routing_rule NMIPRoutingRule *self = NULL; - gs_free const char ** tokens = NULL; - gsize i_token; - gboolean any_words = FALSE; - char * word0 = NULL; - char * word1 = NULL; - char * word_from = NULL; - char * word_to = NULL; - char * word_iifname = NULL; - char * word_oifname = NULL; - gint64 i64_priority = -1; - gint64 i64_table = -1; - gint64 i64_tos = -1; - gint64 i64_fwmark = -1; - gint64 i64_fwmask = -1; - gint64 i64_sport_start = -1; - gint64 i64_ipproto = -1; - gint64 i64_suppress_prefixlength = -1; - guint16 sport_end = 0; - gint64 i64_dport_start = -1; - guint16 dport_end = 0; - gboolean val_invert = FALSE; - int addr_family = AF_UNSPEC; - NMIPAddr val_from = {}; - NMIPAddr val_to = {}; - int val_from_len = -1; - int val_to_len = -1; - char * s; - - g_return_val_if_fail(str, NULL); - - if (!_rr_string_validate(TRUE, to_string_flags, extra_args, error)) - return NULL; - - /* NM_IP_ROUTING_RULE_TO_STRING_TYPE_IPROUTE gives a string representation that is - * partly compatibly with iproute2. That is, the part after `ip -[46] rule add $ARGS`. - * There are differences though: - * - * - trying to convert an invalid rule to string may not be possible. The reason is for - * example that an invalid rule can have nm_ip_routing_rule_get_from() like "bogus", - * but we don't write that as "from bogus". In general, if you try to convert an invalid - * rule to string, the operation may fail or the result may itself not be parsable. - * Of course, valid rules can be converted to string and read back the same (round-trip). - * - * - iproute2 in may regards is flexible about the command lines. For example - * - for tables it accepts table names from /etc/iproute2/rt_tables. We only - * accept the special aliases "main", "local", and "default". - * - key names like "preference" can be abbreviated to "pref", we don't do that. - * - the "preference"/"priority" may be unspecified, in which kernel automatically - * chooses an unused priority (during `ip rule add`). We don't allow for that, the - * priority must be explicitly set. - * - * - iproute2 does not support any escaping. Well, it's the shell that supports quoting - * and escaping and splits the command line. We need to split the command line ourself, - * but we don't support full shell quotation. - * from-string tokenizes words at (ASCII) whitespaces (removing the whitespaces). - * It also supports backslash escaping (e.g. to contain whitespace), but it does - * not support special escape sequences. Values are taken literally, meaning - * "\n\ \111" gives results in "n 111". - * The strings really shouldn't contain any special characters that require escaping, - * but that's the rule. - * This also goes together with the @allow_escaping parameter of nm_utils_strsplit_set(). - * If you concatenate multiple rule expressions with a delimiter, the delimiter inside - * each word can be backslash escaped, and nm_utils_strsplit_set(allow_escaping=TRUE) will - * properly split the words, preserving the backslashes, which then will be removed by - * nm_ip_routing_rule_from_string(). - */ - - addr_family = _rr_string_addr_family_from_flags(to_string_flags); - - tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); - for (i_token = 0; tokens && tokens[i_token]; i_token++) { - char *str_word = (char *) tokens[i_token]; - - any_words = TRUE; - if (!word0) - word0 = str_word; - else { - nm_assert(!word1); - word1 = str_word; - } - - /* iproute2 matches keywords with any partial prefix. We don't allow - * for that flexibility. */ - - if (NM_IN_STRSET(word0, "from")) { - if (!word1) - continue; - if (word_from) - goto next_fail_word0_duplicate_key; - word_from = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "to")) { - if (!word1) - continue; - if (word_to) - goto next_fail_word0_duplicate_key; - word_to = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "not")) { - /* we accept multiple "not" specifiers. "not not" still means - * not. */ - val_invert = TRUE; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "priority", "order", "pref", "preference")) { - if (!word1) - continue; - if (i64_priority != -1) - goto next_fail_word0_duplicate_key; - i64_priority = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); - if (i64_priority == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "table", "lookup")) { - if (!word1) - continue; - if (i64_table != -1) - goto next_fail_word0_duplicate_key; - i64_table = _nm_utils_ascii_str_to_int64(word1, 0, 1, G_MAXUINT32, -1); - if (i64_table == -1) { - if (nm_streq(word1, "main")) - i64_table = RT_TABLE_MAIN; - else if (nm_streq(word1, "local")) - i64_table = RT_TABLE_LOCAL; - else if (nm_streq(word1, "default")) - i64_table = RT_TABLE_DEFAULT; - else - goto next_fail_word1_invalid_value; - } - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "tos", "dsfield")) { - if (!word1) - continue; - if (i64_tos != -1) - goto next_fail_word0_duplicate_key; - i64_tos = _nm_utils_ascii_str_to_int64(word1, 16, 0, G_MAXUINT8, -1); - if (i64_tos == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "ipproto")) { - if (!word1) - continue; - if (i64_ipproto != -1) - goto next_fail_word0_duplicate_key; - i64_ipproto = _nm_utils_ascii_str_to_int64(word1, 10, 0, G_MAXUINT8, -1); - if (i64_ipproto == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "sport")) { - if (!word1) - continue; - if (i64_sport_start != -1) - goto next_fail_word0_duplicate_key; - if (!_rr_xport_range_parse(word1, &i64_sport_start, &sport_end)) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "dport")) { - if (!word1) - continue; - if (i64_dport_start != -1) - goto next_fail_word0_duplicate_key; - if (!_rr_xport_range_parse(word1, &i64_dport_start, &dport_end)) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "fwmark")) { - if (!word1) - continue; - if (i64_fwmark != -1) - goto next_fail_word0_duplicate_key; - s = strchr(word1, '/'); - if (s) - *(s++) = '\0'; - i64_fwmark = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXUINT32, -1); - if (i64_fwmark == -1) - goto next_fail_word1_invalid_value; - if (s) { - i64_fwmask = _nm_utils_ascii_str_to_int64(s, 0, 0, G_MAXUINT32, -1); - if (i64_fwmask == -1) - goto next_fail_word1_invalid_value; - } else - i64_fwmask = 0xFFFFFFFFu; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "iif", "dev")) { - if (!word1) - continue; - if (word_iifname) - goto next_fail_word0_duplicate_key; - word_iifname = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "oif")) { - if (!word1) - continue; - if (word_oifname) - goto next_fail_word0_duplicate_key; - word_oifname = word1; - goto next_words_consumed; - } - if (NM_IN_STRSET(word0, "suppress_prefixlength", "sup_pl")) { - if (!word1) - continue; - if (i64_suppress_prefixlength != -1) - goto next_fail_word0_duplicate_key; - i64_suppress_prefixlength = _nm_utils_ascii_str_to_int64(word1, 0, 0, G_MAXINT32, -1); - if (i64_suppress_prefixlength == -1) - goto next_fail_word1_invalid_value; - goto next_words_consumed; - } - - /* also the action is still unsupported. For the moment, we only support - * FR_ACT_TO_TBL, which is the default (by not expressing it on the command - * line). */ - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("unsupported key \"%s\""), - word0); - return FALSE; -next_fail_word0_duplicate_key: - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("duplicate key \"%s\""), - word0); - return FALSE; -next_fail_word1_invalid_value: - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid value for \"%s\""), - word0); - return FALSE; -next_words_consumed: - word0 = NULL; - word1 = NULL; - } - - if (!any_words) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("empty text does not describe a rule")); - return FALSE; - } - - if (word0) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("missing argument for \"%s\""), - word0); - return FALSE; - } - - if (!NM_IN_STRSET(word_from, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_from, - &addr_family, - &val_from, - &val_from_len)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid \"from\" part")); - return FALSE; - } - if (val_from_len == -1) - val_from_len = nm_utils_addr_family_to_size(addr_family) * 8; - } - - if (!NM_IN_STRSET(word_to, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_to, - &addr_family, - &val_to, - &val_to_len)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid \"to\" part")); - return FALSE; - } - if (val_to_len == -1) - val_to_len = nm_utils_addr_family_to_size(addr_family) * 8; - } - - if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("cannot detect address family for rule")); - return FALSE; - } - - self = nm_ip_routing_rule_new(addr_family); - - if (val_invert) - self->invert = TRUE; - - if (i64_priority != -1) - nm_ip_routing_rule_set_priority(self, i64_priority); - - if (i64_tos != -1) - nm_ip_routing_rule_set_tos(self, i64_tos); - - if (i64_ipproto != -1) - nm_ip_routing_rule_set_ipproto(self, i64_ipproto); - - if (i64_fwmark != -1) - nm_ip_routing_rule_set_fwmark(self, i64_fwmark, i64_fwmask); - - if (i64_sport_start != -1) - nm_ip_routing_rule_set_source_port(self, i64_sport_start, sport_end); - - if (i64_dport_start != -1) - nm_ip_routing_rule_set_destination_port(self, i64_dport_start, dport_end); - - if (i64_suppress_prefixlength != -1) - nm_ip_routing_rule_set_suppress_prefixlength(self, i64_suppress_prefixlength); - - if (val_from_len > 0 || (val_from_len == 0 && !nm_ip_addr_is_null(addr_family, &val_from))) { - nm_ip_routing_rule_set_from_bin(self, &val_from, val_from_len); - } - - if (val_to_len > 0 || (val_to_len == 0 && !nm_ip_addr_is_null(addr_family, &val_to))) { - nm_ip_routing_rule_set_to_bin(self, &val_to, val_to_len); - } - - if (word_iifname) - nm_ip_routing_rule_set_iifname(self, word_iifname); - - if (word_oifname) - nm_ip_routing_rule_set_oifname(self, word_oifname); - - if (i64_table != -1) - nm_ip_routing_rule_set_table(self, i64_table); - - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { - gs_free_error GError *local = NULL; - - if (!nm_ip_routing_rule_validate(self, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("rule is invalid: %s"), - local->message); - return NULL; - } - } - - return g_steal_pointer(&self); -} - -static void -_rr_string_append_inet_addr(NMStrBuf * str, - gboolean is_from /* or else is-to */, - gboolean required, - int addr_family, - const NMIPAddr *addr_bin, - guint8 addr_len) -{ - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - - if (addr_len == 0) { - if (required) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), - "%s %s/0", - is_from ? "from" : "to", - (addr_family == AF_INET) ? "0.0.0.0" : "::"); - } - return; - } - - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), - "%s %s", - is_from ? "from" : "to", - nm_utils_inet_ntop(addr_family, addr_bin, addr_str)); - if (addr_len != nm_utils_addr_family_to_size(addr_family) * 8) { - nm_str_buf_append_printf(str, "/%u", addr_len); - } -} - -/** - * nm_ip_routing_rule_to_string: - * @self: the #NMIPRoutingRule instance to convert to string. - * @to_string_flags: #NMIPRoutingRuleAsStringFlags for controlling the - * string conversion. - * @extra_args: (allow-none): extra arguments for controlling the string - * conversion. Currently, not extra arguments are supported. - * @error: (allow-none) (out): the error reason. - * - * Returns: (transfer full): the string representation or %NULL on error. - * - * Since: 1.18 - */ -char * -nm_ip_routing_rule_to_string(const NMIPRoutingRule * self, - NMIPRoutingRuleAsStringFlags to_string_flags, - GHashTable * extra_args, - GError ** error) -{ - int addr_family; - NMStrBuf str; - - g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - - if (!_rr_string_validate(FALSE, to_string_flags, extra_args, error)) - return NULL; - - addr_family = nm_ip_routing_rule_get_addr_family(self); - - if (!NM_IN_SET(_rr_string_addr_family_from_flags(to_string_flags), AF_UNSPEC, addr_family)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("invalid address family")); - return NULL; - } - - /* It is only guaranteed that valid rules can be expressed as string. - * - * Still, unless requested proceed to convert to string without validating and - * hope for the best. - * - * That is, because self->from_str might contain an invalid IP address (indicated - * by self->from_valid). But we don't support serializing such arbitrary strings - * as "from %s". */ - if (NM_FLAGS_HAS(to_string_flags, NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE)) { - gs_free_error GError *local = NULL; - - if (!nm_ip_routing_rule_validate(self, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_FAILED, - _("rule is invalid: %s"), - local->message); - return NULL; - } - } - - nm_str_buf_init(&str, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); - - if (self->priority_has) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "priority %u", - (guint) self->priority); - } - - if (self->invert) - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "not"); - - _rr_string_append_inet_addr(&str, - TRUE, - (!self->to_has || !self->to_valid), - addr_family, - &self->from_bin, - (self->from_has && self->from_valid) ? self->from_len : 0); - - _rr_string_append_inet_addr(&str, - FALSE, - FALSE, - addr_family, - &self->to_bin, - (self->to_has && self->to_valid) ? self->to_len : 0); - - if (self->tos != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "tos 0x%02x", - (guint) self->tos); - } - - if (self->ipproto != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "ipproto %u", - (guint) self->ipproto); - } - - if (self->fwmark != 0 || self->fwmask != 0) { - if (self->fwmark != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "fwmark 0x%x", - self->fwmark); - } else { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), "fwmark 0"); - } - if (self->fwmask != 0xFFFFFFFFu) { - if (self->fwmask != 0) - nm_str_buf_append_printf(&str, "/0x%x", self->fwmask); - else - nm_str_buf_append_printf(&str, "/0"); - } - } - - if (self->sport_start != 0 || self->sport_end != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "sport %u", - self->sport_start); - if (self->sport_start != self->sport_end) { - nm_str_buf_append_printf(&str, "-%u", self->sport_end); - } - } - - if (self->dport_start != 0 || self->dport_end != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "dport %u", - self->dport_start); - if (self->dport_start != self->dport_end) { - nm_str_buf_append_printf(&str, "-%u", self->dport_end); - } - } - - if (self->iifname) { - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "iif "); - nm_utils_escaped_tokens_escape_strbuf(self->iifname, NM_ASCII_SPACES, &str); - } - - if (self->oifname) { - nm_str_buf_append(nm_str_buf_append_required_delimiter(&str, ' '), "oif "); - nm_utils_escaped_tokens_escape_strbuf(self->oifname, NM_ASCII_SPACES, &str); - } - - if (self->table != 0) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "table %u", - (guint) self->table); - } - - if (self->suppress_prefixlength != -1) { - nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), - "suppress_prefixlength %d", - (int) self->suppress_prefixlength); - } - - return nm_str_buf_finalize(&str, NULL); -} - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig, - PROP_METHOD, - PROP_DNS, - PROP_DNS_SEARCH, - PROP_DNS_OPTIONS, - PROP_DNS_PRIORITY, - PROP_ADDRESSES, - PROP_GATEWAY, - PROP_ROUTES, - PROP_ROUTE_METRIC, - PROP_ROUTE_TABLE, - PROP_IGNORE_AUTO_ROUTES, - PROP_IGNORE_AUTO_DNS, - PROP_DHCP_HOSTNAME, - PROP_DHCP_HOSTNAME_FLAGS, - PROP_DHCP_SEND_HOSTNAME, - PROP_NEVER_DEFAULT, - PROP_MAY_FAIL, - PROP_DAD_TIMEOUT, - PROP_DHCP_TIMEOUT, - PROP_DHCP_IAID, - PROP_DHCP_REJECT_SERVERS, ); - -typedef struct { - GPtrArray *dns; /* array of IP address strings */ - GPtrArray *dns_search; /* array of domain name strings */ - GPtrArray *dns_options; /* array of DNS options */ - GPtrArray *addresses; /* array of NMIPAddress */ - GPtrArray *routes; /* array of NMIPRoute */ - GPtrArray *routing_rules; - GArray * dhcp_reject_servers; - char * method; - char * gateway; - char * dhcp_hostname; - char * dhcp_iaid; - gint64 route_metric; - guint dhcp_hostname_flags; - int dns_priority; - int dad_timeout; - int dhcp_timeout; - guint32 route_table; - bool ignore_auto_routes : 1; - bool ignore_auto_dns : 1; - bool dhcp_send_hostname : 1; - bool never_default : 1; - bool may_fail : 1; -} NMSettingIPConfigPrivate; - -G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) - -#define NM_SETTING_IP_CONFIG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigPrivate)) - -/*****************************************************************************/ - -#define NM_SETTING_IP_CONFIG_GET_FAMILY(setting) \ - (NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6) - -/** - * nm_setting_ip_config_get_method: - * @setting: the #NMSettingIPConfig - * - * Returns: the #NMSettingIPConfig:method property of the setting; see - * #NMSettingIP4Config and #NMSettingIP6Config for details of the - * methods available with each type. - **/ -const char * -nm_setting_ip_config_get_method(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->method; -} - -/** - * nm_setting_ip_config_get_num_dns: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS servers - **/ -guint -nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns->len; -} - -/** - * nm_setting_ip_config_get_dns: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS server to return - * - * Returns: the IP address of the DNS server at index @idx - **/ -const char * -nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns->len, NULL); - - return priv->dns->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_dns: - * @setting: the #NMSettingIPConfig - * @dns: the IP address of the DNS server to add - * - * Adds a new DNS server to the setting. - * - * Returns: %TRUE if the DNS server was added; %FALSE if the server was already - * known - **/ -gboolean -nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) -{ - NMSettingIPConfigPrivate *priv; - char * dns_canonical; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), - FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); - for (i = 0; i < priv->dns->len; i++) { - if (!strcmp(dns_canonical, priv->dns->pdata[i])) { - g_free(dns_canonical); - return FALSE; - } - } - - g_ptr_array_add(priv->dns, dns_canonical); - _notify(setting, PROP_DNS); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS server to remove - * - * Removes the DNS server at index @idx. - **/ -void -nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns->len); - - g_ptr_array_remove_index(priv->dns, idx); - _notify(setting, PROP_DNS); -} - -/** - * nm_setting_ip_config_remove_dns_by_value: - * @setting: the #NMSettingIPConfig - * @dns: the DNS server to remove - * - * Removes the DNS server @dns. - * - * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns) -{ - NMSettingIPConfigPrivate *priv; - char * dns_canonical; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns), - FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - dns_canonical = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns, FALSE); - for (i = 0; i < priv->dns->len; i++) { - if (!strcmp(dns_canonical, priv->dns->pdata[i])) { - g_ptr_array_remove_index(priv->dns, i); - _notify(setting, PROP_DNS); - g_free(dns_canonical); - return TRUE; - } - } - g_free(dns_canonical); - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DNS servers. - **/ -void -nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (priv->dns->len != 0) { - g_ptr_array_set_size(priv->dns, 0); - _notify(setting, PROP_DNS); - } -} - -/** - * nm_setting_ip_config_get_num_dns_searches: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS search domains - **/ -guint -nm_setting_ip_config_get_num_dns_searches(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_search->len; -} - -/** - * nm_setting_ip_config_get_dns_search: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS search domain to return - * - * Returns: the DNS search domain at index @idx - **/ -const char * -nm_setting_ip_config_get_dns_search(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns_search->len, NULL); - - return priv->dns_search->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_dns_search: - * @setting: the #NMSettingIPConfig - * @dns_search: the search domain to add - * - * Adds a new DNS search domain to the setting. - * - * Returns: %TRUE if the DNS search domain was added; %FALSE if the search - * domain was already known - **/ -gboolean -nm_setting_ip_config_add_dns_search(NMSettingIPConfig *setting, const char *dns_search) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_search != NULL, FALSE); - g_return_val_if_fail(dns_search[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->dns_search->len; i++) { - if (!strcmp(dns_search, priv->dns_search->pdata[i])) - return FALSE; - } - - g_ptr_array_add(priv->dns_search, g_strdup(dns_search)); - _notify(setting, PROP_DNS_SEARCH); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns_search: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS search domain - * - * Removes the DNS search domain at index @idx. - **/ -void -nm_setting_ip_config_remove_dns_search(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns_search->len); - - g_ptr_array_remove_index(priv->dns_search, idx); - _notify(setting, PROP_DNS_SEARCH); -} - -/** - * nm_setting_ip_config_remove_dns_search_by_value: - * @setting: the #NMSettingIPConfig - * @dns_search: the search domain to remove - * - * Removes the DNS search domain @dns_search. - * - * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_dns_search_by_value(NMSettingIPConfig *setting, const char *dns_search) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_search != NULL, FALSE); - g_return_val_if_fail(dns_search[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->dns_search->len; i++) { - if (!strcmp(dns_search, priv->dns_search->pdata[i])) { - g_ptr_array_remove_index(priv->dns_search, i); - _notify(setting, PROP_DNS_SEARCH); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns_searches: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DNS search domains. - **/ -void -nm_setting_ip_config_clear_dns_searches(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (priv->dns_search->len != 0) { - g_ptr_array_set_size(priv->dns_search, 0); - _notify(setting, PROP_DNS_SEARCH); - } -} - -/** - * nm_setting_ip_config_get_num_dns_options: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured DNS options - * - * Since: 1.2 - **/ -guint -nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - return priv->dns_options ? priv->dns_options->len : 0; -} - -/** - * nm_setting_ip_config_has_dns_options: - * @setting: the #NMSettingIPConfig - * - * NMSettingIPConfig can have a list of dns-options. If the list - * is empty, there are two similar (but differentiated) states. - * Either the options are explicitly set to have no values, - * or the options are left undefined. The latter means to use - * a default configuration, while the former explicitly means "no-options". - * - * Returns: whether DNS options are initialized or left unset (the default). - **/ -gboolean -nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return !!NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_options; -} - -/** - * nm_setting_ip_config_get_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS option - * - * Returns: the DNS option at index @idx - * - * Since: 1.2 - **/ -const char * -nm_setting_ip_config_get_dns_option(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(priv->dns_options, NULL); - g_return_val_if_fail(idx < priv->dns_options->len, NULL); - - return priv->dns_options->pdata[idx]; -} - -/** - * nm_setting_ip_config_next_valid_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index to start the search from - * - * Returns: the index, greater or equal than @idx, of the first valid - * DNS option, or -1 if no valid option is found - **/ -int -nm_setting_ip_config_next_valid_dns_option(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (!priv->dns_options) - return -1; - - for (; idx < priv->dns_options->len; idx++) { - if (_nm_utils_dns_option_validate(priv->dns_options->pdata[idx], - NULL, - NULL, - NM_IS_SETTING_IP6_CONFIG(setting), - _nm_utils_dns_option_descs)) - return idx; - } - - return -1; -} - -/** - * nm_setting_ip_config_add_dns_option: - * @setting: the #NMSettingIPConfig - * @dns_option: the DNS option to add - * - * Adds a new DNS option to the setting. - * - * Returns: %TRUE if the DNS option was added; %FALSE otherwise - * - * Since: 1.2 - **/ -gboolean -nm_setting_ip_config_add_dns_option(NMSettingIPConfig *setting, const char *dns_option) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_option != NULL, FALSE); - g_return_val_if_fail(dns_option[0] != '\0', FALSE); - - if (!_nm_utils_dns_option_validate(dns_option, NULL, NULL, FALSE, NULL)) - return FALSE; - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - else { - if (_nm_utils_dns_option_find_idx(priv->dns_options, dns_option) >= 0) - return FALSE; - } - - g_ptr_array_add(priv->dns_options, g_strdup(dns_option)); - _notify(setting, PROP_DNS_OPTIONS); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_dns_option: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DNS option - * - * Removes the DNS option at index @idx. - * - * Since: 1.2 - **/ -void -nm_setting_ip_config_remove_dns_option(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->dns_options); - g_return_if_fail(idx >= 0 && idx < priv->dns_options->len); - - g_ptr_array_remove_index(priv->dns_options, idx); - _notify(setting, PROP_DNS_OPTIONS); -} - -/** - * nm_setting_ip_config_remove_dns_option_by_value: - * @setting: the #NMSettingIPConfig - * @dns_option: the DNS option to remove - * - * Removes the DNS option @dns_option. - * - * Returns: %TRUE if the DNS option was found and removed; %FALSE if it was not. - * - * Since: 1.2 - **/ -gboolean -nm_setting_ip_config_remove_dns_option_by_value(NMSettingIPConfig *setting, const char *dns_option) -{ - NMSettingIPConfigPrivate *priv; - gssize i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(dns_option != NULL, FALSE); - g_return_val_if_fail(dns_option[0] != '\0', FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) - return FALSE; - - i = _nm_utils_dns_option_find_idx(priv->dns_options, dns_option); - if (i >= 0) { - g_ptr_array_remove_index(priv->dns_options, i); - _notify(setting, PROP_DNS_OPTIONS); - return TRUE; - } - - return FALSE; -} - -/** - * nm_setting_ip_config_clear_dns_options: - * @setting: the #NMSettingIPConfig - * @is_set: the dns-options can be either empty or unset (default). - * Specify how to clear the options. - * - * Removes all configured DNS options. - * - * Since: 1.2 - **/ -void -nm_setting_ip_config_clear_dns_options(NMSettingIPConfig *setting, gboolean is_set) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (!priv->dns_options) { - if (!is_set) - return; - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - } else { - if (!is_set) { - g_ptr_array_unref(priv->dns_options); - priv->dns_options = NULL; - } else { - if (priv->dns_options->len == 0) - return; - g_ptr_array_set_size(priv->dns_options, 0); - } - } - _notify(setting, PROP_DNS_OPTIONS); -} - -/** - * nm_setting_ip_config_get_dns_priority: - * @setting: the #NMSettingIPConfig - * - * Returns: the priority of DNS servers - * - * Since: 1.4 - **/ -int -nm_setting_ip_config_get_dns_priority(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns_priority; -} - -/** - * nm_setting_ip_config_get_num_addresses: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured addresses - **/ -guint -nm_setting_ip_config_get_num_addresses(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->addresses->len; -} - -/** - * nm_setting_ip_config_get_address: - * @setting: the #NMSettingIPConfig - * @idx: index number of the address to return - * - * Returns: (transfer none): the address at index @idx - **/ -NMIPAddress * -nm_setting_ip_config_get_address(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->addresses->len, NULL); - - return priv->addresses->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_address: - * @setting: the #NMSettingIPConfig - * @address: the new address to add - * - * Adds a new IP address and associated information to the setting. The - * given address is duplicated internally and is not changed by this function. - * - * Returns: %TRUE if the address was added; %FALSE if the address was already - * known. - **/ -gboolean -nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *address) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(address != NULL, FALSE); - g_return_val_if_fail(address->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->addresses->len; i++) { - if (nm_ip_address_equal(priv->addresses->pdata[i], address)) - return FALSE; - } - - g_ptr_array_add(priv->addresses, nm_ip_address_dup(address)); - - _notify(setting, PROP_ADDRESSES); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_address: - * @setting: the #NMSettingIPConfig - * @idx: index number of the address to remove - * - * Removes the address at index @idx. - **/ -void -nm_setting_ip_config_remove_address(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->addresses->len); - - g_ptr_array_remove_index(priv->addresses, idx); - - _notify(setting, PROP_ADDRESSES); -} - -/** - * nm_setting_ip_config_remove_address_by_value: - * @setting: the #NMSettingIPConfig - * @address: the IP address to remove - * - * Removes the address @address. - * - * Returns: %TRUE if the address was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_address_by_value(NMSettingIPConfig *setting, NMIPAddress *address) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(address != NULL, FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->addresses->len; i++) { - if (nm_ip_address_equal(priv->addresses->pdata[i], address)) { - g_ptr_array_remove_index(priv->addresses, i); - _notify(setting, PROP_ADDRESSES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_addresses: - * @setting: the #NMSettingIPConfig - * - * Removes all configured addresses. - **/ -void -nm_setting_ip_config_clear_addresses(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->addresses->len != 0) { - g_ptr_array_set_size(priv->addresses, 0); - _notify(setting, PROP_ADDRESSES); - } -} - -/** - * nm_setting_ip_config_get_gateway: - * @setting: the #NMSettingIPConfig - * - * Returns: the IP address of the gateway associated with this configuration, or - * %NULL. - **/ -const char * -nm_setting_ip_config_get_gateway(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->gateway; -} - -/** - * nm_setting_ip_config_get_num_routes: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured routes - **/ -guint -nm_setting_ip_config_get_num_routes(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->routes->len; -} - -/** - * nm_setting_ip_config_get_route: - * @setting: the #NMSettingIPConfig - * @idx: index number of the route to return - * - * Returns: (transfer none): the route at index @idx - **/ -NMIPRoute * -nm_setting_ip_config_get_route(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->routes->len, NULL); - - return priv->routes->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_route: - * @setting: the #NMSettingIPConfig - * @route: the route to add - * - * Appends a new route and associated information to the setting. The - * given route is duplicated internally and is not changed by this function. - * If an identical route (considering attributes as well) already exists, the - * route is not added and the function returns %FALSE. - * - * Note that before 1.10, this function would not consider route attributes - * and not add a route that has an existing route with same dest/prefix,next_hop,metric - * parameters. - * - * Returns: %TRUE if the route was added; %FALSE if the route was already known. - **/ -gboolean -nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(route->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal_full(priv->routes->pdata[i], - route, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) - return FALSE; - } - - g_ptr_array_add(priv->routes, nm_ip_route_dup(route)); - _notify(setting, PROP_ROUTES); - return TRUE; -} - -/** - * nm_setting_ip_config_remove_route: - * @setting: the #NMSettingIPConfig - * @idx: index number of the route - * - * Removes the route at index @idx. - **/ -void -nm_setting_ip_config_remove_route(NMSettingIPConfig *setting, int idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->routes->len); - - g_ptr_array_remove_index(priv->routes, idx); - _notify(setting, PROP_ROUTES); -} - -/** - * nm_setting_ip_config_remove_route_by_value: - * @setting: the #NMSettingIPConfig - * @route: the route to remove - * - * Removes the first matching route that matches @route. - * Note that before 1.10, this function would only compare dest/prefix,next_hop,metric - * and ignore route attributes. Now, @route must match exactly. - * - * Returns: %TRUE if the route was found and removed; %FALSE if it was not. - **/ -gboolean -nm_setting_ip_config_remove_route_by_value(NMSettingIPConfig *setting, NMIPRoute *route) -{ - NMSettingIPConfigPrivate *priv; - guint i; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - g_return_val_if_fail(route != NULL, FALSE); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal_full(priv->routes->pdata[i], - route, - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { - g_ptr_array_remove_index(priv->routes, i); - _notify(setting, PROP_ROUTES); - return TRUE; - } - } - return FALSE; -} - -/** - * nm_setting_ip_config_clear_routes: - * @setting: the #NMSettingIPConfig - * - * Removes all configured routes. - **/ -void -nm_setting_ip_config_clear_routes(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->routes->len != 0) { - g_ptr_array_set_size(priv->routes, 0); - _notify(setting, PROP_ROUTES); - } -} - -/** - * nm_setting_ip_config_get_route_metric: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:route-metric - * property. - * - * Returns: the route metric that is used for routes that don't explicitly - * specify a metric. See #NMSettingIPConfig:route-metric for more details. - **/ -gint64 -nm_setting_ip_config_get_route_metric(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_metric; -} - -/** - * nm_setting_ip_config_get_route_table: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:route-table - * property. - * - * Returns: the configured route-table. - * - * Since: 1.10 - **/ -guint32 -nm_setting_ip_config_get_route_table(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->route_table; -} - -/*****************************************************************************/ - -static void -_routing_rules_notify(NMSettingIPConfig *setting) -{ - _nm_setting_emit_property_changed(NM_SETTING(setting)); -} - -/** - * nm_setting_ip_config_get_num_routing_rules: - * @setting: the #NMSettingIPConfig - * - * Returns: the number of configured routing rules - * - * Since: 1.18 - **/ -guint -nm_setting_ip_config_get_num_routing_rules(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - return priv->routing_rules ? priv->routing_rules->len : 0u; -} - -/** - * nm_setting_ip_config_get_routing_rule: - * @setting: the #NMSettingIPConfig - * @idx: index number of the routing_rule to return - * - * Returns: (transfer none): the routing rule at index @idx - * - * Since: 1.18 - **/ -NMIPRoutingRule * -nm_setting_ip_config_get_routing_rule(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_val_if_fail(priv->routing_rules && idx < priv->routing_rules->len, NULL); - - return priv->routing_rules->pdata[idx]; -} - -/** - * nm_setting_ip_config_add_routing_rule: - * @setting: the #NMSettingIPConfig - * @routing_rule: the #NMIPRoutingRule to add. The address family - * of the added rule must be compatible with the setting. - * - * Appends a new routing-rule and associated information to the setting. The - * given routing rules gets sealed and the reference count is incremented. - * The function does not check whether an identical rule already exists - * and always appends the rule to the end of the list. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, NMIPRoutingRule *routing_rule) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - g_return_if_fail(NM_IS_IP_ROUTING_RULE(routing_rule, TRUE)); - g_return_if_fail(_ip_routing_rule_get_addr_family(routing_rule) - == NM_SETTING_IP_CONFIG_GET_FAMILY(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - if (!priv->routing_rules) - priv->routing_rules = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - - nm_ip_routing_rule_seal(routing_rule); - g_ptr_array_add(priv->routing_rules, nm_ip_routing_rule_ref(routing_rule)); - _routing_rules_notify(setting); -} - -/** - * nm_setting_ip_config_remove_routing_rule: - * @setting: the #NMSettingIPConfig - * @idx: index number of the routing_rule - * - * Removes the routing_rule at index @idx. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_remove_routing_rule(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->routing_rules && idx < priv->routing_rules->len); - - g_ptr_array_remove_index(priv->routing_rules, idx); - _routing_rules_notify(setting); -} - -/** - * nm_setting_ip_config_clear_routing_rules: - * @setting: the #NMSettingIPConfig - * - * Removes all configured routing rules. - * - * Since: 1.18 - **/ -void -nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - if (priv->routing_rules && priv->routing_rules->len > 0) { - g_ptr_array_set_size(priv->routing_rules, 0); - _routing_rules_notify(setting); - } -} - -static GVariant * -_routing_rules_dbus_only_synth(const NMSettInfoSetting * sett_info, - guint property_idx, - NMConnection * connection, - NMSetting * setting, - NMConnectionSerializationFlags flags, - const NMConnectionSerializationOptions *options) -{ - NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(setting); - NMSettingIPConfigPrivate *priv; - GVariantBuilder builder; - gboolean any = FALSE; - guint i; - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - - if (!priv->routing_rules || priv->routing_rules->len == 0) - return NULL; - - for (i = 0; i < priv->routing_rules->len; i++) { - GVariant *variant; - - variant = nm_ip_routing_rule_to_dbus(priv->routing_rules->pdata[i]); - if (!variant) - continue; - - if (!any) { - any = TRUE; - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - } - g_variant_builder_add(&builder, "@a{sv}", variant); - } - - return any ? g_variant_builder_end(&builder) : NULL; -} - -static gboolean -_routing_rules_dbus_only_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - GVariantIter iter_rules; - GVariant * rule_var; - guint i_rule; - gboolean success = FALSE; - gboolean rules_changed = FALSE; - - nm_assert(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}"))); - - g_variant_iter_init(&iter_rules, value); - - i_rule = 0; - while (g_variant_iter_next(&iter_rules, "@a{sv}", &rule_var)) { - _nm_unused gs_unref_variant GVariant *rule_var_unref = rule_var; - nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL; - gs_free_error GError *local = NULL; - - i_rule++; - - rule = - nm_ip_routing_rule_from_dbus(rule_var, - NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), - &local); - if (!rule) { - if (NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("rule #%u is invalid: %s"), - i_rule, - local->message); - goto out; - } - continue; - } - - nm_setting_ip_config_add_routing_rule(NM_SETTING_IP_CONFIG(setting), rule); - rules_changed = TRUE; - } - - success = TRUE; - -out: - if (rules_changed) - _routing_rules_notify(NM_SETTING_IP_CONFIG(setting)); - return success; -} - -/*****************************************************************************/ - -/** - * nm_setting_ip_config_get_ignore_auto_routes: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:ignore-auto-routes - * property. - * - * Returns: %TRUE if automatically configured (ie via DHCP) routes should be - * ignored. - **/ -gboolean -nm_setting_ip_config_get_ignore_auto_routes(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_routes; -} - -/** - * nm_setting_ip_config_get_ignore_auto_dns: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:ignore-auto-dns - * property. - * - * Returns: %TRUE if automatically configured (ie via DHCP) DNS information - * should be ignored. - **/ -gboolean -nm_setting_ip_config_get_ignore_auto_dns(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->ignore_auto_dns; -} - -/** - * nm_setting_ip_config_get_dhcp_hostname: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname - * property. - * - * Returns: the configured hostname to send to the DHCP server - **/ -const char * -nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname; -} - -/** - * nm_setting_ip_config_get_dhcp_send_hostname: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-send-hostname - * property. - * - * Returns: %TRUE if NetworkManager should send the machine hostname to the - * DHCP server when requesting addresses to allow the server to automatically - * update DNS information for this machine. - **/ -gboolean -nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_send_hostname; -} - -/** - * nm_setting_ip_config_get_never_default: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:never-default - * property. - * - * Returns: %TRUE if this connection should never be the default - * connection - **/ -gboolean -nm_setting_ip_config_get_never_default(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->never_default; -} - -/** - * nm_setting_ip_config_get_may_fail: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:may-fail - * property. - * - * Returns: %TRUE if this connection doesn't require this type of IP - * addressing to complete for the connection to succeed. - **/ -gboolean -nm_setting_ip_config_get_may_fail(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->may_fail; -} - -/** - * nm_setting_ip_config_get_dad_timeout: - * @setting: the #NMSettingIPConfig - * - * Returns: the #NMSettingIPConfig:dad-timeout property. - * - * Since: 1.2 - **/ -int -nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dad_timeout; -} - -/** - * nm_setting_ip_config_get_dhcp_hostname_flags: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname-flags - * property. - * - * Returns: flags for the DHCP hostname and FQDN - * - * Since: 1.22 - */ -NMDhcpHostnameFlags -nm_setting_ip_config_get_dhcp_hostname_flags(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NM_DHCP_HOSTNAME_FLAG_NONE); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_hostname_flags; -} - -/** - * nm_setting_ip_config_get_dhcp_timeout: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-timeout - * property. - * - * Returns: the configured DHCP timeout in seconds. 0 = default for - * the particular kind of device. - * - * Since: 1.2 - **/ -int -nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_timeout; -} - -/** - * nm_setting_ip_config_get_dhcp_iaid: - * @setting: the #NMSettingIPConfig - * - * Returns the value contained in the #NMSettingIPConfig:dhcp-iaid - * property. - * - * Returns: the configured DHCP IAID (Identity Association Identifier) - * - * Since: 1.22 - **/ -const char * -nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_iaid; -} - -/** - * nm_setting_ip_config_get_dhcp_reject_servers: - * @setting: the #NMSettingIPConfig - * @out_len: (allow-none) (out): the number of returned elements - * - * Returns: (array length=out_len zero-terminated=1) (transfer none): - * A %NULL terminated array of DHCP reject servers. Even if no reject - * servers are configured, this always returns a non %NULL value. - * - * Since: 1.28 - */ -const char *const * -nm_setting_ip_config_get_dhcp_reject_servers(NMSettingIPConfig *setting, guint *out_len) -{ - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); - return nm_strvarray_get_strv(&NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_reject_servers, - out_len); -} - -/** - * nm_setting_ip_config_add_dhcp_reject_server: - * @setting: the #NMSettingIPConfig - * @server: the DHCP reject server to add - * - * Adds a new DHCP reject server to the setting. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_add_dhcp_reject_server(NMSettingIPConfig *setting, const char *server) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - g_return_if_fail(server != NULL); - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - nm_strvarray_add(nm_strvarray_ensure(&priv->dhcp_reject_servers), server); - _notify(setting, PROP_DHCP_REJECT_SERVERS); -} - -/** - * nm_setting_ip_config_remove_dhcp_reject_server: - * @setting: the #NMSettingIPConfig - * @idx: index number of the DHCP reject server - * - * Removes the DHCP reject server at index @idx. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_remove_dhcp_reject_server(NMSettingIPConfig *setting, guint idx) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(priv->dhcp_reject_servers && idx < priv->dhcp_reject_servers->len); - - g_array_remove_index(priv->dhcp_reject_servers, idx); - _notify(setting, PROP_DHCP_REJECT_SERVERS); -} - -/** - * nm_setting_ip_config_clear_dhcp_reject_servers: - * @setting: the #NMSettingIPConfig - * - * Removes all configured DHCP reject servers. - * - * Since: 1.28 - **/ -void -nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv; - - g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (nm_g_array_len(priv->dhcp_reject_servers) != 0) { - nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); - _notify(setting, PROP_DHCP_REJECT_SERVERS); - } -} - -static gboolean -verify_label(const char *label) -{ - const char *p; - char * iface; - - p = strchr(label, ':'); - if (!p) - return FALSE; - iface = g_strndup(label, p - label); - if (!nm_utils_ifname_valid_kernel(iface, NULL)) { - g_free(iface); - return FALSE; - } - g_free(iface); - - for (p++; *p; p++) { - if (!g_ascii_isalnum(*p) && *p != '_') - return FALSE; - } - - return TRUE; -} - -static gboolean -verify(NMSetting *setting, NMConnection *connection, GError **error) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - guint i; - - if (!priv->method) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), NM_SETTING_IP_CONFIG_METHOD); - return FALSE; - } - - if (priv->dhcp_hostname && !*priv->dhcp_hostname) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("property is empty")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME); - return FALSE; - } - - /* Validate DNS */ - for (i = 0; i < priv->dns->len; i++) { - const char *dns = priv->dns->pdata[i]; - - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. DNS server address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DNS); - return FALSE; - } - } - - /* Validate addresses */ - for (i = 0; i < priv->addresses->len; i++) { - NMIPAddress *addr = (NMIPAddress *) priv->addresses->pdata[i]; - GVariant * label; - - if (nm_ip_address_get_family(addr) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - - label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - if (label) { - if (!g_variant_is_of_type(label, G_VARIANT_TYPE_STRING)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address has 'label' property with invalid type"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - if (!verify_label(g_variant_get_string(label, NULL))) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. IP address has invalid label '%s'"), - (int) (i + 1), - g_variant_get_string(label, NULL)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ADDRESSES); - return FALSE; - } - } - } - - /* Validate gateway */ - if (priv->gateway) { - if (!priv->addresses->len) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("gateway cannot be set if there are no addresses configured")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return FALSE; - } - - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), priv->gateway)) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("gateway is invalid")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return FALSE; - } - } - - /* Validate routes */ - for (i = 0; i < priv->routes->len; i++) { - gs_free_error GError *local = NULL; - NMIPRoute * route = (NMIPRoute *) priv->routes->pdata[i]; - - if (nm_ip_route_get_family(route) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. route is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - - if (!_nm_ip_route_attribute_validate_all(route, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid attribute: %s"), - local->message); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - } - - if (priv->routing_rules) { - for (i = 0; i < priv->routing_rules->len; i++) { - NMIPRoutingRule *rule = priv->routing_rules->pdata[i]; - gs_free_error GError *local = NULL; - - if (_ip_routing_rule_get_addr_family(rule) - != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%u. rule has wrong address-family"), - i + 1); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTING_RULES); - return FALSE; - } - if (!nm_ip_routing_rule_validate(rule, &local)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%u. rule is invalid: %s"), - i + 1, - local->message); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_ROUTES); - return FALSE; - } - } - } - - if (priv->dhcp_iaid && !_nm_utils_iaid_verify(priv->dhcp_iaid, NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IAID"), - priv->dhcp_iaid); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_IAID); - return FALSE; - } - - /* Validate DHCP hostname flags */ - if (priv->dhcp_hostname_flags != NM_DHCP_HOSTNAME_FLAG_NONE && !priv->dhcp_send_hostname) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the property cannot be set when '%s' is disabled"), - NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); - return FALSE; - } - - if (!_nm_utils_validate_dhcp_hostname_flags(priv->dhcp_hostname_flags, - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), - error)) { - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS); - return FALSE; - } - - /* Validate reject servers */ - if (priv->dhcp_reject_servers && priv->dhcp_reject_servers->len != 0) { - if (NM_SETTING_IP_CONFIG_GET_FAMILY(setting) != AF_INET) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("the property is currently supported only for DHCPv4")); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); - return FALSE; - } - - for (i = 0; i < priv->dhcp_reject_servers->len; i++) { - if (!nm_utils_parse_inaddr_prefix( - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), - g_array_index(priv->dhcp_reject_servers, const char *, i), - NULL, - NULL)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid IP or subnet"), - g_array_index(priv->dhcp_reject_servers, const char *, i)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS); - return FALSE; - } - } - } - - /* Normalizable errors */ - if (priv->gateway && priv->never_default) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a gateway is incompatible with '%s'"), - NM_SETTING_IP_CONFIG_NEVER_DEFAULT); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_GATEWAY); - return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - - return TRUE; -} - -static NMTernary -compare_property(const NMSettInfoSetting *sett_info, - guint property_idx, - NMConnection * con_a, - NMSetting * set_a, - NMConnection * con_b, - NMSetting * set_b, - NMSettingCompareFlags flags) -{ - NMSettingIPConfigPrivate *a_priv; - NMSettingIPConfigPrivate *b_priv; - guint i; - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ADDRESSES)) { - if (set_b) { - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - if (a_priv->addresses->len != b_priv->addresses->len) - return FALSE; - for (i = 0; i < a_priv->addresses->len; i++) { - if (nm_ip_address_cmp_full(a_priv->addresses->pdata[i], - b_priv->addresses->pdata[i], - NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) - != 0) - return FALSE; - } - } - return TRUE; - } - - if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ROUTES)) { - if (set_b) { - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - if (a_priv->routes->len != b_priv->routes->len) - return FALSE; - for (i = 0; i < a_priv->routes->len; i++) { - if (!nm_ip_route_equal_full(a_priv->routes->pdata[i], - b_priv->routes->pdata[i], - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) - return FALSE; - } - } - return TRUE; - } - - if (nm_streq(sett_info->property_infos[property_idx].name, - NM_SETTING_IP_CONFIG_ROUTING_RULES)) { - if (set_b) { - guint n; - - a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a); - b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b); - - n = (a_priv->routing_rules) ? a_priv->routing_rules->len : 0u; - if (n != (b_priv->routing_rules ? b_priv->routing_rules->len : 0u)) - return FALSE; - for (i = 0; i < n; i++) { - if (nm_ip_routing_rule_cmp(a_priv->routing_rules->pdata[i], - b_priv->routing_rules->pdata[i]) - != 0) - return FALSE; - } - } - return TRUE; - } - - return NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); -} - -static void -duplicate_copy_properties(const NMSettInfoSetting *sett_info, NMSetting *src, NMSetting *dst) -{ - NMSettingIPConfigPrivate *priv_src = NM_SETTING_IP_CONFIG_GET_PRIVATE(src); - NMSettingIPConfigPrivate *priv_dst = NM_SETTING_IP_CONFIG_GET_PRIVATE(dst); - guint i; - gboolean changed = FALSE; - - NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->duplicate_copy_properties(sett_info, src, dst); - - if (priv_dst->routing_rules && priv_dst->routing_rules->len > 0) { - changed = TRUE; - g_ptr_array_set_size(priv_dst->routing_rules, 0); - } - if (priv_src->routing_rules && priv_src->routing_rules->len > 0) { - changed = TRUE; - if (!priv_dst->routing_rules) - priv_dst->routing_rules = - g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - for (i = 0; i < priv_src->routing_rules->len; i++) { - g_ptr_array_add(priv_dst->routing_rules, - nm_ip_routing_rule_ref(priv_src->routing_rules->pdata[i])); - } - } - if (changed) - _routing_rules_notify(NM_SETTING_IP_CONFIG(dst)); -} - -static void -enumerate_values(const NMSettInfoProperty *property_info, - NMSetting * setting, - NMSettingValueIterFn func, - gpointer user_data) -{ - if (nm_streq(property_info->name, NM_SETTING_IP_CONFIG_ROUTING_RULES)) { - NMSettingIPConfigPrivate * priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - GPtrArray * ptr = NULL; - guint i; - - if (priv->routing_rules && priv->routing_rules->len > 0) { - ptr = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_routing_rule_unref); - for (i = 0; i < priv->routing_rules->len; i++) - g_ptr_array_add(ptr, nm_ip_routing_rule_ref(priv->routing_rules->pdata[i])); - } - g_value_init(&value, G_TYPE_PTR_ARRAY); - g_value_take_boxed(&value, ptr); - func(setting, property_info->name, &value, 0, user_data); - return; - } - - NM_SETTING_CLASS(nm_setting_ip_config_parent_class) - ->enumerate_values(property_info, setting, func, user_data); -} - -/*****************************************************************************/ - -static gboolean -ip_gateway_set(NMSetting * setting, - GVariant * connection_dict, - const char * property, - GVariant * value, - NMSettingParseFlags parse_flags, - GError ** error) -{ - /* FIXME: properly handle errors */ - - /* Don't set from 'gateway' if we're going to use the gateway in 'addresses' */ - if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "gateway")) - return TRUE; - - g_object_set(setting, property, g_variant_get_string(value, NULL), NULL); - return TRUE; -} - -GArray * -_nm_sett_info_property_override_create_array_ip_config(void) -{ - GArray *properties_override = _nm_sett_info_property_override_create_array(); - - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_GATEWAY], - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = G_VARIANT_TYPE_STRING, - .from_dbus_fcn = ip_gateway_set, )); - - /* ---dbus--- - * property: routing-rules - * format: array of 'a{sv}' - * description: Array of dictionaries for routing rules. - * ---end--- - */ - _nm_properties_override_dbus( - properties_override, - NM_SETTING_IP_CONFIG_ROUTING_RULES, - NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _routing_rules_dbus_only_synth, - .from_dbus_fcn = _routing_rules_dbus_only_set, )); - - return properties_override; -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - switch (prop_id) { - case PROP_METHOD: - g_value_set_string(value, nm_setting_ip_config_get_method(setting)); - break; - case PROP_DNS: - g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns)); - break; - case PROP_DNS_SEARCH: - g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns_search)); - break; - case PROP_DNS_OPTIONS: - g_value_take_boxed(value, - priv->dns_options ? _nm_utils_ptrarray_to_strv(priv->dns_options) - : NULL); - break; - case PROP_DNS_PRIORITY: - g_value_set_int(value, priv->dns_priority); - break; - case PROP_ADDRESSES: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->addresses, - (NMUtilsCopyFunc) nm_ip_address_dup, - (GDestroyNotify) nm_ip_address_unref)); - break; - case PROP_GATEWAY: - g_value_set_string(value, nm_setting_ip_config_get_gateway(setting)); - break; - case PROP_ROUTES: - g_value_take_boxed(value, - _nm_utils_copy_array(priv->routes, - (NMUtilsCopyFunc) nm_ip_route_dup, - (GDestroyNotify) nm_ip_route_unref)); - break; - case PROP_ROUTE_METRIC: - g_value_set_int64(value, priv->route_metric); - break; - case PROP_ROUTE_TABLE: - g_value_set_uint(value, priv->route_table); - break; - case PROP_IGNORE_AUTO_ROUTES: - g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_routes(setting)); - break; - case PROP_IGNORE_AUTO_DNS: - g_value_set_boolean(value, nm_setting_ip_config_get_ignore_auto_dns(setting)); - break; - case PROP_DHCP_HOSTNAME: - g_value_set_string(value, nm_setting_ip_config_get_dhcp_hostname(setting)); - break; - case PROP_DHCP_SEND_HOSTNAME: - g_value_set_boolean(value, nm_setting_ip_config_get_dhcp_send_hostname(setting)); - break; - case PROP_NEVER_DEFAULT: - g_value_set_boolean(value, priv->never_default); - break; - case PROP_MAY_FAIL: - g_value_set_boolean(value, priv->may_fail); - break; - case PROP_DAD_TIMEOUT: - g_value_set_int(value, nm_setting_ip_config_get_dad_timeout(setting)); - break; - case PROP_DHCP_TIMEOUT: - g_value_set_int(value, nm_setting_ip_config_get_dhcp_timeout(setting)); - break; - case PROP_DHCP_IAID: - g_value_set_string(value, nm_setting_ip_config_get_dhcp_iaid(setting)); - break; - case PROP_DHCP_HOSTNAME_FLAGS: - g_value_set_uint(value, nm_setting_ip_config_get_dhcp_hostname_flags(setting)); - break; - case PROP_DHCP_REJECT_SERVERS: - g_value_set_boxed(value, nm_strvarray_get_strv_non_empty(priv->dhcp_reject_servers, NULL)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMSettingIPConfig * setting = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - const char * gateway; - char ** strv; - guint i; - - switch (prop_id) { - case PROP_METHOD: - g_free(priv->method); - priv->method = g_value_dup_string(value); - break; - case PROP_DNS: - g_ptr_array_unref(priv->dns); - priv->dns = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); - break; - case PROP_DNS_SEARCH: - g_ptr_array_unref(priv->dns_search); - priv->dns_search = _nm_utils_strv_to_ptrarray(g_value_get_boxed(value)); - break; - case PROP_DNS_OPTIONS: - strv = g_value_get_boxed(value); - if (!strv) { - if (priv->dns_options) { - g_ptr_array_unref(priv->dns_options); - priv->dns_options = NULL; - } - } else { - if (priv->dns_options) - g_ptr_array_set_size(priv->dns_options, 0); - else - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - for (i = 0; strv[i]; i++) { - if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, FALSE, NULL) - && _nm_utils_dns_option_find_idx(priv->dns_options, strv[i]) < 0) - g_ptr_array_add(priv->dns_options, g_strdup(strv[i])); - } - } - break; - case PROP_DNS_PRIORITY: - priv->dns_priority = g_value_get_int(value); - break; - case PROP_ADDRESSES: - g_ptr_array_unref(priv->addresses); - priv->addresses = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_ip_address_dup, - (GDestroyNotify) nm_ip_address_unref); - break; - case PROP_GATEWAY: - gateway = g_value_get_string(value); - g_return_if_fail( - !gateway - || nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway)); - g_free(priv->gateway); - priv->gateway = canonicalize_ip(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), gateway, TRUE); - break; - case PROP_ROUTES: - g_ptr_array_unref(priv->routes); - priv->routes = _nm_utils_copy_array(g_value_get_boxed(value), - (NMUtilsCopyFunc) nm_ip_route_dup, - (GDestroyNotify) nm_ip_route_unref); - break; - case PROP_ROUTE_METRIC: - priv->route_metric = g_value_get_int64(value); - break; - case PROP_ROUTE_TABLE: - priv->route_table = g_value_get_uint(value); - break; - case PROP_IGNORE_AUTO_ROUTES: - priv->ignore_auto_routes = g_value_get_boolean(value); - break; - case PROP_IGNORE_AUTO_DNS: - priv->ignore_auto_dns = g_value_get_boolean(value); - break; - case PROP_DHCP_HOSTNAME: - g_free(priv->dhcp_hostname); - priv->dhcp_hostname = g_value_dup_string(value); - break; - case PROP_DHCP_SEND_HOSTNAME: - priv->dhcp_send_hostname = g_value_get_boolean(value); - break; - case PROP_NEVER_DEFAULT: - priv->never_default = g_value_get_boolean(value); - break; - case PROP_MAY_FAIL: - priv->may_fail = g_value_get_boolean(value); - break; - case PROP_DAD_TIMEOUT: - priv->dad_timeout = g_value_get_int(value); - break; - case PROP_DHCP_TIMEOUT: - priv->dhcp_timeout = g_value_get_int(value); - break; - case PROP_DHCP_IAID: - g_free(priv->dhcp_iaid); - priv->dhcp_iaid = g_value_dup_string(value); - break; - case PROP_DHCP_HOSTNAME_FLAGS: - priv->dhcp_hostname_flags = g_value_get_uint(value); - break; - case PROP_DHCP_REJECT_SERVERS: - nm_strvarray_set_strv(&priv->dhcp_reject_servers, g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_setting_ip_config_init(NMSettingIPConfig *setting) -{ - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - priv->dns = g_ptr_array_new_with_free_func(g_free); - priv->dns_search = g_ptr_array_new_with_free_func(g_free); - priv->addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); - priv->routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); - priv->route_metric = -1; - priv->dhcp_send_hostname = TRUE; - priv->may_fail = TRUE; - priv->dad_timeout = -1; -} - -static void -finalize(GObject *object) -{ - NMSettingIPConfig * self = NM_SETTING_IP_CONFIG(object); - NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - - g_free(priv->method); - g_free(priv->gateway); - g_free(priv->dhcp_hostname); - g_free(priv->dhcp_iaid); - - g_ptr_array_unref(priv->dns); - g_ptr_array_unref(priv->dns_search); - if (priv->dns_options) - g_ptr_array_unref(priv->dns_options); - g_ptr_array_unref(priv->addresses); - g_ptr_array_unref(priv->routes); - if (priv->routing_rules) - g_ptr_array_unref(priv->routing_rules); - nm_clear_pointer(&priv->dhcp_reject_servers, g_array_unref); - - G_OBJECT_CLASS(nm_setting_ip_config_parent_class)->finalize(object); -} - -static void -nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMSettingClass *setting_class = NM_SETTING_CLASS(klass); - - g_type_class_add_private(klass, sizeof(NMSettingIPConfigPrivate)); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - setting_class->verify = verify; - setting_class->compare_property = compare_property; - setting_class->duplicate_copy_properties = duplicate_copy_properties; - setting_class->enumerate_values = enumerate_values; - - /** - * NMSettingIPConfig:method: - * - * IP configuration method. - * - * #NMSettingIP4Config and #NMSettingIP6Config both support "disabled", - * "auto", "manual", and "link-local". See the subclass-specific - * documentation for other values. - * - * In general, for the "auto" method, properties such as - * #NMSettingIPConfig:dns and #NMSettingIPConfig:routes specify information - * that is added on to the information returned from automatic - * configuration. The #NMSettingIPConfig:ignore-auto-routes and - * #NMSettingIPConfig:ignore-auto-dns properties modify this behavior. - * - * For methods that imply no upstream network, such as "shared" or - * "link-local", these properties must be empty. - * - * For IPv4 method "shared", the IP subnet can be configured by adding one - * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the - * shared method must be configured on the interface which shares the internet - * to a subnet, not on the uplink which is shared. - **/ - obj_properties[PROP_METHOD] = g_param_spec_string( - NM_SETTING_IP_CONFIG_METHOD, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns: - * - * Array of IP addresses of DNS servers. - **/ - obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-search: - * - * Array of DNS search domains. Domains starting with a tilde ('~') - * are considered 'routing' domains and are used only to decide the - * interface over which a query must be forwarded; they are not used - * to complete unqualified host names. - * - * When using a DNS plugin that supports Conditional Forwarding or - * Split DNS, then the search domains specify which name servers to - * query. This makes the behavior different from running with plain - * /etc/resolv.conf. For more information see also the dns-priority setting. - **/ - obj_properties[PROP_DNS_SEARCH] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_SEARCH, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-options: - * - * Array of DNS options as described in man 5 resolv.conf. - * - * %NULL means that the options are unset and left at the default. - * In this case NetworkManager will use default options. This is - * distinct from an empty list of properties. - * - * The currently supported options are "attempts", "debug", "edns0", - * "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", - * "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single-request", - * "single-request-reopen", "timeout", "trust-ad", "use-vc". - * - * The "trust-ad" setting is only honored if the profile contributes - * name servers to resolv.conf, and if all contributing profiles have - * "trust-ad" enabled. - * - * When using a caching DNS plugin (dnsmasq or systemd-resolved in - * NetworkManager.conf) then "edns0" and "trust-ad" are automatically - * added. - * - * Since: 1.2 - **/ - obj_properties[PROP_DNS_OPTIONS] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS_OPTIONS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dns-priority: - * - * DNS servers priority. - * - * The relative priority for DNS servers specified by this setting. A lower - * numerical value is better (higher priority). - * - * Negative values have the special effect of excluding other configurations - * with a greater numerical priority value; so in presence of at least one negative - * priority, only DNS servers from connections with the lowest priority value will be used. - * To avoid all DNS leaks, set the priority of the profile that should be used - * to the most negative value of all active connections profiles. - * - * Zero selects a globally configured default value. If the latter is missing - * or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for - * other connections. - * - * Note that the priority is to order DNS settings for multiple active - * connections. It does not disambiguate multiple DNS servers within the - * same connection profile. - * - * When multiple devices have configurations with the same priority, VPNs will be - * considered first, then devices with the best (lowest metric) default - * route and then all other devices. - * - * When using dns=default, servers with higher priority will be on top of - * resolv.conf. To prioritize a given server over another one within the - * same connection, just specify them in the desired order. - * Note that commonly the resolver tries name servers in /etc/resolv.conf - * in the order listed, proceeding with the next server in the list - * on failure. See for example the "rotate" option of the dns-options setting. - * If there are any negative DNS priorities, then only name servers from - * the devices with that lowest priority will be considered. - * - * When using a DNS resolver that supports Conditional Forwarding or - * Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection - * is used to query domains in its search list. The search domains determine which - * name servers to ask, and the DNS priority is used to prioritize - * name servers based on the domain. Queries for domains not present in any - * search list are routed through connections having the '~.' special wildcard - * domain, which is added automatically to connections with the default route - * (or can be added manually). When multiple connections specify the same domain, the - * one with the best priority (lowest numerical value) wins. If a sub domain - * is configured on another interface it will be accepted regardless the priority, - * unless parent domain on the other interface has a negative priority, which causes - * the sub domain to be shadowed. - * With Split DNS one can avoid undesired DNS leaks by properly configuring - * DNS priorities and the search domains, so that only name servers of the desired - * interface are configured. - * - * Since: 1.4 - **/ - obj_properties[PROP_DNS_PRIORITY] = - g_param_spec_int(NM_SETTING_IP_CONFIG_DNS_PRIORITY, - "", - "", - G_MININT32, - G_MAXINT32, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:addresses: (type GPtrArray(NMIPAddress)) - * - * Array of IP addresses. - **/ - obj_properties[PROP_ADDRESSES] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_ADDRESSES, - "", - "", - G_TYPE_PTR_ARRAY, - /* "addresses" is a legacy D-Bus property, because the - * "addresses" GObject property normally gets set from - * the "address-data" D-Bus property... - */ - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | NM_SETTING_PARAM_LEGACY - | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:gateway: - * - * The gateway associated with this configuration. This is only meaningful - * if #NMSettingIPConfig:addresses is also set. - * - * The gateway's main purpose is to control the next hop of the standard default route on the device. - * Hence, the gateway property conflicts with #NMSettingIPConfig:never-default and will be - * automatically dropped if the IP configuration is set to never-default. - * - * As an alternative to set the gateway, configure a static default route with /0 as prefix - * length. - **/ - obj_properties[PROP_GATEWAY] = g_param_spec_string( - NM_SETTING_IP_CONFIG_GATEWAY, - "", - "", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) - * - * Array of IP routes. - **/ - obj_properties[PROP_ROUTES] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_ROUTES, - "", - "", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | - /* See :addresses above Re: LEGACY */ - NM_SETTING_PARAM_LEGACY | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:route-metric: - * - * The default metric for routes that don't explicitly specify a metric. - * The default value -1 means that the metric is chosen automatically - * based on the device type. - * The metric applies to dynamic routes, manual (static) routes that - * don't have an explicit metric setting, address prefix routes, and - * the default route. - * Note that for IPv6, the kernel accepts zero (0) but coerces it to - * 1024 (user default). Hence, setting this property to zero effectively - * mean setting it to 1024. - * For IPv4, zero is a regular value for the metric. - **/ - obj_properties[PROP_ROUTE_METRIC] = - g_param_spec_int64(NM_SETTING_IP_CONFIG_ROUTE_METRIC, - "", - "", - -1, - G_MAXUINT32, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:route-table: - * - * Enable policy routing (source routing) and set the routing table used when adding routes. - * - * This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes - * and static routes. But note that static routes can individually overwrite the setting - * by explicitly specifying a non-zero routing table. - * - * If the table setting is left at zero, it is eligible to be overwritten via global - * configuration. If the property is zero even after applying the global configuration - * value, policy routing is disabled for the address family of this connection. - * - * Policy routing disabled means that NetworkManager will add all routes to the main - * table (except static routes that explicitly configure a different table). Additionally, - * NetworkManager will not delete any extraneous routes from tables except the main table. - * This is to preserve backward compatibility for users who manage routing tables outside - * of NetworkManager. - * - * Since: 1.10 - **/ - obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint( - NM_SETTING_IP_CONFIG_ROUTE_TABLE, - "", - "", - 0, - G_MAXUINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - /** - * NMSettingIPConfig:ignore-auto-routes: - * - * When #NMSettingIPConfig:method is set to "auto" and this property to - * %TRUE, automatically configured routes are ignored and only routes - * specified in the #NMSettingIPConfig:routes property, if any, are used. - **/ - obj_properties[PROP_IGNORE_AUTO_ROUTES] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:ignore-auto-dns: - * - * When #NMSettingIPConfig:method is set to "auto" and this property to - * %TRUE, automatically configured name servers and search domains are - * ignored and only name servers and search domains specified in the - * #NMSettingIPConfig:dns and #NMSettingIPConfig:dns-search properties, if - * any, are used. - **/ - obj_properties[PROP_IGNORE_AUTO_DNS] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-hostname: - * - * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the - * specified name will be sent to the DHCP server when acquiring a lease. - * This property and #NMSettingIP4Config:dhcp-fqdn are mutually exclusive and - * cannot be set at the same time. - **/ - obj_properties[PROP_DHCP_HOSTNAME] = - g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-send-hostname: - * - * If %TRUE, a hostname is sent to the DHCP server when acquiring a lease. - * Some DHCP servers use this hostname to update DNS databases, essentially - * providing a static hostname for the computer. If the - * #NMSettingIPConfig:dhcp-hostname property is %NULL and this property is - * %TRUE, the current persistent hostname of the computer is sent. - **/ - obj_properties[PROP_DHCP_SEND_HOSTNAME] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:never-default: - * - * If %TRUE, this connection will never be the default connection for this - * IP type, meaning it will never be assigned the default route by - * NetworkManager. - **/ - obj_properties[PROP_NEVER_DEFAULT] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_NEVER_DEFAULT, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:may-fail: - * - * If %TRUE, allow overall network configuration to proceed even if the - * configuration specified by this property times out. Note that at least - * one IP configuration must succeed or overall network configuration will - * still fail. For example, in IPv6-only networks, setting this property to - * %TRUE on the #NMSettingIP4Config allows the overall network configuration - * to succeed if IPv4 configuration fails but IPv6 configuration completes - * successfully. - **/ - obj_properties[PROP_MAY_FAIL] = - g_param_spec_boolean(NM_SETTING_IP_CONFIG_MAY_FAIL, - "", - "", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dad-timeout: - * - * Timeout in milliseconds used to check for the presence of duplicate IP - * addresses on the network. If an address conflict is detected, the - * activation will fail. A zero value means that no duplicate address - * detection is performed, -1 means the default value (either configuration - * ipvx.dad-timeout override or zero). A value greater than zero is a - * timeout in milliseconds. - * - * The property is currently implemented only for IPv4. - * - * Since: 1.2 - **/ - obj_properties[PROP_DAD_TIMEOUT] = g_param_spec_int( - NM_SETTING_IP_CONFIG_DAD_TIMEOUT, - "", - "", - -1, - NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, - -1, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-timeout: - * - * A timeout for a DHCP transaction in seconds. If zero (the default), a - * globally configured default is used. If still unspecified, a device specific - * timeout is used (usually 45 seconds). - * - * Set to 2147483647 (MAXINT32) for infinity. - **/ - obj_properties[PROP_DHCP_TIMEOUT] = g_param_spec_int( - NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, - "", - "", - 0, - G_MAXINT32, - 0, - G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-iaid: - * - * A string containing the "Identity Association Identifier" (IAID) used - * by the DHCP client. The property is a 32-bit decimal value or a - * special value among "mac", "perm-mac", "ifname" and "stable". When - * set to "mac" (or "perm-mac"), the last 4 bytes of the current (or - * permanent) MAC address are used as IAID. When set to "ifname", the - * IAID is computed by hashing the interface name. The special value - * "stable" can be used to generate an IAID based on the stable-id (see - * connection.stable-id), a per-host key and the interface name. When - * the property is unset, the value from global configuration is used; - * if no global default is set then the IAID is assumed to be - * "ifname". Note that at the moment this property is ignored for IPv6 - * by dhclient, which always derives the IAID from the MAC address. - * - * Since: 1.22 - **/ - obj_properties[PROP_DHCP_IAID] = - g_param_spec_string(NM_SETTING_IP_CONFIG_DHCP_IAID, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-hostname-flags: - * - * Flags for the DHCP hostname and FQDN. - * - * Currently, this property only includes flags to control the FQDN flags - * set in the DHCP FQDN option. Supported FQDN flags are - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE. When no FQDN flag is set and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is set, the DHCP FQDN option will - * contain no flag. Otherwise, if no FQDN flag is set and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS is not set, the standard FQDN flags - * are set in the request: - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - * %NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED for IPv4 and - * %NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE for IPv6. - * - * When this property is set to the default value %NM_DHCP_HOSTNAME_FLAG_NONE, - * a global default is looked up in NetworkManager configuration. If that value - * is unset or also %NM_DHCP_HOSTNAME_FLAG_NONE, then the standard FQDN flags - * described above are sent in the DHCP requests. - * - * Since: 1.22 - */ - obj_properties[PROP_DHCP_HOSTNAME_FLAGS] = - g_param_spec_uint(NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, - "", - "", - 0, - G_MAXUINT32, - NM_DHCP_HOSTNAME_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * NMSettingIPConfig:dhcp-reject-servers: - * - * Array of servers from which DHCP offers must be rejected. This property - * is useful to avoid getting a lease from misconfigured or rogue servers. - * - * For DHCPv4, each element must be an IPv4 address, optionally - * followed by a slash and a prefix length (e.g. "192.168.122.0/24"). - * - * This property is currently not implemented for DHCPv6. - * - * Since: 1.28 - **/ - obj_properties[PROP_DHCP_REJECT_SERVERS] = - g_param_spec_boxed(NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} |