mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-23 19:24:38 +00:00
cli: support route options
This commit is contained in:
parent
40e1fd9531
commit
d094914120
|
@ -395,26 +395,20 @@ finish:
|
|||
/*
|
||||
* nmc_parse_and_build_route:
|
||||
* @family: AF_INET or AF_INET6
|
||||
* @first: the route destination in the form of "address/prefix"
|
||||
(/prefix is optional)
|
||||
* @second: (allow-none): next hop address, if third is not NULL. Otherwise it could be
|
||||
either next hop address or metric. (It can be NULL when @third is NULL).
|
||||
* @third: (allow-none): route metric
|
||||
* @str: route string to be parsed
|
||||
* @error: location to store GError
|
||||
*
|
||||
* Parse route from strings and return an #NMIPRoute
|
||||
* Parse route from string and return an #NMIPRoute
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure
|
||||
* Returns: a new #NMIPRoute or %NULL on error
|
||||
*/
|
||||
NMIPRoute *
|
||||
nmc_parse_and_build_route (int family,
|
||||
const char *first,
|
||||
const char *second,
|
||||
const char *third,
|
||||
const char *str,
|
||||
GError **error)
|
||||
{
|
||||
int max_prefix = (family == AF_INET) ? 32 : 128;
|
||||
char *dest = NULL, *plen = NULL;
|
||||
char *plen = NULL;
|
||||
const char *next_hop = NULL;
|
||||
const char *canon_dest;
|
||||
long int prefix = max_prefix;
|
||||
|
@ -423,13 +417,27 @@ nmc_parse_and_build_route (int family,
|
|||
gboolean success = FALSE;
|
||||
GError *local = NULL;
|
||||
gint64 metric = -1;
|
||||
guint i, len;
|
||||
gs_strfreev char **routev = NULL;
|
||||
gs_free char *value = NULL;
|
||||
gs_free char *dest = NULL;
|
||||
gs_unref_hashtable GHashTable *attrs = NULL;
|
||||
GHashTable *tmp_attrs;
|
||||
|
||||
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
|
||||
g_return_val_if_fail (first != NULL, FALSE);
|
||||
g_return_val_if_fail (second || !third, FALSE);
|
||||
g_return_val_if_fail (str, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
dest = g_strdup (first);
|
||||
value = g_strdup (str);
|
||||
routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
|
||||
len = g_strv_length (routev);
|
||||
if (len < 1) {
|
||||
g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric] [attr=val] [attr=val])"),
|
||||
str);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
dest = g_strdup (routev[0]);
|
||||
plen = strchr (dest, '/'); /* prefix delimiter */
|
||||
if (plen)
|
||||
*plen++ = '\0';
|
||||
|
@ -443,26 +451,50 @@ nmc_parse_and_build_route (int family,
|
|||
}
|
||||
}
|
||||
|
||||
if (second) {
|
||||
if (third || nm_utils_ipaddr_valid (family, second))
|
||||
next_hop = second;
|
||||
else {
|
||||
/* 'second' can be a metric */
|
||||
if (!nmc_string_to_uint (second, TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
g_set_error (error, 1, 0, _("the second component of route ('%s') is neither "
|
||||
"a next hop address nor a metric"), second);
|
||||
for (i = 1; i < len; i++) {
|
||||
if (nm_utils_ipaddr_valid (family, routev[i])) {
|
||||
if (metric != -1 || attrs) {
|
||||
g_set_error (error, 1, 0, _("the next hop ('%s') must be first"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
next_hop = routev[i];
|
||||
} else if (nmc_string_to_uint (routev[i], TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
if (attrs) {
|
||||
g_set_error (error, 1, 0, _("the metric ('%s') must be before attributes"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
metric = tmp_ulong;
|
||||
}
|
||||
}
|
||||
} else if (strchr (routev[i], '=')) {
|
||||
GHashTableIter iter;
|
||||
char *iter_key;
|
||||
GVariant *iter_value;
|
||||
|
||||
if (third) {
|
||||
if (!nmc_string_to_uint (third, TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
|
||||
g_set_error (error, 1, 0, _("invalid metric '%s'"), third);
|
||||
tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE,
|
||||
nm_ip_route_get_variant_attribute_spec(),
|
||||
error);
|
||||
if (!tmp_attrs) {
|
||||
g_prefix_error (error, "invalid option '%s': ", routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!attrs)
|
||||
attrs = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_iter_init (&iter, tmp_attrs);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &iter_key, (gpointer *) &iter_value)) {
|
||||
if (!nm_ip_route_attribute_validate (iter_key, iter_value, family, NULL, error)) {
|
||||
g_prefix_error (error, "%s: ", iter_key);
|
||||
g_hash_table_unref (tmp_attrs);
|
||||
goto finish;
|
||||
}
|
||||
g_hash_table_insert (attrs, iter_key, iter_value);
|
||||
g_hash_table_iter_steal (&iter);
|
||||
}
|
||||
g_hash_table_unref (tmp_attrs);
|
||||
} else {
|
||||
g_set_error (error, 1, 0, _("unrecognized option '%s'"), routev[i]);
|
||||
goto finish;
|
||||
}
|
||||
metric = tmp_ulong;
|
||||
}
|
||||
|
||||
route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local);
|
||||
|
@ -485,10 +517,19 @@ nmc_parse_and_build_route (int family,
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
GHashTableIter iter;
|
||||
char *name;
|
||||
GVariant *variant;
|
||||
|
||||
g_hash_table_iter_init (&iter, attrs);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant))
|
||||
nm_ip_route_set_attribute (route, name, variant);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
finish:
|
||||
g_free (dest);
|
||||
return route;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ gboolean print_dhcp4_config (NMDhcpConfig *dhcp4, NmCli *nmc, const char *group_
|
|||
gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, NmCli *nmc, const char *group_prefix, const char *one_field);
|
||||
|
||||
NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, GError **error);
|
||||
NMIPRoute *nmc_parse_and_build_route (int family, const char *first, const char *second, const char *third, GError **error);
|
||||
NMIPRoute *nmc_parse_and_build_route (int family, const char *str, GError **error);
|
||||
|
||||
const char * nmc_device_state_to_string (NMDeviceState state);
|
||||
const char * nmc_device_reason_to_string (NMDeviceStateReason reason);
|
||||
|
|
|
@ -3470,29 +3470,6 @@ _parse_ip_address (int family, const char *address, GError **error)
|
|||
return ipaddr;
|
||||
}
|
||||
|
||||
static NMIPRoute *
|
||||
_parse_ip_route (int family, const char *route, GError **error)
|
||||
{
|
||||
char *value = g_strdup (route);
|
||||
char **routev;
|
||||
guint len;
|
||||
NMIPRoute *iproute = NULL;
|
||||
|
||||
routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
|
||||
len = g_strv_length (routev);
|
||||
if (len < 1 || len > 3) {
|
||||
g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric])"),
|
||||
route);
|
||||
goto finish;
|
||||
}
|
||||
iproute = nmc_parse_and_build_route (family, routev[0], routev[1], len >= 2 ? routev[2] : NULL, error);
|
||||
|
||||
finish:
|
||||
g_free (value);
|
||||
g_strfreev (routev);
|
||||
return iproute;
|
||||
}
|
||||
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_method, NM_SETTING_IP_CONFIG_METHOD)
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_dns, NM_SETTING_IP_CONFIG_DNS)
|
||||
DEFINE_GETTER (nmc_property_ipv4_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH)
|
||||
|
@ -3536,8 +3513,21 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
|
||||
num_routes = nm_setting_ip_config_get_num_routes (s_ip);
|
||||
for (i = 0; i < num_routes; i++) {
|
||||
gs_free char *attr_str = NULL;
|
||||
gs_strfreev char **attr_names = NULL;
|
||||
gs_unref_hashtable GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
int j;
|
||||
|
||||
route = nm_setting_ip_config_get_route (s_ip, i);
|
||||
|
||||
attr_names = nm_ip_route_get_attribute_names (route);
|
||||
for (j = 0; attr_names && attr_names[j]; j++) {
|
||||
g_hash_table_insert (hash, attr_names[j],
|
||||
nm_ip_route_get_attribute (route, attr_names[j]));
|
||||
}
|
||||
|
||||
attr_str = nm_utils_format_variant_attributes (hash, ' ', '=');
|
||||
|
||||
if (get_type == NMC_PROPERTY_GET_PARSABLE) {
|
||||
if (printable->len > 0)
|
||||
g_string_append (printable, ", ");
|
||||
|
@ -3550,7 +3540,10 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
g_string_append_printf (printable, " %s", nm_ip_route_get_next_hop (route));
|
||||
if (nm_ip_route_get_metric (route) != -1)
|
||||
g_string_append_printf (printable, " %u", (guint32) nm_ip_route_get_metric (route));
|
||||
if (attr_str)
|
||||
g_string_append_printf (printable, " %s", attr_str);
|
||||
} else {
|
||||
|
||||
if (printable->len > 0)
|
||||
g_string_append (printable, "; ");
|
||||
|
||||
|
@ -3567,6 +3560,8 @@ nmc_property_ipvx_get_routes (NMSetting *setting, NmcPropertyGetType get_type)
|
|||
|
||||
if (nm_ip_route_get_metric (route) != -1)
|
||||
g_string_append_printf (printable, ", mt = %u", (guint32) nm_ip_route_get_metric (route));
|
||||
if (attr_str)
|
||||
g_string_append_printf (printable, " %s", attr_str);
|
||||
|
||||
g_string_append (printable, " }");
|
||||
}
|
||||
|
@ -3858,7 +3853,7 @@ nmc_property_ipv4_set_gateway (NMSetting *setting, const char *prop, const char
|
|||
static NMIPRoute *
|
||||
_parse_ipv4_route (const char *route, GError **error)
|
||||
{
|
||||
return _parse_ip_route (AF_INET, route, error);
|
||||
return nmc_parse_and_build_route (AF_INET, route, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -4201,7 +4196,7 @@ nmc_property_ipv6_set_gateway (NMSetting *setting, const char *prop, const char
|
|||
static NMIPRoute *
|
||||
_parse_ipv6_route (const char *route, GError **error)
|
||||
{
|
||||
return _parse_ip_route (AF_INET6, route, error);
|
||||
return nmc_parse_and_build_route (AF_INET6, route, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
Loading…
Reference in a new issue