mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-23 16:40:43 +01:00
tui: guess the prefix length (netmask) of private IPv4 addresses and routes based on network class
For RFC1918 private IPv4addresses, guess a better prefix length for addresses and routes. nmtui is an interactive program. It makes sense to be a bit smarter about what the user probably meant. It would be nice if nmtui would update the entry field immediately when the cursor leaves the field, to show the guessed prefix length. However, that is not easily possible, so lets to that another time. For IPv6 addresses, default to /64 instead of /128. https://bugzilla.redhat.com/show_bug.cgi?id=1474295
This commit is contained in:
parent
b434d7d436
commit
506fca65b3
4 changed files with 117 additions and 73 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue