diff --git a/clients/tui/nm-editor-bindings.c b/clients/tui/nm-editor-bindings.c index 3753aaa9ac..7ac7f0c7e2 100644 --- a/clients/tui/nm-editor-bindings.c +++ b/clients/tui/nm-editor-bindings.c @@ -70,45 +70,6 @@ nm_editor_bindings_init (void) g_value_register_transform_func (G_TYPE_STRING, G_TYPE_UINT, value_transform_string_uint); } -static gboolean -parse_addr_prefix (const char *text, - int family, - char **addr, - guint32 *prefix) -{ - const char *slash; - char *addrstr, *end; - gboolean valid; - - slash = strchr (text, '/'); - - if (slash) - addrstr = g_strndup (text, slash - text); - else - addrstr = g_strdup (text); - valid = nm_utils_ipaddr_valid (family, addrstr); - - if (slash) { - *prefix = strtoul (slash + 1, &end, 10); - if ( *end - || *prefix == 0 - || (family == AF_INET && *prefix > 32) - || (family == AF_INET6 && *prefix > 128)) - valid = FALSE; - } else if (prefix) { - if (family == AF_INET) - *prefix = 32; - else - *prefix = 128; - } - - if (addr && valid) - *addr = addrstr; - else - g_free (addrstr); - return valid; -} - static gboolean ip_addresses_with_prefix_to_strv (GBinding *binding, const GValue *source_value, @@ -151,7 +112,7 @@ ip_addresses_with_prefix_from_strv (GBinding *binding, GPtrArray *addrs; NMIPAddress *addr; char *addrstr; - guint32 prefix; + int prefix; int i; strings = g_value_get_boxed (source_value); @@ -170,11 +131,24 @@ ip_addresses_with_prefix_from_strv (GBinding *binding, } else addr = addrs->pdata[i]; - if (!parse_addr_prefix (strings[i], family, &addrstr, &prefix)) { + if (!nm_utils_parse_inaddr_prefix (strings[i], family, &addrstr, &prefix)) { g_ptr_array_unref (addrs); return FALSE; } + if (prefix == -1) { + if (family == AF_INET) { + in_addr_t v4; + + inet_pton (family, addrstr, &v4); + if (nm_utils_ip_is_site_local (AF_INET, &v4)) + prefix = nm_utils_ip4_get_default_prefix (v4); + else + prefix = 32; + } else + prefix = 64; + } + nm_ip_address_set_address (addr, addrstr); nm_ip_address_set_prefix (addr, prefix); g_free (addrstr); @@ -451,10 +425,10 @@ ip_route_transform_from_dest_string (GBinding *binding, NMIPRoute *route; const char *text; char *addrstr; - guint32 prefix; + int prefix; text = g_value_get_string (source_value); - if (!parse_addr_prefix (text, family, &addrstr, &prefix)) + if (!nm_utils_parse_inaddr_prefix (text, family, &addrstr, &prefix)) return FALSE; /* Fetch the original property value */ @@ -462,6 +436,21 @@ ip_route_transform_from_dest_string (GBinding *binding, g_binding_get_source_property (binding), &route, NULL); + if (prefix == -1) { + if (family == AF_INET) { + in_addr_t v4; + + inet_pton (family, addrstr, &v4); + if (nm_utils_ip_is_site_local (AF_INET, &v4)) { + prefix = nm_utils_ip4_get_default_prefix (v4); + if (v4 & (~nm_utils_ip4_prefix_to_netmask (prefix))) + prefix = 32; + } else + prefix = 32; + } else + prefix = 64; + } + nm_ip_route_set_dest (route, addrstr); nm_ip_route_set_prefix (route, prefix); g_free (addrstr); diff --git a/clients/tui/nmt-ip-entry.c b/clients/tui/nmt-ip-entry.c index 8d8f888f0d..1556c8d7fe 100644 --- a/clients/tui/nmt-ip-entry.c +++ b/clients/tui/nmt-ip-entry.c @@ -123,39 +123,12 @@ ip_entry_validate (NmtNewtEntry *entry, gpointer user_data) { NmtIPEntryPrivate *priv = NMT_IP_ENTRY_GET_PRIVATE (entry); - guchar buf[16]; - guint32 prefix; - const char *slash; - char *addrstr, *end; - gboolean valid; if (!*text) return priv->optional; - - slash = strchr (text, '/'); - - if (slash) { - if (!priv->prefix) - return FALSE; - addrstr = g_strndup (text, slash - text); - } else - addrstr = g_strdup (text); - valid = (inet_pton (priv->family, addrstr, buf) == 1); - g_free (addrstr); - - if (!valid) - return FALSE; - - if (slash) { - prefix = strtoul (slash + 1, &end, 10); - if ( *end - || prefix == 0 - || (priv->family == AF_INET && prefix > 32) - || (priv->family == AF_INET6 && prefix > 128)) - valid = FALSE; - } - - return valid; + if (priv->prefix) + return nm_utils_parse_inaddr_prefix (text, priv->family, NULL, NULL); + return nm_utils_parse_inaddr (text, priv->family, NULL); } static void diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c index aa1e9f02dd..b512e52a57 100644 --- a/shared/nm-utils/nm-shared-utils.c +++ b/shared/nm-utils/nm-shared-utils.c @@ -169,6 +169,79 @@ nm_utils_ip_is_site_local (int addr_family, /*****************************************************************************/ +gboolean +nm_utils_parse_inaddr (const char *text, + int family, + char **out_addr) +{ + union { + in_addr_t v4; + struct in6_addr v6; + } addrbin; + char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + + g_return_val_if_fail (text, FALSE); + + if (family == AF_UNSPEC) + family = strchr (text, ':') ? AF_INET6 : AF_INET; + else + g_return_val_if_fail (NM_IN_SET (family, AF_INET, AF_INET6), FALSE); + + if (inet_pton (family, text, &addrbin) != 1) + return FALSE; + + NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf)))); + return TRUE; +} + +gboolean +nm_utils_parse_inaddr_prefix (const char *text, + int family, + char **out_addr, + int *out_prefix) +{ + gs_free char *addrstr_free = NULL; + int prefix = -1; + const char *slash; + const char *addrstr; + union { + in_addr_t v4; + struct in6_addr v6; + } addrbin; + char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + + g_return_val_if_fail (text, FALSE); + + if (family == AF_UNSPEC) + family = strchr (text, ':') ? AF_INET6 : AF_INET; + else + g_return_val_if_fail (NM_IN_SET (family, AF_INET, AF_INET6), FALSE); + + slash = strchr (text, '/'); + if (slash) + addrstr = addrstr_free = g_strndup (text, slash - text); + else + addrstr = text; + + if (inet_pton (family, addrstr, &addrbin) != 1) + return FALSE; + + if (slash) { + prefix = _nm_utils_ascii_str_to_int64 (slash + 1, 10, + 0, + family == AF_INET ? 32 : 128, + -1); + if (prefix == -1) + return FALSE; + } + + NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf)))); + NM_SET_OUT (out_prefix, prefix); + return TRUE; +} + +/*****************************************************************************/ + /* _nm_utils_ascii_str_to_int64: * * A wrapper for g_ascii_strtoll, that checks whether the whole string diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index 968f709ade..dc17fb269f 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -151,6 +151,15 @@ gboolean nm_utils_ip_is_site_local (int addr_family, /*****************************************************************************/ +gboolean nm_utils_parse_inaddr (const char *text, + int family, + char **out_addr); + +gboolean nm_utils_parse_inaddr_prefix (const char *text, + int family, + char **out_addr, + int *out_prefix); + gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); gint _nm_utils_ascii_str_to_bool (const char *str,