mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 22:20:19 +01:00
core: merge branch 'th/policy-routing-pt1-rh1436531'
Add initial support for policy-routing/source-routing. It does not support rules (yet), only configuring routes in a different routing table then 254 (main). And this currently only works for manually configured routes, not routes from DHCP or the default-route. https://bugzilla.redhat.com/show_bug.cgi?id=1436531
This commit is contained in:
commit
e6292bcb2a
27 changed files with 817 additions and 339 deletions
|
|
@ -38,6 +38,61 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static char **
|
||||
_ip_config_get_routes (NMIPConfig *cfg)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
GPtrArray *ptr_array;
|
||||
char **arr;
|
||||
guint i;
|
||||
|
||||
ptr_array = nm_ip_config_get_routes (cfg);
|
||||
if (!ptr_array)
|
||||
return NULL;
|
||||
|
||||
arr = g_new (char *, ptr_array->len + 1);
|
||||
for (i = 0; i < ptr_array->len; i++) {
|
||||
NMIPRoute *route = g_ptr_array_index (ptr_array, i);
|
||||
gs_strfreev char **names = NULL;
|
||||
gs_free char *attributes = NULL;
|
||||
gsize j;
|
||||
GString *str;
|
||||
guint64 metric;
|
||||
|
||||
str = g_string_new (NULL);
|
||||
g_string_append_printf (str,
|
||||
"dst = %s/%u, nh = %s",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
nm_ip_route_get_next_hop (route)
|
||||
?: (nm_ip_route_get_family (route) == AF_INET ? "0.0.0.0" : "::"));
|
||||
|
||||
metric = nm_ip_route_get_metric (route);
|
||||
if (metric != -1) {
|
||||
g_string_append_printf (str,
|
||||
", mt = %u",
|
||||
(guint) metric);
|
||||
}
|
||||
|
||||
names = nm_ip_route_get_attribute_names (route);
|
||||
g_hash_table_remove_all (hash);
|
||||
for (j = 0; names && names[j]; j++)
|
||||
g_hash_table_insert (hash, names[j], nm_ip_route_get_attribute (route, names[j]));
|
||||
attributes = nm_utils_format_variant_attributes (hash, ',', '=');
|
||||
if (attributes) {
|
||||
g_string_append (str, ", ");
|
||||
g_string_append (str, attributes);
|
||||
}
|
||||
|
||||
arr[i] = g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
nm_assert (i == ptr_array->len);
|
||||
arr[i] = NULL;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
static gconstpointer
|
||||
_metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
|
|
@ -81,27 +136,7 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment,
|
|||
case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
return NULL;
|
||||
ptr_array = nm_ip_config_get_routes (cfg4);
|
||||
if (ptr_array) {
|
||||
arr = g_new (char *, ptr_array->len + 1);
|
||||
for (i = 0; i < ptr_array->len; i++) {
|
||||
NMIPRoute *route = g_ptr_array_index (ptr_array, i);
|
||||
const char *next_hop;
|
||||
|
||||
next_hop = nm_ip_route_get_next_hop (route);
|
||||
if (!next_hop)
|
||||
next_hop = "0.0.0.0";
|
||||
|
||||
arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s%c mt = %u",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
next_hop,
|
||||
nm_ip_route_get_metric (route) == -1 ? '\0' : ',',
|
||||
(guint32) nm_ip_route_get_metric (route));
|
||||
}
|
||||
arr[i] = NULL;
|
||||
} else
|
||||
arr = NULL;
|
||||
arr = _ip_config_get_routes (cfg4);
|
||||
goto arr_out;
|
||||
case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
|
|
@ -134,6 +169,77 @@ arr_out:
|
|||
return arr;
|
||||
}
|
||||
|
||||
static gconstpointer
|
||||
_metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
const NmcMetaGenericInfo *info,
|
||||
gpointer target,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gpointer *out_to_free)
|
||||
{
|
||||
NMIPConfig *cfg6 = target;
|
||||
GPtrArray *ptr_array;
|
||||
char **arr;
|
||||
const char *const*arrc;
|
||||
guint i = 0;
|
||||
|
||||
nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM);
|
||||
|
||||
NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL);
|
||||
|
||||
switch (info->info_type) {
|
||||
case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
return NULL;
|
||||
ptr_array = nm_ip_config_get_addresses (cfg6);
|
||||
if (ptr_array) {
|
||||
arr = g_new (char *, ptr_array->len + 1);
|
||||
for (i = 0; i < ptr_array->len; i++) {
|
||||
NMIPAddress *addr = g_ptr_array_index (ptr_array, i);
|
||||
|
||||
arr[i] = g_strdup_printf ("%s/%u",
|
||||
nm_ip_address_get_address (addr),
|
||||
nm_ip_address_get_prefix (addr));
|
||||
}
|
||||
arr[i] = NULL;
|
||||
} else
|
||||
arr = NULL;
|
||||
goto arr_out;
|
||||
case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY:
|
||||
return nm_ip_config_get_gateway (cfg6);
|
||||
case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
return NULL;
|
||||
arr = _ip_config_get_routes (cfg6);
|
||||
goto arr_out;
|
||||
case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
return NULL;
|
||||
arrc = nm_ip_config_get_nameservers (cfg6);
|
||||
goto arrc_out;
|
||||
case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN:
|
||||
if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
||||
return NULL;
|
||||
arrc = nm_ip_config_get_domains (cfg6);
|
||||
goto arrc_out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
|
||||
arrc_out:
|
||||
*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
|
||||
return arrc;
|
||||
|
||||
arr_out:
|
||||
*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
|
||||
*out_to_free = arr;
|
||||
return arr;
|
||||
}
|
||||
|
||||
const NmcMetaGenericInfo *const metagen_ip4_config[_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM + 1] = {
|
||||
#define _METAGEN_IP4_CONFIG(type, name) \
|
||||
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip4_config_get_fcn)
|
||||
|
|
@ -150,6 +256,21 @@ static const NmcMetaGenericInfo *const metagen_ip4_config_group[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
const NmcMetaGenericInfo *const metagen_ip6_config[_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM + 1] = {
|
||||
#define _METAGEN_IP6_CONFIG(type, name) \
|
||||
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_ip6_config_get_fcn)
|
||||
_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS, "ADDRESS"),
|
||||
_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY, "GATEWAY"),
|
||||
_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE, "ROUTE"),
|
||||
_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS, "DNS"),
|
||||
_METAGEN_IP6_CONFIG (NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN, "DOMAIN"),
|
||||
};
|
||||
|
||||
static const NmcMetaGenericInfo *const metagen_ip6_config_group[] = {
|
||||
NMC_META_GENERIC_WITH_NESTED ("IP6", metagen_ip6_config, .name_header = N_("GROUP")),
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NmcMetaGenericInfo *const nmc_fields_dhcp4_config[] = {
|
||||
|
|
@ -205,79 +326,23 @@ print_ip6_config (NMIPConfig *cfg6,
|
|||
const char *group_prefix,
|
||||
const char *one_field)
|
||||
{
|
||||
GPtrArray *ptr_array;
|
||||
char **addr_arr = NULL;
|
||||
char **route_arr = NULL;
|
||||
char **dns_arr = NULL;
|
||||
char **domain_arr = NULL;
|
||||
int i = 0;
|
||||
const NMMetaAbstractInfo *const*tmpl;
|
||||
NmcOutputField *arr;
|
||||
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free char *field_str = NULL;
|
||||
|
||||
if (cfg6 == NULL)
|
||||
return FALSE;
|
||||
|
||||
tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_ip6_config;
|
||||
out_indices = parse_output_fields (one_field,
|
||||
tmpl, FALSE, NULL, NULL);
|
||||
arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
||||
g_ptr_array_add (out.output_data, arr);
|
||||
if (one_field)
|
||||
field_str = g_strdup_printf ("IP6.%s", one_field);
|
||||
|
||||
/* addresses */
|
||||
ptr_array = nm_ip_config_get_addresses (cfg6);
|
||||
if (ptr_array) {
|
||||
addr_arr = g_new (char *, ptr_array->len + 1);
|
||||
for (i = 0; i < ptr_array->len; i++) {
|
||||
NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i);
|
||||
|
||||
addr_arr[i] = g_strdup_printf ("%s/%u",
|
||||
nm_ip_address_get_address (addr),
|
||||
nm_ip_address_get_prefix (addr));
|
||||
}
|
||||
addr_arr[i] = NULL;
|
||||
if (!nmc_print (nmc_config,
|
||||
(gpointer[]) { cfg6, NULL },
|
||||
NULL,
|
||||
(const NMMetaAbstractInfo *const*) metagen_ip6_config_group,
|
||||
field_str,
|
||||
&error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* routes */
|
||||
ptr_array = nm_ip_config_get_routes (cfg6);
|
||||
if (ptr_array) {
|
||||
route_arr = g_new (char *, ptr_array->len + 1);
|
||||
for (i = 0; i < ptr_array->len; i++) {
|
||||
NMIPRoute *route = (NMIPRoute *) g_ptr_array_index (ptr_array, i);
|
||||
const char *next_hop;
|
||||
|
||||
next_hop = nm_ip_route_get_next_hop (route);
|
||||
if (!next_hop)
|
||||
next_hop = "::";
|
||||
|
||||
route_arr[i] = g_strdup_printf ("dst = %s/%u, nh = %s%c mt = %u",
|
||||
nm_ip_route_get_dest (route),
|
||||
nm_ip_route_get_prefix (route),
|
||||
next_hop,
|
||||
nm_ip_route_get_metric (route) == -1 ? '\0' : ',',
|
||||
(guint32) nm_ip_route_get_metric (route));
|
||||
}
|
||||
route_arr[i] = NULL;
|
||||
}
|
||||
|
||||
/* DNS */
|
||||
dns_arr = g_strdupv ((char **) nm_ip_config_get_nameservers (cfg6));
|
||||
|
||||
/* domains */
|
||||
domain_arr = g_strdupv ((char **) nm_ip_config_get_domains (cfg6));
|
||||
|
||||
arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
||||
set_val_strc (arr, 0, group_prefix);
|
||||
set_val_arr (arr, 1, addr_arr);
|
||||
set_val_strc (arr, 2, nm_ip_config_get_gateway (cfg6));
|
||||
set_val_arr (arr, 3, route_arr);
|
||||
set_val_arr (arr, 4, dns_arr);
|
||||
set_val_arr (arr, 5, domain_arr);
|
||||
g_ptr_array_add (out.output_data, arr);
|
||||
|
||||
print_data_prepare_width (out.output_data);
|
||||
print_data (nmc_config, out_indices, NULL, 0, &out);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,13 @@ typedef enum {
|
|||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS,
|
||||
_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN,
|
||||
_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM,
|
||||
|
||||
} NmcGenericInfoType;
|
||||
|
||||
#define NMC_HANDLE_TERMFORMAT(color) \
|
||||
|
|
|
|||
|
|
@ -5353,6 +5353,14 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
|
|||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_METRIC, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC,
|
||||
.property_type = &_pt_gobject_int,
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE_SYNC,
|
||||
.property_type = &_pt_gobject_enum,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
|
||||
PROPERTY_TYP_DATA_SUBTYPE (gobject_enum,
|
||||
.get_gtype = nm_ip_route_table_sync_mode_get_type,
|
||||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
|
|
@ -5502,6 +5510,14 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = {
|
|||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_METRIC, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC,
|
||||
.property_type = &_pt_gobject_int,
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE_SYNC,
|
||||
.property_type = &_pt_gobject_enum,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
|
||||
PROPERTY_TYP_DATA_SUBTYPE (gobject_enum,
|
||||
.get_gtype = nm_ip_route_table_sync_mode_get_type,
|
||||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("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.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC N_("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.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE_SYNC N_("The mode how to sync the routes per table. In general, when NetworkManager manages a device it will remove extraneous routes from the routing tables. The sync parameter specifies which tables are synced this way. That means, from which routing table NetworkManager will remove those unexpected, extraneous routes. A value of 1 (none) means that no route tables will not be synced and no routes are removed by NetworkManager. 2 (main) means that only the main table will be synced. 3 (full) will sync all the route tables, except the local table. A value of zero is the default value and allows to be overwritten via global configuration. In absence of global configuration, the default value is 2 (main).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("Array of IP routes.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: \"eui64\", or \"stable-privacy\". If the property is set to \"eui64\", the addresses will be generated using the interface tokens derived from hardware address. This makes the host part of the address to stay constant, making it possible to track host's presence when it changes networks. The address changes when the interface hardware is replaced. The value of \"stable-privacy\" enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217. This makes it impossible to use the address track host's presence, and makes the address stable when the network interface hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals enabling \"stable-privacy\". For keyfile plugin, the absence of the setting on disk means \"eui64\" so that the property doesn't change on upgrade from older versions. Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("Array of IP addresses.")
|
||||
|
|
@ -244,6 +245,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT N_("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.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC N_("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.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE_SYNC N_("The mode how to sync the routes per table. In general, when NetworkManager manages a device it will remove extraneous routes from the routing tables. The sync parameter specifies which tables are synced this way. That means, from which routing table NetworkManager will remove those unexpected, extraneous routes. A value of 1 (none) means that no route tables will not be synced and no routes are removed by NetworkManager. 2 (main) means that only the main table will be synced. 3 (full) will sync all the route tables, except the local table. A value of zero is the default value and allows to be overwritten via global configuration. In absence of global configuration, the default value is 2 (main).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TOKEN N_("Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MACSEC_ENCRYPT N_("Whether the transmitted traffic must be encrypted.")
|
||||
|
|
|
|||
|
|
@ -856,4 +856,25 @@ typedef enum { /*< skip >*/
|
|||
NM_ROLLBACK_RESULT_ERR_FAILED = 3,
|
||||
} NMRollbackResult;
|
||||
|
||||
/**
|
||||
* NMIPRouteTableSyncMode:
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT: the default value, meaning the value
|
||||
* is subject to global configuration default.
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_NONE: no route table is synced. This means,
|
||||
* NetworkManager will only add routes for a particular interface to the
|
||||
* routing tables, but not delete any routes.
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: only the main table is synced. For all
|
||||
* other tables, NM won't delete any extra routes.
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_FULL: NM will sync all tables, except the
|
||||
* local table (255).
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
typedef enum {
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT = 0,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_NONE = 1,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN = 2,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL = 3,
|
||||
} NMIPRouteTableSyncMode;
|
||||
|
||||
#endif /* __NM_DBUS_INTERFACE_H__ */
|
||||
|
|
|
|||
|
|
@ -1128,6 +1128,7 @@ nm_ip_route_get_attribute_names (NMIPRoute *route)
|
|||
while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
|
||||
g_ptr_array_add (names, g_strdup (key));
|
||||
}
|
||||
g_ptr_array_sort (names, nm_strcmp_p);
|
||||
g_ptr_array_add (names, NULL);
|
||||
|
||||
return (char **) g_ptr_array_free (names, FALSE);
|
||||
|
|
@ -1186,6 +1187,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
|
|||
&(NMVariantAttributeSpec) { name, type, v4, v6, str_type }
|
||||
|
||||
static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
|
||||
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ),
|
||||
|
|
@ -1377,6 +1379,7 @@ typedef struct {
|
|||
gboolean may_fail;
|
||||
gint dad_timeout;
|
||||
gint dhcp_timeout;
|
||||
int route_table_sync;
|
||||
} NMSettingIPConfigPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -1398,6 +1401,7 @@ enum {
|
|||
PROP_MAY_FAIL,
|
||||
PROP_DAD_TIMEOUT,
|
||||
PROP_DHCP_TIMEOUT,
|
||||
PROP_ROUTE_TABLE_SYNC,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -2249,6 +2253,24 @@ nm_setting_ip_config_get_route_metric (NMSettingIPConfig *setting)
|
|||
return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_metric;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ip_config_get_route_table_sync:
|
||||
* @setting: the #NMSettingIPConfig
|
||||
*
|
||||
* Returns the value contained in the #NMSettingIPConfig:route-table-sync
|
||||
* property.
|
||||
*
|
||||
* Returns: the configured route-table-sync mode.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
NMIPRouteTableSyncMode
|
||||
nm_setting_ip_config_get_route_table_sync (NMSettingIPConfig *setting)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
|
||||
|
||||
return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_table_sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ip_config_get_ignore_auto_routes:
|
||||
|
|
@ -2512,6 +2534,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
if ( priv->route_table_sync < NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT
|
||||
|| priv->route_table_sync > NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("invalid route table sync value %d"),
|
||||
priv->route_table_sync);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Validate routes */
|
||||
for (i = 0; i < priv->routes->len; i++) {
|
||||
NMIPRoute *route = (NMIPRoute *) priv->routes->pdata[i];
|
||||
|
|
@ -2715,6 +2748,9 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_DHCP_TIMEOUT:
|
||||
priv->dhcp_timeout = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_ROUTE_TABLE_SYNC:
|
||||
priv->route_table_sync = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -2784,6 +2820,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_DHCP_TIMEOUT:
|
||||
g_value_set_int (value, nm_setting_ip_config_get_dhcp_timeout (setting));
|
||||
break;
|
||||
case PROP_ROUTE_TABLE_SYNC:
|
||||
g_value_set_int (value, priv->route_table_sync);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -3126,6 +3165,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
|
|||
G_PARAM_CONSTRUCT |
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingIPConfig:dhcp-timeout:
|
||||
*
|
||||
|
|
@ -3138,4 +3178,27 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
|
|||
G_PARAM_READWRITE |
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingIPConfig:route-table-sync:
|
||||
*
|
||||
* The mode how to sync the routes per table. In general, when NetworkManager manages
|
||||
* a device it will remove extraneous routes from the routing tables. The
|
||||
* sync parameter specifies which tables are synced this way. That means, from
|
||||
* which routing table NetworkManager will remove those unexpected, extraneous routes.
|
||||
* A value of 1 (none) means that no route tables will not be synced and no routes
|
||||
* are removed by NetworkManager. 2 (main) means that only the main table will be synced.
|
||||
* 3 (full) will sync all the route tables, except the local table. A value of zero is
|
||||
* the default value and allows to be overwritten via global configuration. In absence of
|
||||
* global configuration, the default value is 2 (main).
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_ROUTE_TABLE_SYNC,
|
||||
g_param_spec_int (NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, "", "",
|
||||
G_MININT32, G_MAXINT32, NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT,
|
||||
G_PARAM_READWRITE |
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ gboolean nm_ip_route_attribute_validate (const char *name,
|
|||
gboolean *known,
|
||||
GError **error);
|
||||
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_SRC "src"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_FROM "from"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_TOS "tos"
|
||||
|
|
@ -171,6 +172,7 @@ gboolean nm_ip_route_attribute_validate (const char *name,
|
|||
#define NM_SETTING_IP_CONFIG_MAY_FAIL "may-fail"
|
||||
#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout"
|
||||
#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout"
|
||||
#define NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC "route-table-sync"
|
||||
|
||||
#define NM_SETTING_DNS_OPTION_DEBUG "debug"
|
||||
#define NM_SETTING_DNS_OPTION_NDOTS "ndots"
|
||||
|
|
@ -284,6 +286,9 @@ gint nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig
|
|||
NM_AVAILABLE_IN_1_2
|
||||
gint nm_setting_ip_config_get_dhcp_timeout (NMSettingIPConfig *setting);
|
||||
|
||||
NM_AVAILABLE_IN_1_10
|
||||
NMIPRouteTableSyncMode nm_setting_ip_config_get_route_table_sync (NMSettingIPConfig *setting);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_SETTING_IP_CONFIG_H */
|
||||
|
|
|
|||
|
|
@ -680,6 +680,15 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
|
|||
* ---end---
|
||||
*/
|
||||
|
||||
/* ---ifcfg-rh---
|
||||
* property: route-table-sync
|
||||
* variable: IPV4_ROUTE_TABLE_SYNC(+)
|
||||
* default: 0
|
||||
* description: IPV4_ROUTE_TABLE_SYNC controls how NetworkManager removes extraneous
|
||||
* routes from the routing tables.
|
||||
* ---end---
|
||||
*/
|
||||
|
||||
/* ---ifcfg-rh---
|
||||
* property: dns-priority
|
||||
* variable: IPV4_DNS_PRIORITY(+)
|
||||
|
|
|
|||
|
|
@ -652,6 +652,15 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
|
|||
* ---end---
|
||||
*/
|
||||
|
||||
/* ---ifcfg-rh---
|
||||
* property: route-table-sync
|
||||
* variable: IPV6_ROUTE_TABLE_SYNC(+)
|
||||
* default: 0
|
||||
* description: IPV6_ROUTE_TABLE_SYNC controls how NetworkManager removes extraneous
|
||||
* routes from the routing tables.
|
||||
* ---end---
|
||||
*/
|
||||
|
||||
/* ---ifcfg-rh---
|
||||
* property: dns-priority
|
||||
* variable: IPV6_DNS_PRIORITY(+)
|
||||
|
|
|
|||
|
|
@ -2479,6 +2479,7 @@ test_connection_diff_a_only (void)
|
|||
{ NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
|
|
|
|||
|
|
@ -1185,7 +1185,9 @@ global:
|
|||
nm_client_connectivity_check_set_enabled;
|
||||
nm_device_dummy_get_hw_address;
|
||||
nm_device_ppp_get_type;
|
||||
nm_ip_route_table_sync_mode_get_type;
|
||||
nm_setting_bridge_get_group_forward_mask;
|
||||
nm_setting_ip_config_get_route_table_sync;
|
||||
nm_setting_pppoe_get_parent;
|
||||
nm_setting_wireless_security_get_pmf;
|
||||
nm_setting_wireless_security_get_wps_method;
|
||||
|
|
|
|||
|
|
@ -682,6 +682,10 @@ ipv6.ip6-privacy=0
|
|||
<varlistentry>
|
||||
<term><varname>ipv4.route-metric</varname></term>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>ipv4.route-table-sync</varname></term>
|
||||
<listitem><para>If left unspecified, the default value is 2 (main).</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>ipv6.dhcp-timeout</varname></term>
|
||||
<listitem><para>If left unspecified, the default value for
|
||||
|
|
@ -696,6 +700,10 @@ ipv6.ip6-privacy=0
|
|||
<varlistentry>
|
||||
<term><varname>ipv6.route-metric</varname></term>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>ipv6.route-table-sync</varname></term>
|
||||
<listitem><para>If left unspecified, the default value is 2 (main).</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>vpn.timeout</varname></term>
|
||||
<listitem><para>If left unspecified, default value of 60 seconds is used.</para></listitem>
|
||||
|
|
|
|||
|
|
@ -871,22 +871,6 @@ nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
|
|||
return obj_new;
|
||||
}
|
||||
|
||||
const NMDedupMultiObj *
|
||||
nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj)
|
||||
{
|
||||
/* ref and unref accept const pointers. Objects is supposed to be shared
|
||||
* and kept immutable. Disallowing to take/retrun a reference to a const
|
||||
* NMPObject is cumbersome, because callers are precisely expected to
|
||||
* keep a ref on the otherwise immutable object. */
|
||||
|
||||
nm_assert (obj);
|
||||
nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
|
||||
nm_assert (obj->_ref_count > 0);
|
||||
|
||||
((NMDedupMultiObj *) obj)->_ref_count++;
|
||||
return obj;
|
||||
}
|
||||
|
||||
const NMDedupMultiObj *
|
||||
nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,7 +78,22 @@ struct _NMDedupMultiObjClass {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMDedupMultiObj *nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj);
|
||||
static inline const NMDedupMultiObj *
|
||||
nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj)
|
||||
{
|
||||
/* ref and unref accept const pointers. Objects is supposed to be shared
|
||||
* and kept immutable. Disallowing to take/retrun a reference to a const
|
||||
* NMPObject is cumbersome, because callers are precisely expected to
|
||||
* keep a ref on the otherwise immutable object. */
|
||||
|
||||
nm_assert (obj);
|
||||
nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
|
||||
nm_assert (obj->_ref_count > 0);
|
||||
|
||||
((NMDedupMultiObj *) obj)->_ref_count++;
|
||||
return obj;
|
||||
}
|
||||
|
||||
const NMDedupMultiObj *nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj);
|
||||
const NMDedupMultiObj *nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj);
|
||||
gboolean nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,8 @@ G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
|
|||
|
||||
static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
|
||||
|
||||
static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs);
|
||||
|
||||
static gboolean nm_device_set_ip4_config (NMDevice *self,
|
||||
NMIP4Config *config,
|
||||
gboolean commit,
|
||||
|
|
@ -1698,6 +1700,46 @@ out:
|
|||
return nm_utils_ip_route_metric_normalize (addr_family, route_metric);
|
||||
}
|
||||
|
||||
static NMIPRouteTableSyncMode
|
||||
get_route_table_sync (NMDevice *self, int addr_family)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingIPConfig *s_ip;
|
||||
NMIPRouteTableSyncMode route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT;
|
||||
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
if (connection) {
|
||||
if (addr_family == AF_INET)
|
||||
s_ip = nm_connection_get_setting_ip4_config (connection);
|
||||
else
|
||||
s_ip = nm_connection_get_setting_ip6_config (connection);
|
||||
|
||||
if (s_ip)
|
||||
route_table_sync = nm_setting_ip_config_get_route_table_sync (s_ip);
|
||||
}
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT) {
|
||||
gs_free char *value = NULL;
|
||||
|
||||
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
||||
addr_family == AF_INET
|
||||
? "ipv4.route-table-sync"
|
||||
: "ipv6.route-table-sync",
|
||||
self);
|
||||
route_table_sync = _nm_utils_ascii_str_to_int64 (value, 10,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT);
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT)
|
||||
route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN;
|
||||
}
|
||||
|
||||
return route_table_sync;
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nm_device_get_best_default_route (NMDevice *self,
|
||||
int addr_family)
|
||||
|
|
@ -5605,14 +5647,9 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||
init_ip4_config_dns_priority (self, composite);
|
||||
|
||||
if (commit) {
|
||||
if (priv->queued_ip4_config_id)
|
||||
update_ext_ip_config (self, AF_INET, FALSE, FALSE);
|
||||
ensure_con_ip4_config (self);
|
||||
if (priv->queued_ip4_config_id) {
|
||||
g_clear_object (&priv->ext_ip4_config);
|
||||
priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
nm_device_get_ip_ifindex (self),
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->dev_ip4_config) {
|
||||
|
|
@ -6324,18 +6361,9 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||
init_ip6_config_dns_priority (self, composite);
|
||||
|
||||
if (commit) {
|
||||
if (priv->queued_ip6_config_id)
|
||||
update_ext_ip_config (self, AF_INET6, FALSE, FALSE);
|
||||
ensure_con_ip6_config (self);
|
||||
if (priv->queued_ip6_config_id) {
|
||||
g_clear_object (&priv->ext_ip6_config);
|
||||
g_clear_object (&priv->ext_ip6_config_captured);
|
||||
priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
nm_device_get_ip_ifindex (self),
|
||||
FALSE,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||
if (priv->ext_ip6_config_captured)
|
||||
priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured);
|
||||
}
|
||||
}
|
||||
|
||||
/* Merge all the IP configs into the composite config */
|
||||
|
|
@ -9914,7 +9942,8 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||
if (commit && new_config) {
|
||||
_commit_mtu (self, new_config);
|
||||
success = nm_ip4_config_commit (new_config,
|
||||
nm_device_get_platform (self));
|
||||
nm_device_get_platform (self),
|
||||
get_route_table_sync (self, AF_INET));
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self),
|
||||
nm_ip4_config_get_ifindex (new_config),
|
||||
ip4_dev_route_blacklist);
|
||||
|
|
@ -10087,6 +10116,7 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
|
||||
success = nm_ip6_config_commit (new_config,
|
||||
nm_device_get_platform (self),
|
||||
get_route_table_sync (self, AF_INET6),
|
||||
&temporary_not_available);
|
||||
|
||||
if (!_rt6_temporary_not_available_set (self, temporary_not_available))
|
||||
|
|
@ -10745,175 +10775,153 @@ capture_lease_config (NMDevice *self,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_ip4_config (NMDevice *self, gboolean initial)
|
||||
static gboolean
|
||||
update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int ifindex;
|
||||
gboolean capture_resolv_conf;
|
||||
GSList *iter;
|
||||
|
||||
/* If a commit is scheduled, this function would potentially interfere with
|
||||
* it changing IP configurations before they are applied. Postpone the
|
||||
* update in such case.
|
||||
*/
|
||||
if ( !initial
|
||||
&& activation_source_is_scheduled (self,
|
||||
activate_stage5_ip4_config_result,
|
||||
AF_INET)) {
|
||||
priv->queued_ip4_config_pending = FALSE;
|
||||
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
|
||||
_LOGT (LOGD_DEVICE, "IP4 update was postponed");
|
||||
return;
|
||||
}
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (!ifindex)
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
capture_resolv_conf = initial
|
||||
&& nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ());
|
||||
|
||||
/* IPv4 */
|
||||
g_clear_object (&priv->ext_ip4_config);
|
||||
priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
ifindex,
|
||||
capture_resolv_conf);
|
||||
if (priv->ext_ip4_config) {
|
||||
if (initial) {
|
||||
g_clear_object (&priv->dev_ip4_config);
|
||||
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
|
||||
if (addr_family == AF_INET) {
|
||||
|
||||
g_clear_object (&priv->ext_ip4_config);
|
||||
priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
ifindex,
|
||||
capture_resolv_conf);
|
||||
if (priv->ext_ip4_config) {
|
||||
if (initial) {
|
||||
g_clear_object (&priv->dev_ip4_config);
|
||||
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
|
||||
}
|
||||
|
||||
if (intersect_configs) {
|
||||
/* This function was called upon external changes. Remove the configuration
|
||||
* (addresses,routes) that is no longer present externally from the internal
|
||||
* config. This way, we don't re-add addresses that were manually removed
|
||||
* by the user. */
|
||||
if (priv->con_ip4_config)
|
||||
nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config);
|
||||
if (priv->dev_ip4_config)
|
||||
nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config);
|
||||
if (priv->wwan_ip4_config)
|
||||
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
|
||||
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
||||
nm_ip4_config_intersect (iter->data, priv->ext_ip4_config);
|
||||
if ( priv->default_route4
|
||||
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_route4))
|
||||
nm_clear_nmp_object (&priv->default_route4);
|
||||
if ( priv->default_routegw4
|
||||
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_routegw4))
|
||||
nm_clear_nmp_object (&priv->default_routegw4);
|
||||
}
|
||||
|
||||
/* Remove parts from ext_ip4_config to only contain the information that
|
||||
* was configured externally -- we already have the same configuration from
|
||||
* internal origins. */
|
||||
if (priv->con_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config);
|
||||
if (priv->dev_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
|
||||
if (priv->wwan_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config);
|
||||
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, iter->data);
|
||||
if (priv->default_route4)
|
||||
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_route4);
|
||||
if (priv->default_routegw4)
|
||||
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_routegw4);
|
||||
}
|
||||
|
||||
/* FIXME: ext_ip4_config does not contain routes with source==RTPROT_KERNEL.
|
||||
* Hence, we will wrongly remove device-routes with metric=0 if they were added by
|
||||
* the user on purpose. This should be fixed by also tracking and exposing
|
||||
* kernel routes. */
|
||||
} else {
|
||||
nm_assert (addr_family == AF_INET6);
|
||||
|
||||
/* This function was called upon external changes. Remove the configuration
|
||||
* (addresses,routes) that is no longer present externally from the internal
|
||||
* config. This way, we don't re-add addresses that were manually removed
|
||||
* by the user. */
|
||||
if (priv->con_ip4_config)
|
||||
nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config);
|
||||
if (priv->dev_ip4_config)
|
||||
nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config);
|
||||
if (priv->wwan_ip4_config)
|
||||
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
|
||||
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
||||
nm_ip4_config_intersect (iter->data, priv->ext_ip4_config);
|
||||
if ( priv->default_route4
|
||||
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_route4))
|
||||
nm_clear_nmp_object (&priv->default_route4);
|
||||
if ( priv->default_routegw4
|
||||
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_routegw4))
|
||||
nm_clear_nmp_object (&priv->default_routegw4);
|
||||
g_clear_object (&priv->ext_ip6_config);
|
||||
g_clear_object (&priv->ext_ip6_config_captured);
|
||||
priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
ifindex,
|
||||
capture_resolv_conf,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||
if (priv->ext_ip6_config_captured) {
|
||||
|
||||
/* Remove parts from ext_ip4_config to only contain the information that
|
||||
* was configured externally -- we already have the same configuration from
|
||||
* internal origins. */
|
||||
if (priv->con_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config);
|
||||
if (priv->dev_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
|
||||
if (priv->wwan_ip4_config)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config);
|
||||
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
||||
nm_ip4_config_subtract (priv->ext_ip4_config, iter->data);
|
||||
if (priv->default_route4)
|
||||
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_route4);
|
||||
if (priv->default_routegw4)
|
||||
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_routegw4);
|
||||
priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured);
|
||||
|
||||
ip4_config_merge_and_apply (self, NULL, FALSE);
|
||||
if (intersect_configs) {
|
||||
/* This function was called upon external changes. Remove the configuration
|
||||
* (addresses,routes) that is no longer present externally from the internal
|
||||
* config. This way, we don't re-add addresses that were manually removed
|
||||
* by the user. */
|
||||
if (priv->con_ip6_config)
|
||||
nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config);
|
||||
if (priv->ac_ip6_config)
|
||||
nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config);
|
||||
if (priv->dhcp6.ip6_config)
|
||||
nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config);
|
||||
if (priv->wwan_ip6_config)
|
||||
nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config);
|
||||
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
||||
nm_ip6_config_intersect (iter->data, priv->ext_ip6_config);
|
||||
if ( priv->default_route6
|
||||
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_route6))
|
||||
nm_clear_nmp_object (&priv->default_route6);
|
||||
if ( priv->default_routegw6
|
||||
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_routegw6))
|
||||
nm_clear_nmp_object (&priv->default_routegw6);
|
||||
}
|
||||
|
||||
/* Remove parts from ext_ip6_config to only contain the information that
|
||||
* was configured externally -- we already have the same configuration from
|
||||
* internal origins. */
|
||||
if (priv->con_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config);
|
||||
if (priv->ac_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
|
||||
if (priv->dhcp6.ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config);
|
||||
if (priv->wwan_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config);
|
||||
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, iter->data);
|
||||
if (priv->default_route6)
|
||||
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_route6);
|
||||
if (priv->default_routegw6)
|
||||
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_routegw6);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_ip6_config (NMDevice *self, gboolean initial)
|
||||
update_ip_config (NMDevice *self, int addr_family, gboolean initial)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int ifindex;
|
||||
gboolean capture_resolv_conf;
|
||||
GSList *iter;
|
||||
|
||||
/* If a commit is scheduled, this function would potentially interfere with
|
||||
* it changing IP configurations before they are applied. Postpone the
|
||||
* update in such case.
|
||||
*/
|
||||
if ( !initial
|
||||
&& activation_source_is_scheduled (self,
|
||||
activate_stage5_ip6_config_commit,
|
||||
AF_INET6)) {
|
||||
priv->queued_ip6_config_pending = FALSE;
|
||||
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
||||
_LOGT (LOGD_DEVICE, "IP6 update was postponed");
|
||||
return;
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
if (update_ext_ip_config (self, addr_family, initial, TRUE)) {
|
||||
if (addr_family == AF_INET) {
|
||||
if (priv->ext_ip4_config)
|
||||
ip4_config_merge_and_apply (self, NULL, FALSE);
|
||||
} else {
|
||||
if (priv->ext_ip6_config_captured)
|
||||
ip6_config_merge_and_apply (self, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (!ifindex)
|
||||
return;
|
||||
|
||||
capture_resolv_conf = initial
|
||||
&& nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ());
|
||||
|
||||
/* IPv6 */
|
||||
g_clear_object (&priv->ext_ip6_config);
|
||||
g_clear_object (&priv->ext_ip6_config_captured);
|
||||
priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
|
||||
nm_device_get_platform (self),
|
||||
ifindex,
|
||||
capture_resolv_conf,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||
if (priv->ext_ip6_config_captured) {
|
||||
|
||||
priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured);
|
||||
|
||||
/* This function was called upon external changes. Remove the configuration
|
||||
* (addresses,routes) that is no longer present externally from the internal
|
||||
* config. This way, we don't re-add addresses that were manually removed
|
||||
* by the user. */
|
||||
if (priv->con_ip6_config)
|
||||
nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config);
|
||||
if (priv->ac_ip6_config)
|
||||
nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config);
|
||||
if (priv->dhcp6.ip6_config)
|
||||
nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config);
|
||||
if (priv->wwan_ip6_config)
|
||||
nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config);
|
||||
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
||||
nm_ip6_config_intersect (iter->data, priv->ext_ip6_config);
|
||||
if ( priv->default_route6
|
||||
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_route6))
|
||||
nm_clear_nmp_object (&priv->default_route6);
|
||||
if ( priv->default_routegw6
|
||||
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_routegw6))
|
||||
nm_clear_nmp_object (&priv->default_routegw6);
|
||||
|
||||
/* Remove parts from ext_ip6_config to only contain the information that
|
||||
* was configured externally -- we already have the same configuration from
|
||||
* internal origins. */
|
||||
if (priv->con_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config);
|
||||
if (priv->ac_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
|
||||
if (priv->dhcp6.ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config);
|
||||
if (priv->wwan_ip6_config)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config);
|
||||
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
||||
nm_ip6_config_subtract (priv->ext_ip6_config, iter->data);
|
||||
if (priv->default_route6)
|
||||
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_route6);
|
||||
if (priv->default_routegw6)
|
||||
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_routegw6);
|
||||
|
||||
ip6_config_merge_and_apply (self, FALSE);
|
||||
}
|
||||
|
||||
if ( priv->linklocal6_timeout_id
|
||||
if ( addr_family == AF_INET6
|
||||
&& priv->linklocal6_timeout_id
|
||||
&& priv->ext_ip6_config_captured
|
||||
&& nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) {
|
||||
/* linklocal6 is ready now, do the state transition... we are also
|
||||
|
|
@ -10926,8 +10934,8 @@ update_ip6_config (NMDevice *self, gboolean initial)
|
|||
void
|
||||
nm_device_capture_initial_config (NMDevice *self)
|
||||
{
|
||||
update_ip4_config (self, TRUE);
|
||||
update_ip6_config (self, TRUE);
|
||||
update_ip_config (self, AF_INET, TRUE);
|
||||
update_ip_config (self, AF_INET6, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -10947,7 +10955,19 @@ queued_ip4_config_change (gpointer user_data)
|
|||
return TRUE;
|
||||
|
||||
priv->queued_ip4_config_id = 0;
|
||||
update_ip4_config (self, FALSE);
|
||||
|
||||
/* If a commit is scheduled, this function would potentially interfere with
|
||||
* it changing IP configurations before they are applied. Postpone the
|
||||
* update in such case.
|
||||
*/
|
||||
if (activation_source_is_scheduled (self,
|
||||
activate_stage5_ip4_config_result,
|
||||
AF_INET)) {
|
||||
priv->queued_ip4_config_pending = FALSE;
|
||||
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
|
||||
_LOGT (LOGD_DEVICE, "IP4 update was postponed");
|
||||
} else
|
||||
update_ip_config (self, AF_INET, FALSE);
|
||||
|
||||
set_unmanaged_external_down (self, TRUE);
|
||||
|
||||
|
|
@ -10978,7 +10998,19 @@ queued_ip6_config_change (gpointer user_data)
|
|||
return TRUE;
|
||||
|
||||
priv->queued_ip6_config_id = 0;
|
||||
update_ip6_config (self, FALSE);
|
||||
|
||||
/* If a commit is scheduled, this function would potentially interfere with
|
||||
* it changing IP configurations before they are applied. Postpone the
|
||||
* update in such case.
|
||||
*/
|
||||
if (activation_source_is_scheduled (self,
|
||||
activate_stage5_ip6_config_commit,
|
||||
AF_INET6)) {
|
||||
priv->queued_ip6_config_pending = FALSE;
|
||||
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
||||
_LOGT (LOGD_DEVICE, "IP6 update was postponed");
|
||||
} else
|
||||
update_ip_config (self, AF_INET6, FALSE);
|
||||
|
||||
if (priv->state < NM_DEVICE_STATE_DEACTIVATING
|
||||
&& nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
|
||||
|
||||
#define NM_IP_ROUTE_TABLE_SYNC_MODE_ALL ((NMIPRouteTableSyncMode) -1)
|
||||
|
||||
#define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \
|
||||
static TYPE *singleton_instance
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
global_opt.priority_v4,
|
||||
&ip4_dev_route_blacklist);
|
||||
if (!nm_ip4_config_commit (existing,
|
||||
NM_PLATFORM_GET))
|
||||
NM_PLATFORM_GET,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN))
|
||||
_LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config");
|
||||
|
||||
nm_platform_ip4_dev_route_blacklist_set (NM_PLATFORM_GET,
|
||||
|
|
@ -228,7 +229,10 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||
nm_ip6_config_add_device_routes (existing,
|
||||
global_opt.priority_v6);
|
||||
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET, NULL))
|
||||
if (!nm_ip6_config_commit (existing,
|
||||
NM_PLATFORM_GET,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
|
||||
NULL))
|
||||
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -705,8 +705,6 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
priv->has_gateway = TRUE;
|
||||
}
|
||||
|
||||
if (route->table_coerced)
|
||||
continue;
|
||||
_add_route (self, plobj, NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -821,10 +819,12 @@ nm_ip4_config_add_device_routes (NMIP4Config *self,
|
|||
|
||||
gboolean
|
||||
nm_ip4_config_commit (const NMIP4Config *self,
|
||||
NMPlatform *platform)
|
||||
NMPlatform *platform,
|
||||
NMIPRouteTableSyncMode route_table_sync)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes_prune = NULL;
|
||||
int ifindex;
|
||||
gboolean success = TRUE;
|
||||
|
||||
|
|
@ -839,14 +839,18 @@ nm_ip4_config_commit (const NMIP4Config *self,
|
|||
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_routes (self),
|
||||
NULL, NULL);
|
||||
|
||||
routes_prune = nm_platform_ip_route_get_prune_list (platform,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
route_table_sync);
|
||||
|
||||
nm_platform_ip4_address_sync (platform, ifindex, addresses);
|
||||
|
||||
if (!nm_platform_ip_route_sync (platform,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
routes,
|
||||
nm_platform_lookup_predicate_routes_main,
|
||||
NULL,
|
||||
routes_prune,
|
||||
NULL))
|
||||
success = FALSE;
|
||||
|
||||
|
|
@ -864,6 +868,10 @@ merge_route_attributes (NMIPRoute *s_route, NMPlatformIP4Route *r)
|
|||
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||||
r->field = g_variant_get_ ## type (variant);
|
||||
|
||||
r->table_coerced = 254 /* RT_TABLE_MAIN */;
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table_coerced, UINT32, uint32);
|
||||
r->table_coerced = nm_platform_route_table_coerce (r->table_coerced);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, tos, BYTE, byte);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32);
|
||||
|
|
@ -3046,11 +3054,18 @@ out_addresses_cached:
|
|||
"metric",
|
||||
g_variant_new_uint32 (route->metric));
|
||||
|
||||
if (!nm_platform_route_table_is_main (route->table_coerced)) {
|
||||
g_variant_builder_add (&route_builder, "{sv}",
|
||||
"table",
|
||||
g_variant_new_uint32 (nm_platform_route_table_uncoerce (route->table_coerced, TRUE)));
|
||||
}
|
||||
|
||||
g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
|
||||
|
||||
/* legacy versions of nm_ip4_route_set_prefix() in libnm-util assert that the
|
||||
* plen is positive. Skip the default routes not to break older clients. */
|
||||
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
|
||||
if ( nm_platform_route_table_is_main (route->table_coerced)
|
||||
&& !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
|
||||
const guint32 dbus_route[4] = {
|
||||
route->network,
|
||||
route->plen,
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ void nm_ip4_config_add_device_routes (NMIP4Config *self,
|
|||
GPtrArray **out_ip4_dev_route_blacklist);
|
||||
|
||||
gboolean nm_ip4_config_commit (const NMIP4Config *self,
|
||||
NMPlatform *platform);
|
||||
NMPlatform *platform,
|
||||
NMIPRouteTableSyncMode route_table_sync);
|
||||
|
||||
void nm_ip4_config_merge_setting (NMIP4Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
|
||||
|
|
|
|||
|
|
@ -502,8 +502,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
has_gateway = TRUE;
|
||||
}
|
||||
|
||||
if (route->table_coerced)
|
||||
continue;
|
||||
_add_route (self, plobj, NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -604,10 +602,12 @@ nm_ip6_config_add_device_routes (NMIP6Config *self,
|
|||
gboolean
|
||||
nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
NMIPRouteTableSyncMode route_table_sync,
|
||||
GPtrArray **out_temporary_not_available)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes_prune = NULL;
|
||||
int ifindex;
|
||||
gboolean success = TRUE;
|
||||
|
||||
|
|
@ -618,16 +618,22 @@ nm_ip6_config_commit (const NMIP6Config *self,
|
|||
|
||||
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
|
||||
NULL, NULL);
|
||||
|
||||
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_routes (self),
|
||||
NULL, NULL);
|
||||
|
||||
routes_prune = nm_platform_ip_route_get_prune_list (platform,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
route_table_sync);
|
||||
|
||||
nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE);
|
||||
|
||||
if (!nm_platform_ip_route_sync (platform,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
routes,
|
||||
nm_platform_lookup_predicate_routes_main,
|
||||
NULL,
|
||||
routes_prune,
|
||||
out_temporary_not_available))
|
||||
success = FALSE;
|
||||
|
||||
|
|
@ -645,6 +651,10 @@ merge_route_attributes (NMIPRoute *s_route, NMPlatformIP6Route *r)
|
|||
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||||
r->field = g_variant_get_ ## type (variant);
|
||||
|
||||
r->table_coerced = 254 /* RT_TABLE_MAIN */;
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table_coerced, UINT32, uint32);
|
||||
r->table_coerced = nm_platform_route_table_coerce (r->table_coerced);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, window, UINT32, uint32);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, cwnd, UINT32, uint32);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, initcwnd, UINT32, uint32);
|
||||
|
|
@ -2708,11 +2718,18 @@ out_addresses_cached:
|
|||
"metric",
|
||||
g_variant_new_uint32 (route->metric));
|
||||
|
||||
if (!nm_platform_route_table_is_main (route->table_coerced)) {
|
||||
g_variant_builder_add (&route_builder, "{sv}",
|
||||
"table",
|
||||
g_variant_new_uint32 (nm_platform_route_table_uncoerce (route->table_coerced, TRUE)));
|
||||
}
|
||||
|
||||
g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
|
||||
|
||||
/* legacy versions of nm_ip6_route_set_prefix() in libnm-util assert that the
|
||||
* plen is positive. Skip the default routes not to break older clients. */
|
||||
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
|
||||
if ( nm_platform_route_table_is_main (route->table_coerced)
|
||||
&& !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
|
||||
g_variant_builder_add (&builder_legacy, "(@ayu@ayu)",
|
||||
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||
&route->network, 16, 1),
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ void nm_ip6_config_add_device_routes (NMIP6Config *self,
|
|||
|
||||
gboolean nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
NMIPRouteTableSyncMode route_table_sync,
|
||||
GPtrArray **out_temporary_not_available);
|
||||
void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self);
|
||||
|
|
|
|||
|
|
@ -1988,6 +1988,7 @@ static NMPObject *
|
|||
_new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
||||
{
|
||||
static struct nla_policy policy[RTA_MAX+1] = {
|
||||
[RTA_TABLE] = { .type = NLA_U32 },
|
||||
[RTA_IIF] = { .type = NLA_U32 },
|
||||
[RTA_OIF] = { .type = NLA_U32 },
|
||||
[RTA_PRIORITY] = { .type = NLA_U32 },
|
||||
|
|
@ -2010,7 +2011,6 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
} nh;
|
||||
guint32 mss;
|
||||
guint32 window = 0, cwnd = 0, initcwnd = 0, initrwnd = 0, mtu = 0, lock = 0;
|
||||
guint32 table;
|
||||
|
||||
if (!nlmsg_valid_hdr (nlh, sizeof (*rtm)))
|
||||
return NULL;
|
||||
|
|
@ -2030,10 +2030,6 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
table = tb[RTA_TABLE]
|
||||
? nla_get_u32 (tb[RTA_TABLE])
|
||||
: (guint32) rtm->rtm_table;
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
is_v4 = rtm->rtm_family == AF_INET;
|
||||
|
|
@ -2149,7 +2145,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
|
||||
obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
|
||||
obj->ip_route.table_coerced = nm_platform_route_table_coerce (table);
|
||||
obj->ip_route.table_coerced = nm_platform_route_table_coerce ( tb[RTA_TABLE]
|
||||
? nla_get_u32 (tb[RTA_TABLE])
|
||||
: (guint32) rtm->rtm_table);
|
||||
|
||||
obj->ip_route.ifindex = nh.ifindex;
|
||||
|
||||
if (_check_addr_or_errout (tb, RTA_DST, addr_len))
|
||||
|
|
@ -2594,7 +2593,7 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
gboolean is_v4 = klass->addr_family == AF_INET;
|
||||
const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj));
|
||||
const guint32 table = nm_platform_route_table_coerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced);
|
||||
const guint32 table = nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE);
|
||||
struct rtmsg rtmsg = {
|
||||
.rtm_family = klass->addr_family,
|
||||
.rtm_tos = is_v4
|
||||
|
|
|
|||
|
|
@ -2904,7 +2904,7 @@ nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
|
|||
{
|
||||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
return !obj->ip_route.table_coerced;
|
||||
return nm_platform_route_table_is_main (obj->ip_route.table_coerced);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -2913,7 +2913,7 @@ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *ob
|
|||
{
|
||||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
return !obj->ip_route.table_coerced
|
||||
return nm_platform_route_table_is_main (obj->ip_route.table_coerced)
|
||||
&& obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
|
||||
}
|
||||
|
||||
|
|
@ -3589,6 +3589,61 @@ _err_inval_due_to_ipv6_tentative_pref_src (NMPlatform *self, const NMPObject *ob
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
nm_platform_ip_route_get_prune_list (NMPlatform *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
NMIPRouteTableSyncMode route_table_sync)
|
||||
{
|
||||
NMPLookup lookup;
|
||||
GPtrArray *routes_prune;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
CList *iter;
|
||||
|
||||
nm_assert (NM_IS_PLATFORM (self));
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
nm_assert (NM_IN_SET (route_table_sync, NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL));
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE)
|
||||
return NULL;
|
||||
|
||||
nmp_lookup_init_addrroute (&lookup,
|
||||
addr_family == AF_INET
|
||||
? NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
: NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
ifindex);
|
||||
head_entry = nm_platform_lookup (self, &lookup);
|
||||
if (!head_entry)
|
||||
return NULL;
|
||||
|
||||
routes_prune = g_ptr_array_new_full (head_entry->len,
|
||||
(GDestroyNotify) nm_dedup_multi_obj_unref);
|
||||
|
||||
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
||||
const NMPObject *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) {
|
||||
if (nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE) == (RT_TABLE_LOCAL))
|
||||
continue;
|
||||
} else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) {
|
||||
if (!nm_platform_route_table_is_main (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced))
|
||||
continue;
|
||||
} else
|
||||
nm_assert (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
|
||||
g_ptr_array_add (routes_prune, (gpointer) nmp_object_ref (obj));
|
||||
}
|
||||
|
||||
if (routes_prune->len == 0) {
|
||||
g_ptr_array_unref (routes_prune);
|
||||
return NULL;
|
||||
}
|
||||
return routes_prune;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_ip_route_sync:
|
||||
* @self: the #NMPlatform instance.
|
||||
|
|
@ -3596,12 +3651,11 @@ _err_inval_due_to_ipv6_tentative_pref_src (NMPlatform *self, const NMPObject *ob
|
|||
* @ifindex: the @ifindex for which the routes are to be added.
|
||||
* @routes: (allow-none): a list of routes to configure. Must contain
|
||||
* NMPObject instances of routes, according to @addr_family.
|
||||
* @kernel_delete_predicate: (allow-none): if not %NULL, previously
|
||||
* existing routes already configured will only be deleted if the
|
||||
* predicate returns TRUE. This allows to preserve/ignore some
|
||||
* routes. For example by passing @nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
* routes with "proto kernel" will be left untouched.
|
||||
* @kernel_delete_userdata: user data for @kernel_delete_predicate.
|
||||
* @routes_prune: (allow-none): the list of routes to delete.
|
||||
* If platform has such a route configured, it will be deleted
|
||||
* at the end of the operation. Note that if @routes contains
|
||||
* the same route, then it will not be deleted. @routes overrules
|
||||
* @routes_prune list.
|
||||
* @out_temporary_not_available: (allow-none): (out): routes that could
|
||||
* currently not be synced. The caller shall keep them and try later again.
|
||||
*
|
||||
|
|
@ -3612,14 +3666,12 @@ nm_platform_ip_route_sync (NMPlatform *self,
|
|||
int addr_family,
|
||||
int ifindex,
|
||||
GPtrArray *routes,
|
||||
NMPObjectPredicateFunc kernel_delete_predicate,
|
||||
gpointer kernel_delete_userdata,
|
||||
GPtrArray *routes_prune,
|
||||
GPtrArray **out_temporary_not_available)
|
||||
{
|
||||
const NMPlatformVTableRoute *vt;
|
||||
gs_unref_ptrarray GPtrArray *plat_routes = NULL;
|
||||
gs_unref_hashtable GHashTable *routes_idx = NULL;
|
||||
const NMPObject *plat_o;
|
||||
const NMPObject *conf_o;
|
||||
const NMDedupMultiEntry *plat_entry;
|
||||
guint i;
|
||||
|
|
@ -3669,6 +3721,8 @@ nm_platform_ip_route_sync (NMPlatform *self,
|
|||
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
conf_o);
|
||||
if (plat_entry) {
|
||||
const NMPObject *plat_o;
|
||||
|
||||
plat_o = plat_entry->obj;
|
||||
|
||||
if (vt->route_cmp (NMP_OBJECT_CAST_IPX_ROUTE (conf_o),
|
||||
|
|
@ -3741,21 +3795,26 @@ nm_platform_ip_route_sync (NMPlatform *self,
|
|||
}
|
||||
}
|
||||
|
||||
plat_routes = nm_platform_lookup_addrroute_clone (self,
|
||||
vt->obj_type,
|
||||
ifindex,
|
||||
kernel_delete_predicate,
|
||||
kernel_delete_userdata);
|
||||
if (routes_prune) {
|
||||
for (i = 0; i < routes_prune->len; i++) {
|
||||
const NMPObject *prune_o;
|
||||
|
||||
if (plat_routes) {
|
||||
for (i = 0; i < plat_routes->len; i++) {
|
||||
plat_o = plat_routes->pdata[i];
|
||||
prune_o = routes_prune->pdata[i];
|
||||
|
||||
if ( !routes_idx
|
||||
|| !g_hash_table_lookup (routes_idx, plat_o)) {
|
||||
if (!nm_platform_ip_route_delete (self, plat_o)) {
|
||||
/* ignore error... */
|
||||
}
|
||||
nm_assert ( (addr_family == AF_INET && NMP_OBJECT_GET_TYPE (prune_o) == NMP_OBJECT_TYPE_IP4_ROUTE)
|
||||
|| (addr_family == AF_INET6 && NMP_OBJECT_GET_TYPE (prune_o) == NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
|
||||
if ( routes_idx
|
||||
&& g_hash_table_lookup (routes_idx, prune_o))
|
||||
continue;
|
||||
|
||||
if (!nm_platform_lookup_entry (self,
|
||||
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
prune_o))
|
||||
continue;
|
||||
|
||||
if (!nm_platform_ip_route_delete (self, prune_o)) {
|
||||
/* ignore error... */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3776,10 +3835,24 @@ nm_platform_ip_route_flush (NMPlatform *self,
|
|||
AF_INET,
|
||||
AF_INET6));
|
||||
|
||||
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET))
|
||||
success &= nm_platform_ip_route_sync (self, AF_INET, ifindex, NULL, NULL, NULL, NULL);
|
||||
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6))
|
||||
success &= nm_platform_ip_route_sync (self, AF_INET6, ifindex, NULL, NULL, NULL, NULL);
|
||||
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) {
|
||||
gs_unref_ptrarray GPtrArray *routes_prune = NULL;
|
||||
|
||||
routes_prune = nm_platform_ip_route_get_prune_list (self,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
success &= nm_platform_ip_route_sync (self, AF_INET, ifindex, NULL, routes_prune, NULL);
|
||||
}
|
||||
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) {
|
||||
gs_unref_ptrarray GPtrArray *routes_prune = NULL;
|
||||
|
||||
routes_prune = nm_platform_ip_route_get_prune_list (self,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
success &= nm_platform_ip_route_sync (self, AF_INET6, ifindex, NULL, routes_prune, NULL);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -3828,12 +3901,14 @@ nm_platform_ip_route_normalize (int addr_family,
|
|||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
r4 = (NMPlatformIP4Route *) route;
|
||||
r4->table_coerced = nm_platform_route_table_coerce (nm_platform_route_table_uncoerce (r4->table_coerced, TRUE));
|
||||
r4->network = nm_utils_ip4_address_clear_host_address (r4->network, r4->plen);
|
||||
r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r4->rt_source);
|
||||
r4->scope_inv = _ip_route_scope_inv_get_normalized (r4);
|
||||
break;
|
||||
case AF_INET6:
|
||||
r6 = (NMPlatformIP6Route *) route;
|
||||
r6->table_coerced = nm_platform_route_table_coerce (nm_platform_route_table_uncoerce (r6->table_coerced, TRUE));
|
||||
nm_utils_ip6_address_clear_host_address (&r6->network, &r6->network, r6->plen);
|
||||
r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r6->rt_source),
|
||||
r6->metric = nm_utils_ip6_route_metric_normalize (r6->metric);
|
||||
|
|
@ -3911,8 +3986,9 @@ nm_platform_ip_route_delete (NMPlatform *self,
|
|||
{
|
||||
_CHECK_SELF (self, klass, FALSE);
|
||||
|
||||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
if (!NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE))
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
_LOGD ("route: delete IPv%c route %s",
|
||||
NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE ? '4' : '6',
|
||||
|
|
@ -4942,7 +5018,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
|
|||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"",
|
||||
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_coerce (route->table_coerced)) : "",
|
||||
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "",
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway,
|
||||
|
|
@ -5015,7 +5091,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
|
|||
"%s" /* initrwnd */
|
||||
"%s" /* mtu */
|
||||
"",
|
||||
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_coerce (route->table_coerced)) : "",
|
||||
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "",
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway,
|
||||
|
|
@ -5458,7 +5534,7 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
h = NM_HASH_COMBINE (h, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE));
|
||||
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
|
||||
h = NM_HASH_COMBINE (h, obj->plen);
|
||||
h = NM_HASH_COMBINE (h, obj->metric);
|
||||
|
|
@ -5484,7 +5560,10 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
|
|||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
h = NM_HASH_COMBINE (h, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE));
|
||||
else
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
h = NM_HASH_COMBINE (h, obj->ifindex);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
|
||||
|
|
@ -5527,7 +5606,8 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce (b->table_coerced, TRUE));
|
||||
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen));
|
||||
NM_CMP_FIELD (a, b, plen);
|
||||
NM_CMP_FIELD (a, b, metric);
|
||||
|
|
@ -5555,7 +5635,11 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
|
|||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce (b->table_coerced, TRUE));
|
||||
} else
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
NM_CMP_FIELD (a, b, ifindex);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen));
|
||||
|
|
@ -5601,7 +5685,7 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
h = NM_HASH_COMBINE (h, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE));
|
||||
h = NM_HASH_COMBINE_IN6ADDR_PREFIX (h, &obj->network, obj->plen);
|
||||
h = NM_HASH_COMBINE (h, obj->plen);
|
||||
h = NM_HASH_COMBINE (h, nm_utils_ip6_route_metric_normalize (obj->metric));
|
||||
|
|
@ -5614,7 +5698,10 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
|
|||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
h = NM_HASH_COMBINE (h, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE));
|
||||
else
|
||||
h = NM_HASH_COMBINE (h, obj->table_coerced);
|
||||
h = NM_HASH_COMBINE (h, obj->ifindex);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
h = NM_HASH_COMBINE_IN6ADDR_PREFIX (h, &obj->network, obj->plen);
|
||||
|
|
@ -5661,7 +5748,8 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
|
|||
switch (cmp_type) {
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce (b->table_coerced, TRUE));
|
||||
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen));
|
||||
NM_CMP_FIELD (a, b, plen);
|
||||
NM_CMP_DIRECT (nm_utils_ip6_route_metric_normalize (a->metric), nm_utils_ip6_route_metric_normalize (b->metric));
|
||||
|
|
@ -5674,7 +5762,11 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
|
|||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE),
|
||||
nm_platform_route_table_uncoerce (b->table_coerced, TRUE));
|
||||
} else
|
||||
NM_CMP_FIELD (a, b, table_coerced);
|
||||
NM_CMP_FIELD (a, b, ifindex);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen));
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ typedef union {
|
|||
*
|
||||
* This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and
|
||||
* zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main
|
||||
* table. Use nm_platform_route_table_coerce(). */ \
|
||||
* table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \
|
||||
guint32 table_coerced; \
|
||||
\
|
||||
/*end*/
|
||||
|
|
@ -860,15 +860,21 @@ NMPlatform *nm_platform_get (void);
|
|||
|
||||
/**
|
||||
* nm_platform_route_table_coerce:
|
||||
* @table: the route table, either its original value, or its coerced.
|
||||
* @table: the route table, in its original value as received
|
||||
* from rtm_table/RTA_TABLE.
|
||||
*
|
||||
* Returns: returns the coerced table id. If the table id is like
|
||||
* RTA_TABLE, it returns a value for NMPlatformIPRoute.table_coerced
|
||||
* and vice versa.
|
||||
* Returns: returns the coerced table id, that can be stored in
|
||||
* NMPlatformIPRoute.table_coerced.
|
||||
*/
|
||||
static inline guint32
|
||||
nm_platform_route_table_coerce (guint32 table)
|
||||
{
|
||||
/* For kernel, the default table is RT_TABLE_MAIN (254).
|
||||
* We want that in NMPlatformIPRoute.table_coerced a numeric
|
||||
* zero is the default. Hence, @table_coerced swaps the
|
||||
* value 0 and 254. Use nm_platform_route_table_coerce()
|
||||
* and nm_platform_route_table_uncoerce() to convert between
|
||||
* the two domains. */
|
||||
switch (table) {
|
||||
case 0 /* RT_TABLE_UNSPEC */:
|
||||
return 254;
|
||||
|
|
@ -879,6 +885,45 @@ nm_platform_route_table_coerce (guint32 table)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_route_table_uncoerce:
|
||||
* @table: the route table, in its coerced value
|
||||
* @normalize: whether to normalize RT_TABLE_UNSPEC to
|
||||
* RT_TABLE_MAIN. For kernel, routes with a table id
|
||||
* RT_TABLE_UNSPEC do not exist and are treated like
|
||||
* RT_TABLE_MAIN.
|
||||
*
|
||||
* Returns: reverts the coerced table ID in NMPlatformIPRoute.table_coerced
|
||||
* to the original value as kernel understands it.
|
||||
*/
|
||||
static inline guint32
|
||||
nm_platform_route_table_uncoerce (guint32 table_coerced, gboolean normalize)
|
||||
{
|
||||
/* this undoes nm_platform_route_table_coerce(). */
|
||||
switch (table_coerced) {
|
||||
case 0 /* RT_TABLE_UNSPEC */:
|
||||
return 254;
|
||||
case 254 /* RT_TABLE_MAIN */:
|
||||
return normalize ? 254 : 0;
|
||||
default:
|
||||
return table_coerced;
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_platform_route_table_is_main (guint32 table)
|
||||
{
|
||||
/* same as
|
||||
* nm_platform_route_table_uncoerce (table, TRUE) == RT_TABLE_MAIN
|
||||
* and
|
||||
* nm_platform_route_table_uncoerce (nm_platform_route_table_coerce (table), TRUE) == RT_TABLE_MAIN
|
||||
*
|
||||
* That is, the function operates the same on @table and its coerced
|
||||
* form.
|
||||
*/
|
||||
return table == 0 || table == 254;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_route_scope_inv:
|
||||
* @scope: the route scope, either its original value, or its inverse.
|
||||
|
|
@ -1172,13 +1217,18 @@ NMPlatformError nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags,
|
|||
|
||||
gboolean nm_platform_ip_route_delete (NMPlatform *self, const NMPObject *route);
|
||||
|
||||
GPtrArray *nm_platform_ip_route_get_prune_list (NMPlatform *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
NMIPRouteTableSyncMode route_table_sync);
|
||||
|
||||
gboolean nm_platform_ip_route_sync (NMPlatform *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
GPtrArray *routes,
|
||||
NMPObjectPredicateFunc kernel_delete_predicate,
|
||||
gpointer kernel_delete_userdata,
|
||||
GPtrArray *routes_prune,
|
||||
GPtrArray **out_temporary_not_available);
|
||||
|
||||
gboolean nm_platform_ip_route_flush (NMPlatform *self,
|
||||
int addr_family,
|
||||
int ifindex);
|
||||
|
|
|
|||
|
|
@ -468,6 +468,7 @@ typedef struct {
|
|||
|
||||
enum {
|
||||
/* route attributes */
|
||||
PARSE_LINE_ATTR_ROUTE_TABLE,
|
||||
PARSE_LINE_ATTR_ROUTE_SRC,
|
||||
PARSE_LINE_ATTR_ROUTE_FROM,
|
||||
PARSE_LINE_ATTR_ROUTE_TOS,
|
||||
|
|
@ -530,6 +531,8 @@ parse_route_line (const char *line,
|
|||
char buf1[256];
|
||||
char buf2[256];
|
||||
ParseLineInfo infos[] = {
|
||||
[PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
||||
.type = PARSE_LINE_TYPE_UINT32, },
|
||||
[PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC,
|
||||
.type = PARSE_LINE_TYPE_ADDR, },
|
||||
[PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM,
|
||||
|
|
@ -816,6 +819,11 @@ next:
|
|||
info->key,
|
||||
g_variant_new_byte (info->v.uint8));
|
||||
break;
|
||||
case PARSE_LINE_TYPE_UINT32:
|
||||
nm_ip_route_set_attribute (route,
|
||||
info->key,
|
||||
g_variant_new_uint32 (info->v.uint32));
|
||||
break;
|
||||
case PARSE_LINE_TYPE_UINT32_WITH_LOCK:
|
||||
if (info->v.uint32_with_lock.lock) {
|
||||
nm_ip_route_set_attribute (route,
|
||||
|
|
@ -1277,6 +1285,8 @@ make_ip4_setting (shvarFile *ifcfg,
|
|||
NM_SETTING_IP_CONFIG_MAY_FAIL, !svGetValueBoolean (ifcfg, "IPV4_FAILURE_FATAL", FALSE),
|
||||
NM_SETTING_IP_CONFIG_ROUTE_METRIC, svGetValueInt64 (ifcfg, "IPV4_ROUTE_METRIC", 10,
|
||||
-1, G_MAXUINT32, -1),
|
||||
NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, (int) svGetValueInt64 (ifcfg, "IPV4_ROUTE_TABLE_SYNC", 10,
|
||||
G_MININT32, G_MAXINT32, NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT),
|
||||
NULL);
|
||||
|
||||
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0)
|
||||
|
|
@ -1707,6 +1717,8 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
NM_SETTING_IP_CONFIG_MAY_FAIL, !svGetValueBoolean (ifcfg, "IPV6_FAILURE_FATAL", FALSE),
|
||||
NM_SETTING_IP_CONFIG_ROUTE_METRIC, svGetValueInt64 (ifcfg, "IPV6_ROUTE_METRIC", 10,
|
||||
-1, G_MAXUINT32, -1),
|
||||
NM_SETTING_IP_CONFIG_ROUTE_TABLE_SYNC, (int) svGetValueInt64 (ifcfg, "IPV6_ROUTE_TABLE_SYNC", 10,
|
||||
G_MININT32, G_MAXINT32, NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT),
|
||||
NM_SETTING_IP6_CONFIG_IP6_PRIVACY, ip6_privacy_val,
|
||||
NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1868,6 +1868,8 @@ get_route_attributes_string (NMIPRoute *route, int family)
|
|||
}
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) {
|
||||
g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr));
|
||||
} else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) {
|
||||
g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_uint32 (attr));
|
||||
} else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC)
|
||||
|| nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) {
|
||||
char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from";
|
||||
|
|
@ -2021,6 +2023,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
gint j;
|
||||
guint i, num, n;
|
||||
gint64 route_metric;
|
||||
NMIPRouteTableSyncMode route_table_sync;
|
||||
gint priority;
|
||||
int timeout;
|
||||
GString *searches;
|
||||
|
|
@ -2215,6 +2218,12 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svSetValueStr (ifcfg, "IPV4_ROUTE_METRIC", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
route_table_sync = nm_setting_ip_config_get_route_table_sync (s_ip4);
|
||||
svSetValueInt64_cond (ifcfg,
|
||||
"IPV4_ROUTE_TABLE_SYNC",
|
||||
route_table_sync != NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT,
|
||||
route_table_sync);
|
||||
|
||||
/* Static routes - route-<name> file */
|
||||
route_path = utils_get_route_path (svFileGetName (ifcfg));
|
||||
if (!route_path) {
|
||||
|
|
@ -2482,6 +2491,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
NMIPAddress *addr;
|
||||
const char *dns;
|
||||
gint64 route_metric;
|
||||
NMIPRouteTableSyncMode route_table_sync;
|
||||
GString *ip_str1, *ip_str2, *ip_ptr;
|
||||
char *route6_path;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
|
|
@ -2614,6 +2624,12 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svSetValueStr (ifcfg, "IPV6_ROUTE_METRIC", tmp);
|
||||
g_free (tmp);
|
||||
|
||||
route_table_sync = nm_setting_ip_config_get_route_table_sync (s_ip6);
|
||||
svSetValueInt64_cond (ifcfg,
|
||||
"IPV6_ROUTE_TABLE_SYNC",
|
||||
route_table_sync != NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT,
|
||||
route_table_sync);
|
||||
|
||||
/* IPv6 Privacy Extensions */
|
||||
svUnsetValue (ifcfg, "IPV6_PRIVACY");
|
||||
svUnsetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP");
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ static void get_secrets (NMVpnConnection *self,
|
|||
SecretsReq secrets_idx,
|
||||
const char **hints);
|
||||
|
||||
static NMIPRouteTableSyncMode get_route_table_sync (NMVpnConnection *self, int addr_family);
|
||||
|
||||
static void plugin_interactive_secrets_required (NMVpnConnection *self,
|
||||
const char *message,
|
||||
const char **secrets);
|
||||
|
|
@ -1149,7 +1151,8 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
|
|||
if (priv->ip4_config) {
|
||||
nm_assert (priv->ip_ifindex == nm_ip4_config_get_ifindex (priv->ip4_config));
|
||||
if (!nm_ip4_config_commit (priv->ip4_config,
|
||||
nm_netns_get_platform (priv->netns)))
|
||||
nm_netns_get_platform (priv->netns),
|
||||
get_route_table_sync (self, AF_INET)))
|
||||
return FALSE;
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_netns_get_platform (priv->netns),
|
||||
priv->ip_ifindex,
|
||||
|
|
@ -1160,6 +1163,7 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
|
|||
nm_assert (priv->ip_ifindex == nm_ip6_config_get_ifindex (priv->ip6_config));
|
||||
if (!nm_ip6_config_commit (priv->ip6_config,
|
||||
nm_netns_get_platform (priv->netns),
|
||||
get_route_table_sync (self, AF_INET6),
|
||||
NULL))
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1431,6 +1435,32 @@ nm_vpn_connection_get_ip6_route_metric (NMVpnConnection *self)
|
|||
return (route_metric >= 0) ? route_metric : NM_VPN_ROUTE_METRIC_DEFAULT;
|
||||
}
|
||||
|
||||
static NMIPRouteTableSyncMode
|
||||
get_route_table_sync (NMVpnConnection *self, int addr_family)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingIPConfig *s_ip;
|
||||
NMIPRouteTableSyncMode route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT;
|
||||
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
connection = _get_applied_connection (self);
|
||||
if (connection) {
|
||||
if (addr_family == AF_INET)
|
||||
s_ip = nm_connection_get_setting_ip4_config (connection);
|
||||
else
|
||||
s_ip = nm_connection_get_setting_ip6_config (connection);
|
||||
|
||||
if (s_ip)
|
||||
route_table_sync = nm_setting_ip_config_get_route_table_sync (s_ip);
|
||||
}
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_DEFAULT)
|
||||
route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN;
|
||||
|
||||
return route_table_sync;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue