core: merge branch 'th/bgo740443_device_ip_changes'
This branch brings three major changes: - when routes or addresses are removed externally, remove those entiries also from what we want to configure on the interface. That way, on the next commit, we will not re-add those externally removed entries. -- at least not unless the entries reappear due to an event such as a new DHCP lease. - the combined NMIPConfig object of a device which is also exposed via DBUS, will no longer contain those externally removed entries. The IP config really shows what is actually configured. - for default-routes, no longer enforce the default route even on managed devices. Only during commit phases, we might re-add/ remove a default route from a device, otherwise, pickup the default route (or its absence) as actually configured. https://bugzilla.gnome.org/show_bug.cgi?id=740443
This commit is contained in:
@@ -239,9 +239,9 @@ typedef struct {
|
|||||||
/* IP4 configuration info */
|
/* IP4 configuration info */
|
||||||
NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */
|
NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */
|
||||||
IpState ip4_state;
|
IpState ip4_state;
|
||||||
|
NMIP4Config * con_ip4_config; /* config from the setting */
|
||||||
NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
|
NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
|
||||||
NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
|
NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
|
||||||
gboolean ext_ip4_config_had_any_addresses;
|
|
||||||
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
|
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
|
||||||
struct {
|
struct {
|
||||||
gboolean v4_has;
|
gboolean v4_has;
|
||||||
@@ -276,10 +276,10 @@ typedef struct {
|
|||||||
/* IP6 configuration info */
|
/* IP6 configuration info */
|
||||||
NMIP6Config * ip6_config;
|
NMIP6Config * ip6_config;
|
||||||
IpState ip6_state;
|
IpState ip6_state;
|
||||||
|
NMIP6Config * con_ip6_config; /* config from the setting */
|
||||||
NMIP6Config * vpn6_config; /* routes added by a VPN which uses this device */
|
NMIP6Config * vpn6_config; /* routes added by a VPN which uses this device */
|
||||||
NMIP6Config * wwan_ip6_config;
|
NMIP6Config * wwan_ip6_config;
|
||||||
NMIP6Config * ext_ip6_config; /* Stuff added outside NM */
|
NMIP6Config * ext_ip6_config; /* Stuff added outside NM */
|
||||||
gboolean ext_ip6_config_had_any_addresses;
|
|
||||||
gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */
|
gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */
|
||||||
|
|
||||||
NMRDisc * rdisc;
|
NMRDisc * rdisc;
|
||||||
@@ -2835,6 +2835,43 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_con_ipx_config (NMDevice *self)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
NMConnection *connection;
|
||||||
|
|
||||||
|
g_assert (!!priv->con_ip4_config == !!priv->con_ip6_config);
|
||||||
|
|
||||||
|
if (priv->con_ip4_config)
|
||||||
|
return;
|
||||||
|
|
||||||
|
connection = nm_device_get_connection (self);
|
||||||
|
if (!connection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->con_ip4_config = nm_ip4_config_new ();
|
||||||
|
priv->con_ip6_config = nm_ip6_config_new ();
|
||||||
|
|
||||||
|
nm_ip4_config_merge_setting (priv->con_ip4_config,
|
||||||
|
nm_connection_get_setting_ip4_config (connection),
|
||||||
|
nm_device_get_ip4_route_metric (self));
|
||||||
|
nm_ip6_config_merge_setting (priv->con_ip6_config,
|
||||||
|
nm_connection_get_setting_ip6_config (connection),
|
||||||
|
nm_device_get_ip6_route_metric (self));
|
||||||
|
|
||||||
|
if (nm_device_uses_assumed_connection (self)) {
|
||||||
|
/* For assumed connections ignore all addresses and routes. */
|
||||||
|
nm_ip4_config_reset_addresses (priv->con_ip4_config);
|
||||||
|
nm_ip4_config_reset_routes (priv->con_ip4_config);
|
||||||
|
|
||||||
|
nm_ip6_config_reset_addresses (priv->con_ip6_config);
|
||||||
|
nm_ip6_config_reset_routes (priv->con_ip6_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************/
|
/*********************************************/
|
||||||
/* DHCPv4 stuff */
|
/* DHCPv4 stuff */
|
||||||
|
|
||||||
@@ -2874,7 +2911,9 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
NMIP4Config *composite;
|
NMIP4Config *composite;
|
||||||
|
gboolean has_direct_route;
|
||||||
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
|
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
|
||||||
|
guint32 gateway;
|
||||||
|
|
||||||
/* Merge all the configs into the composite config */
|
/* Merge all the configs into the composite config */
|
||||||
if (config) {
|
if (config) {
|
||||||
@@ -2883,6 +2922,9 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
composite = nm_ip4_config_new ();
|
composite = nm_ip4_config_new ();
|
||||||
|
|
||||||
|
ensure_con_ipx_config (self);
|
||||||
|
|
||||||
if (priv->dev_ip4_config)
|
if (priv->dev_ip4_config)
|
||||||
nm_ip4_config_merge (composite, priv->dev_ip4_config);
|
nm_ip4_config_merge (composite, priv->dev_ip4_config);
|
||||||
if (priv->vpn4_config)
|
if (priv->vpn4_config)
|
||||||
@@ -2896,73 +2938,87 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||||||
if (priv->wwan_ip4_config)
|
if (priv->wwan_ip4_config)
|
||||||
nm_ip4_config_merge (composite, priv->wwan_ip4_config);
|
nm_ip4_config_merge (composite, priv->wwan_ip4_config);
|
||||||
|
|
||||||
/* Merge user overrides into the composite config. Generated+assumed
|
/* Merge user overrides into the composite config. For assumed connection,
|
||||||
* connections come from the system not the user and merging them would
|
* con_ip4_config is empty. */
|
||||||
* be redundant, so don't bother.
|
if (priv->con_ip4_config)
|
||||||
*/
|
nm_ip4_config_merge (composite, priv->con_ip4_config);
|
||||||
|
|
||||||
connection = nm_device_get_connection (self);
|
connection = nm_device_get_connection (self);
|
||||||
|
|
||||||
|
/* Add the default route.
|
||||||
|
*
|
||||||
|
* We keep track of the default route of a device in a private field.
|
||||||
|
* NMDevice needs to know the default route at this point, because the gateway
|
||||||
|
* might require a direct route (see below).
|
||||||
|
*
|
||||||
|
* But also, we don't want to add the default route to priv->ip4_config,
|
||||||
|
* because the default route from the setting might not be the same that
|
||||||
|
* NMDefaultRouteManager eventually configures (because the it might
|
||||||
|
* tweak the effective metric).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* unless we come to a different conclusion below, we have no default route and
|
||||||
|
* the route is assumed. */
|
||||||
priv->default_route.v4_has = FALSE;
|
priv->default_route.v4_has = FALSE;
|
||||||
priv->default_route.v4_is_assumed = TRUE;
|
priv->default_route.v4_is_assumed = TRUE;
|
||||||
if (connection) {
|
|
||||||
gboolean assumed = nm_device_uses_assumed_connection (self);
|
|
||||||
NMPlatformIP4Route *route = &priv->default_route.v4;
|
|
||||||
|
|
||||||
if (!nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) {
|
if (!commit) {
|
||||||
nm_ip4_config_merge_setting (composite,
|
/* during a non-commit event, we always pickup whatever is configured. */
|
||||||
nm_connection_get_setting_ip4_config (connection),
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
default_route_metric);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the default route.
|
if (nm_device_uses_assumed_connection (self))
|
||||||
*
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
* We keep track of the default route of a device in a private field.
|
|
||||||
* NMDevice needs to know the default route at this point, because the gateway
|
|
||||||
* might require a direct route (see below).
|
/* we are about to commit (for a non-assumed connection). Enforce whatever we have
|
||||||
*
|
* configured. */
|
||||||
* But also, we don't want to add the default route to priv->ip4_config,
|
priv->default_route.v4_is_assumed = FALSE;
|
||||||
* because the default route from the setting might not be the same that
|
|
||||||
* NMDefaultRouteManager eventually configures (because the it might
|
if ( !connection
|
||||||
* tweak the effective metric).
|
|| !nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection))
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
|
||||||
|
if (!nm_ip4_config_get_num_addresses (composite)) {
|
||||||
|
/* without addresses we can have no default route. */
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gateway = nm_ip4_config_get_gateway (composite);
|
||||||
|
if ( !gateway
|
||||||
|
&& nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM)
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
|
||||||
|
has_direct_route = ( gateway == 0
|
||||||
|
|| nm_ip4_config_get_subnet_for_host (composite, gateway)
|
||||||
|
|| nm_ip4_config_get_direct_route_for_host (composite, gateway));
|
||||||
|
|
||||||
|
priv->default_route.v4_has = TRUE;
|
||||||
|
memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4));
|
||||||
|
priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER;
|
||||||
|
priv->default_route.v4.gateway = gateway;
|
||||||
|
priv->default_route.v4.metric = default_route_metric;
|
||||||
|
priv->default_route.v4.mss = nm_ip4_config_get_mss (composite);
|
||||||
|
|
||||||
|
if (!has_direct_route) {
|
||||||
|
NMPlatformIP4Route r = priv->default_route.v4;
|
||||||
|
|
||||||
|
/* add a direct route to the gateway */
|
||||||
|
r.network = gateway;
|
||||||
|
r.plen = 32;
|
||||||
|
r.gateway = 0;
|
||||||
|
nm_ip4_config_add_route (composite, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
END_ADD_DEFAULT_ROUTE:
|
||||||
|
|
||||||
|
if (priv->default_route.v4_is_assumed) {
|
||||||
|
/* If above does not explicitly assign a default route, we always pick up the
|
||||||
|
* default route based on what is currently configured.
|
||||||
|
* That means that even managed connections with never-default, can
|
||||||
|
* get a default route (if configured externally).
|
||||||
*/
|
*/
|
||||||
if ( !assumed
|
priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4);
|
||||||
&& nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection)) {
|
|
||||||
guint32 gateway = 0;
|
|
||||||
|
|
||||||
priv->default_route.v4_is_assumed = FALSE;
|
|
||||||
if ( (!commit && priv->ext_ip4_config_had_any_addresses)
|
|
||||||
|| ( commit && nm_ip4_config_get_num_addresses (composite))) {
|
|
||||||
/* For managed interfaces, we can only configure a gateway, if either the external config indicates
|
|
||||||
* that we already have addresses, or if we are about to commit any addresses.
|
|
||||||
* Otherwise adding a default route will fail, because NMDefaultRouteManager does not add any
|
|
||||||
* addresses for the route. */
|
|
||||||
gateway = nm_ip4_config_get_gateway (composite);
|
|
||||||
if ( gateway
|
|
||||||
|| nm_device_get_device_type (self) == NM_DEVICE_TYPE_MODEM) {
|
|
||||||
memset (route, 0, sizeof (*route));
|
|
||||||
route->source = NM_IP_CONFIG_SOURCE_USER;
|
|
||||||
route->gateway = gateway;
|
|
||||||
route->metric = default_route_metric;
|
|
||||||
route->mss = nm_ip4_config_get_mss (composite);
|
|
||||||
priv->default_route.v4_has = TRUE;
|
|
||||||
|
|
||||||
if ( gateway
|
|
||||||
&& !nm_ip4_config_get_subnet_for_host (composite, gateway)
|
|
||||||
&& !nm_ip4_config_get_direct_route_for_host (composite, gateway)) {
|
|
||||||
/* add a direct route to the gateway */
|
|
||||||
NMPlatformIP4Route r = *route;
|
|
||||||
|
|
||||||
r.network = gateway;
|
|
||||||
r.plen = 32;
|
|
||||||
r.gateway = 0;
|
|
||||||
nm_ip4_config_add_route (composite, &r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* For interfaces that are assumed and that have no default-route by configuration, we assume
|
|
||||||
* the default connection and pick up whatever is configured. */
|
|
||||||
priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) route);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow setting MTU etc */
|
/* Allow setting MTU etc */
|
||||||
@@ -3438,10 +3494,13 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
NMIP6Config *composite;
|
NMIP6Config *composite;
|
||||||
|
gboolean has_direct_route;
|
||||||
|
const struct in6_addr *gateway;
|
||||||
|
|
||||||
/* If no config was passed in, create a new one */
|
/* If no config was passed in, create a new one */
|
||||||
composite = nm_ip6_config_new ();
|
composite = nm_ip6_config_new ();
|
||||||
g_assert (composite);
|
|
||||||
|
ensure_con_ipx_config (self);
|
||||||
|
|
||||||
/* Merge all the IP configs into the composite config */
|
/* Merge all the IP configs into the composite config */
|
||||||
if (priv->ac_ip6_config)
|
if (priv->ac_ip6_config)
|
||||||
@@ -3459,72 +3518,87 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||||||
if (priv->wwan_ip6_config)
|
if (priv->wwan_ip6_config)
|
||||||
nm_ip6_config_merge (composite, priv->wwan_ip6_config);
|
nm_ip6_config_merge (composite, priv->wwan_ip6_config);
|
||||||
|
|
||||||
/* Merge user overrides into the composite config. Generated+assumed
|
/* Merge user overrides into the composite config. For assumed connections,
|
||||||
* connections come from the system not the user and merging them would
|
* con_ip6_config is empty. */
|
||||||
* be redundant, so don't bother.
|
if (priv->con_ip6_config)
|
||||||
*/
|
nm_ip6_config_merge (composite, priv->con_ip6_config);
|
||||||
|
|
||||||
connection = nm_device_get_connection (self);
|
connection = nm_device_get_connection (self);
|
||||||
|
|
||||||
|
/* Add the default route.
|
||||||
|
*
|
||||||
|
* We keep track of the default route of a device in a private field.
|
||||||
|
* NMDevice needs to know the default route at this point, because the gateway
|
||||||
|
* might require a direct route (see below).
|
||||||
|
*
|
||||||
|
* But also, we don't want to add the default route to priv->ip6_config,
|
||||||
|
* because the default route from the setting might not be the same that
|
||||||
|
* NMDefaultRouteManager eventually configures (because the it might
|
||||||
|
* tweak the effective metric).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* unless we come to a different conclusion below, we have no default route and
|
||||||
|
* the route is assumed. */
|
||||||
priv->default_route.v6_has = FALSE;
|
priv->default_route.v6_has = FALSE;
|
||||||
priv->default_route.v6_is_assumed = TRUE;
|
priv->default_route.v6_is_assumed = TRUE;
|
||||||
if (connection) {
|
|
||||||
gboolean assumed = nm_device_uses_assumed_connection (self);
|
|
||||||
NMPlatformIP6Route *route = &priv->default_route.v6;
|
|
||||||
|
|
||||||
if (!nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) {
|
if (!commit) {
|
||||||
nm_ip6_config_merge_setting (composite,
|
/* during a non-commit event, we always pickup whatever is configured. */
|
||||||
nm_connection_get_setting_ip6_config (connection),
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
nm_device_get_ip6_route_metric (self));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the default route.
|
if (nm_device_uses_assumed_connection (self))
|
||||||
*
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
* We keep track of the default route of a device in a private field.
|
|
||||||
* NMDevice needs to know the default route at this point, because the gateway
|
|
||||||
* might require a direct route (see below).
|
/* we are about to commit (for a non-assumed connection). Enforce whatever we have
|
||||||
*
|
* configured. */
|
||||||
* But also, we don't want to add the default route to priv->ip4_config,
|
priv->default_route.v6_is_assumed = FALSE;
|
||||||
* because the default route from the setting might not be the same that
|
|
||||||
* NMDefaultRouteManager eventually configures (because the it might
|
if ( !connection
|
||||||
* tweak the effective metric).
|
|| !nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection))
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
|
||||||
|
if (!nm_ip6_config_get_num_addresses (composite)) {
|
||||||
|
/* without addresses we can have no default route. */
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gateway = nm_ip6_config_get_gateway (composite);
|
||||||
|
if (!gateway)
|
||||||
|
goto END_ADD_DEFAULT_ROUTE;
|
||||||
|
|
||||||
|
|
||||||
|
has_direct_route = nm_ip6_config_get_direct_route_for_host (composite, gateway) != NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
priv->default_route.v6_has = TRUE;
|
||||||
|
memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6));
|
||||||
|
priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER;
|
||||||
|
priv->default_route.v6.gateway = *gateway;
|
||||||
|
priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self);
|
||||||
|
priv->default_route.v6.mss = nm_ip6_config_get_mss (composite);
|
||||||
|
|
||||||
|
if (!has_direct_route) {
|
||||||
|
NMPlatformIP6Route r = priv->default_route.v6;
|
||||||
|
|
||||||
|
/* add a direct route to the gateway */
|
||||||
|
r.network = *gateway;
|
||||||
|
r.plen = 128;
|
||||||
|
r.gateway = in6addr_any;
|
||||||
|
nm_ip6_config_add_route (composite, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
END_ADD_DEFAULT_ROUTE:
|
||||||
|
|
||||||
|
if (priv->default_route.v6_is_assumed) {
|
||||||
|
/* If above does not explicitly assign a default route, we always pick up the
|
||||||
|
* default route based on what is currently configured.
|
||||||
|
* That means that even managed connections with never-default, can
|
||||||
|
* get a default route (if configured externally).
|
||||||
*/
|
*/
|
||||||
if ( !assumed
|
priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6);
|
||||||
&& nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection)) {
|
|
||||||
const struct in6_addr *gateway = NULL;
|
|
||||||
|
|
||||||
priv->default_route.v6_is_assumed = FALSE;
|
|
||||||
if ( (!commit && priv->ext_ip6_config_had_any_addresses)
|
|
||||||
|| ( commit && nm_ip6_config_get_num_addresses (composite))) {
|
|
||||||
/* For managed interfaces, we can only configure a gateway, if either the external config indicates
|
|
||||||
* that we already have addresses, or if we are about to commit any addresses.
|
|
||||||
* Otherwise adding a default route will fail, because NMDefaultRouteManager does not add any
|
|
||||||
* addresses for the route. */
|
|
||||||
gateway = nm_ip6_config_get_gateway (composite);
|
|
||||||
if (gateway) {
|
|
||||||
memset (route, 0, sizeof (*route));
|
|
||||||
route->source = NM_IP_CONFIG_SOURCE_USER;
|
|
||||||
route->gateway = *gateway;
|
|
||||||
route->metric = nm_device_get_ip6_route_metric (self);
|
|
||||||
route->mss = nm_ip6_config_get_mss (composite);
|
|
||||||
priv->default_route.v6_has = TRUE;
|
|
||||||
|
|
||||||
if ( gateway
|
|
||||||
&& !nm_ip6_config_get_subnet_for_host (composite, gateway)
|
|
||||||
&& !nm_ip6_config_get_direct_route_for_host (composite, gateway)) {
|
|
||||||
/* add a direct route to the gateway */
|
|
||||||
NMPlatformIP6Route r = *route;
|
|
||||||
|
|
||||||
r.network = *gateway;
|
|
||||||
r.plen = 128;
|
|
||||||
r.gateway = in6addr_any;
|
|
||||||
nm_ip6_config_add_route (composite, &r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* For interfaces that are assumed and that have no default-route by configuration, we assume
|
|
||||||
* the default connection and pick up whatever is configured. */
|
|
||||||
priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) route);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_ip6_config_addresses_sort (composite,
|
nm_ip6_config_addresses_sort (composite,
|
||||||
@@ -6498,13 +6572,31 @@ update_ip_config (NMDevice *self, gboolean initial)
|
|||||||
/* IPv4 */
|
/* IPv4 */
|
||||||
g_clear_object (&priv->ext_ip4_config);
|
g_clear_object (&priv->ext_ip4_config);
|
||||||
priv->ext_ip4_config = nm_ip4_config_capture (ifindex, capture_resolv_conf);
|
priv->ext_ip4_config = nm_ip4_config_capture (ifindex, capture_resolv_conf);
|
||||||
priv->ext_ip4_config_had_any_addresses = ( priv->ext_ip4_config
|
|
||||||
&& nm_ip4_config_get_num_addresses (priv->ext_ip4_config) > 0);
|
|
||||||
if (priv->ext_ip4_config) {
|
if (priv->ext_ip4_config) {
|
||||||
if (initial) {
|
if (initial) {
|
||||||
g_clear_object (&priv->dev_ip4_config);
|
g_clear_object (&priv->dev_ip4_config);
|
||||||
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
|
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
ensure_con_ipx_config (self);
|
||||||
|
|
||||||
|
/* This function was called upon external changes. Remove the configuration
|
||||||
|
* (adresses,routes) that is no longer present externally from the interal
|
||||||
|
* config. This way, we don't readd 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->vpn4_config)
|
||||||
|
nm_ip4_config_intersect (priv->vpn4_config, priv->ext_ip4_config);
|
||||||
|
if (priv->wwan_ip4_config)
|
||||||
|
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
|
||||||
|
|
||||||
|
/* 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)
|
if (priv->dev_ip4_config)
|
||||||
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
|
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
|
||||||
if (priv->vpn4_config)
|
if (priv->vpn4_config)
|
||||||
@@ -6518,14 +6610,34 @@ update_ip_config (NMDevice *self, gboolean initial)
|
|||||||
/* IPv6 */
|
/* IPv6 */
|
||||||
g_clear_object (&priv->ext_ip6_config);
|
g_clear_object (&priv->ext_ip6_config);
|
||||||
priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||||
priv->ext_ip6_config_had_any_addresses = ( priv->ext_ip6_config
|
|
||||||
&& nm_ip6_config_get_num_addresses (priv->ext_ip6_config) > 0);
|
|
||||||
if (priv->ext_ip6_config) {
|
if (priv->ext_ip6_config) {
|
||||||
|
|
||||||
/* Check this before modifying ext_ip6_config */
|
/* Check this before modifying ext_ip6_config */
|
||||||
linklocal6_just_completed = priv->linklocal6_timeout_id &&
|
linklocal6_just_completed = priv->linklocal6_timeout_id &&
|
||||||
have_ip6_address (priv->ext_ip6_config, TRUE);
|
have_ip6_address (priv->ext_ip6_config, TRUE);
|
||||||
|
|
||||||
|
ensure_con_ipx_config (self);
|
||||||
|
|
||||||
|
/* This function was called upon external changes. Remove the configuration
|
||||||
|
* (adresses,routes) that is no longer present externally from the interal
|
||||||
|
* config. This way, we don't readd 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);
|
||||||
|
if (priv->vpn6_config)
|
||||||
|
nm_ip6_config_intersect (priv->vpn6_config, priv->ext_ip6_config);
|
||||||
|
|
||||||
|
/* 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)
|
if (priv->ac_ip6_config)
|
||||||
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
|
||||||
if (priv->dhcp6_ip6_config)
|
if (priv->dhcp6_ip6_config)
|
||||||
@@ -7117,20 +7229,19 @@ _cleanup_generic_post (NMDevice *self, gboolean deconfigure)
|
|||||||
*/
|
*/
|
||||||
nm_device_set_ip4_config (self, NULL, 0, TRUE, &ignored);
|
nm_device_set_ip4_config (self, NULL, 0, TRUE, &ignored);
|
||||||
nm_device_set_ip6_config (self, NULL, TRUE, &ignored);
|
nm_device_set_ip6_config (self, NULL, TRUE, &ignored);
|
||||||
|
g_clear_object (&priv->con_ip4_config);
|
||||||
g_clear_object (&priv->dev_ip4_config);
|
g_clear_object (&priv->dev_ip4_config);
|
||||||
g_clear_object (&priv->ext_ip4_config);
|
g_clear_object (&priv->ext_ip4_config);
|
||||||
g_clear_object (&priv->wwan_ip4_config);
|
g_clear_object (&priv->wwan_ip4_config);
|
||||||
g_clear_object (&priv->vpn4_config);
|
g_clear_object (&priv->vpn4_config);
|
||||||
g_clear_object (&priv->ip4_config);
|
g_clear_object (&priv->ip4_config);
|
||||||
|
g_clear_object (&priv->con_ip6_config);
|
||||||
g_clear_object (&priv->ac_ip6_config);
|
g_clear_object (&priv->ac_ip6_config);
|
||||||
g_clear_object (&priv->ext_ip6_config);
|
g_clear_object (&priv->ext_ip6_config);
|
||||||
g_clear_object (&priv->vpn6_config);
|
g_clear_object (&priv->vpn6_config);
|
||||||
g_clear_object (&priv->wwan_ip6_config);
|
g_clear_object (&priv->wwan_ip6_config);
|
||||||
g_clear_object (&priv->ip6_config);
|
g_clear_object (&priv->ip6_config);
|
||||||
|
|
||||||
priv->ext_ip4_config_had_any_addresses = FALSE;
|
|
||||||
priv->ext_ip6_config_had_any_addresses = FALSE;
|
|
||||||
|
|
||||||
clear_act_request (self);
|
clear_act_request (self);
|
||||||
|
|
||||||
/* Clear legacy IPv4 address property */
|
/* Clear legacy IPv4 address property */
|
||||||
|
@@ -76,14 +76,14 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get,
|
|||||||
#define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__)
|
#define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__)
|
||||||
#define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__)
|
#define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOG_ENTRY_FMT "entry[%u/%s:%p:%s:%c%c]"
|
#define LOG_ENTRY_FMT "entry[%u/%s:%p:%s:%c:%csync]"
|
||||||
#define LOG_ENTRY_ARGS(entry_idx, entry) \
|
#define LOG_ENTRY_ARGS(entry_idx, entry) \
|
||||||
(entry_idx), \
|
(entry_idx), \
|
||||||
NM_IS_DEVICE ((entry)->source.pointer) ? "dev" : "vpn", \
|
NM_IS_DEVICE ((entry)->source.pointer) ? "dev" : "vpn", \
|
||||||
(entry)->source.pointer, \
|
(entry)->source.pointer, \
|
||||||
NM_IS_DEVICE ((entry)->source.pointer) ? nm_device_get_iface ((entry)->source.device) : nm_vpn_connection_get_connection_id ((entry)->source.vpn), \
|
NM_IS_DEVICE ((entry)->source.pointer) ? nm_device_get_iface ((entry)->source.device) : nm_vpn_connection_get_connection_id ((entry)->source.vpn), \
|
||||||
((entry)->never_default ? 'N' : 'n'), \
|
((entry)->never_default ? '0' : '1'), \
|
||||||
((entry)->synced ? 'S' : 's')
|
((entry)->synced ? '+' : '-')
|
||||||
|
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
|
|
||||||
|
@@ -541,6 +541,117 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
g_object_thaw_notify (G_OBJECT (dst));
|
g_object_thaw_notify (G_OBJECT (dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
static int
|
||||||
|
_addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->addresses->len; i++) {
|
||||||
|
const NMPlatformIP4Address *a = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
|
||||||
|
|
||||||
|
if (addr->address == a->address &&
|
||||||
|
addr->plen == a->plen)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_nameservers_get_index (const NMIP4Config *self, guint32 ns)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nameservers->len; i++) {
|
||||||
|
guint32 n = g_array_index (priv->nameservers, guint32, i);
|
||||||
|
|
||||||
|
if (ns == n)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_routes_get_index (const NMIP4Config *self, const NMPlatformIP4Route *route)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->routes->len; i++) {
|
||||||
|
const NMPlatformIP4Route *r = &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
||||||
|
|
||||||
|
if ( route->network == r->network
|
||||||
|
&& route->plen == r->plen)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_domains_get_index (const NMIP4Config *self, const char *domain)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->domains->len; i++) {
|
||||||
|
const char *d = g_ptr_array_index (priv->domains, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (domain, d) == 0)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_searches_get_index (const NMIP4Config *self, const char *search)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->searches->len; i++) {
|
||||||
|
const char *s = g_ptr_array_index (priv->searches, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (search, s) == 0)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_nis_servers_get_index (const NMIP4Config *self, guint32 nis_server)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nis->len; i++) {
|
||||||
|
guint32 n = g_array_index (priv->nis, guint32, i);
|
||||||
|
|
||||||
|
if (n == nis_server)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_wins_get_index (const NMIP4Config *self, guint32 wins_server)
|
||||||
|
{
|
||||||
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->wins->len; i++) {
|
||||||
|
guint32 n = g_array_index (priv->wins, guint32, i);
|
||||||
|
|
||||||
|
if (n == wins_server)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_ip4_config_subtract:
|
* nm_ip4_config_subtract:
|
||||||
* @dst: config from which to remove everything in @src
|
* @dst: config from which to remove everything in @src
|
||||||
@@ -551,7 +662,8 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
void
|
void
|
||||||
nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
||||||
{
|
{
|
||||||
guint32 i, j;
|
guint32 i;
|
||||||
|
gint idx;
|
||||||
|
|
||||||
g_return_if_fail (src != NULL);
|
g_return_if_fail (src != NULL);
|
||||||
g_return_if_fail (dst != NULL);
|
g_return_if_fail (dst != NULL);
|
||||||
@@ -560,31 +672,16 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
|
|
||||||
/* addresses */
|
/* addresses */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
|
||||||
const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i);
|
idx = _addresses_get_index (dst, nm_ip4_config_get_address (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_addresses (dst); j++) {
|
nm_ip4_config_del_address (dst, idx);
|
||||||
const NMPlatformIP4Address *dst_addr = nm_ip4_config_get_address (dst, j);
|
|
||||||
|
|
||||||
if (src_addr->address == dst_addr->address &&
|
|
||||||
src_addr->plen == dst_addr->plen) {
|
|
||||||
nm_ip4_config_del_address (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nameservers */
|
/* nameservers */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
|
||||||
guint32 src_ns = nm_ip4_config_get_nameserver (src, i);
|
idx = _nameservers_get_index (dst, nm_ip4_config_get_nameserver (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_nameservers (dst); j++) {
|
nm_ip4_config_del_nameserver (dst, idx);
|
||||||
guint32 dst_ns = nm_ip4_config_get_nameserver (dst, j);
|
|
||||||
|
|
||||||
if (dst_ns == src_ns) {
|
|
||||||
nm_ip4_config_del_nameserver (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default gateway */
|
/* default gateway */
|
||||||
@@ -596,44 +693,23 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
|
|
||||||
/* routes */
|
/* routes */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
|
||||||
const NMPlatformIP4Route *src_route = nm_ip4_config_get_route (src, i);
|
idx = _routes_get_index (dst, nm_ip4_config_get_route (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_routes (dst); j++) {
|
nm_ip4_config_del_route (dst, idx);
|
||||||
const NMPlatformIP4Route *dst_route = nm_ip4_config_get_route (dst, j);
|
|
||||||
|
|
||||||
if (src_route->network == dst_route->network && src_route->plen == dst_route->plen) {
|
|
||||||
nm_ip4_config_del_route (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* domains */
|
/* domains */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
|
||||||
const char *src_domain = nm_ip4_config_get_domain (src, i);
|
idx = _domains_get_index (dst, nm_ip4_config_get_domain (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_domains (dst); j++) {
|
nm_ip4_config_del_domain (dst, idx);
|
||||||
const char *dst_domain = nm_ip4_config_get_domain (dst, j);
|
|
||||||
|
|
||||||
if (g_strcmp0 (src_domain, dst_domain) == 0) {
|
|
||||||
nm_ip4_config_del_domain (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dns searches */
|
/* dns searches */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
|
||||||
const char *src_search = nm_ip4_config_get_search (src, i);
|
idx = _searches_get_index (dst, nm_ip4_config_get_search (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_searches (dst); j++) {
|
nm_ip4_config_del_search (dst, idx);
|
||||||
const char *dst_search = nm_ip4_config_get_search (dst, j);
|
|
||||||
|
|
||||||
if (g_strcmp0 (src_search, dst_search) == 0) {
|
|
||||||
nm_ip4_config_del_search (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MSS */
|
/* MSS */
|
||||||
@@ -646,16 +722,9 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
|
|
||||||
/* NIS */
|
/* NIS */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
|
||||||
guint32 src_nis = nm_ip4_config_get_nis_server (src, i);
|
idx = _nis_servers_get_index (dst, nm_ip4_config_get_nis_server (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip4_config_get_num_nis_servers (dst); j++) {
|
nm_ip4_config_del_nis_server (dst, idx);
|
||||||
guint32 dst_nis = nm_ip4_config_get_nis_server (dst, j);
|
|
||||||
|
|
||||||
if (dst_nis == src_nis) {
|
|
||||||
nm_ip4_config_del_nis_server (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
|
if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
|
||||||
@@ -663,16 +732,91 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||||||
|
|
||||||
/* WINS */
|
/* WINS */
|
||||||
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
|
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
|
||||||
guint32 src_wins = nm_ip4_config_get_wins (src, i);
|
idx = _wins_get_index (dst, nm_ip4_config_get_wins (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
|
nm_ip4_config_del_wins (dst, idx);
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0; j < nm_ip4_config_get_num_wins (dst); j++) {
|
g_object_thaw_notify (G_OBJECT (dst));
|
||||||
guint32 dst_wins = nm_ip4_config_get_wins (dst, j);
|
}
|
||||||
|
|
||||||
if (dst_wins == src_wins) {
|
void
|
||||||
nm_ip4_config_del_wins (dst, j);
|
nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
|
||||||
break;
|
{
|
||||||
}
|
guint32 i;
|
||||||
}
|
gint idx;
|
||||||
|
|
||||||
|
g_return_if_fail (src != NULL);
|
||||||
|
g_return_if_fail (dst != NULL);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (dst));
|
||||||
|
|
||||||
|
/* addresses */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_addresses (dst); ) {
|
||||||
|
idx = _addresses_get_index (src, nm_ip4_config_get_address (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_address (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nameservers */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (dst); ) {
|
||||||
|
idx = _nameservers_get_index (src, nm_ip4_config_get_nameserver (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_nameserver (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default gateway */
|
||||||
|
if ( !nm_ip4_config_get_num_addresses (dst)
|
||||||
|
|| (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst)))
|
||||||
|
nm_ip4_config_set_gateway (dst, 0);
|
||||||
|
|
||||||
|
/* routes */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_routes (dst); ) {
|
||||||
|
idx = _routes_get_index (src, nm_ip4_config_get_route (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_route (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* domains */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_domains (dst); ) {
|
||||||
|
idx = _domains_get_index (src, nm_ip4_config_get_domain (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_domain (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dns searches */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_searches (dst); ) {
|
||||||
|
idx = _searches_get_index (src, nm_ip4_config_get_search (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_search (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NIS */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (dst); ) {
|
||||||
|
idx = _nis_servers_get_index (src, nm_ip4_config_get_nis_server (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_nis_server (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WINS */
|
||||||
|
for (i = 0; i < nm_ip4_config_get_num_wins (dst); ) {
|
||||||
|
idx = _wins_get_index (src, nm_ip4_config_get_wins (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip4_config_del_wins (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (dst));
|
g_object_thaw_notify (G_OBJECT (dst));
|
||||||
|
@@ -71,6 +71,7 @@ NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config);
|
|||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src);
|
void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src);
|
||||||
void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src);
|
void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src);
|
||||||
|
void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src);
|
||||||
gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
|
gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
|
||||||
gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen);
|
gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen);
|
||||||
void nm_ip4_config_dump (const NMIP4Config *config, const char *detail);
|
void nm_ip4_config_dump (const NMIP4Config *config, const char *detail);
|
||||||
|
@@ -653,6 +653,85 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
static int
|
||||||
|
_addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr)
|
||||||
|
{
|
||||||
|
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->addresses->len; i++) {
|
||||||
|
const NMPlatformIP6Address *a = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
|
||||||
|
|
||||||
|
if (IN6_ARE_ADDR_EQUAL (&addr->address, &a->address))
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns)
|
||||||
|
{
|
||||||
|
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nameservers->len; i++) {
|
||||||
|
const struct in6_addr *n = &g_array_index (priv->nameservers, struct in6_addr, i);
|
||||||
|
|
||||||
|
if (IN6_ARE_ADDR_EQUAL (ns, n))
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route)
|
||||||
|
{
|
||||||
|
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->routes->len; i++) {
|
||||||
|
const NMPlatformIP6Route *r = &g_array_index (priv->routes, NMPlatformIP6Route, i);
|
||||||
|
|
||||||
|
if (routes_are_duplicate (route, r, FALSE))
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_domains_get_index (const NMIP6Config *self, const char *domain)
|
||||||
|
{
|
||||||
|
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->domains->len; i++) {
|
||||||
|
const char *d = g_ptr_array_index (priv->domains, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (domain, d) == 0)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_searches_get_index (const NMIP6Config *self, const char *search)
|
||||||
|
{
|
||||||
|
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->searches->len; i++) {
|
||||||
|
const char *s = g_ptr_array_index (priv->searches, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (search, s) == 0)
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_ip6_config_subtract:
|
* nm_ip6_config_subtract:
|
||||||
* @dst: config from which to remove everything in @src
|
* @dst: config from which to remove everything in @src
|
||||||
@@ -663,7 +742,8 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6
|
|||||||
void
|
void
|
||||||
nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
||||||
{
|
{
|
||||||
guint32 i, j;
|
guint i;
|
||||||
|
gint idx;
|
||||||
const struct in6_addr *dst_tmp, *src_tmp;
|
const struct in6_addr *dst_tmp, *src_tmp;
|
||||||
|
|
||||||
g_return_if_fail (src != NULL);
|
g_return_if_fail (src != NULL);
|
||||||
@@ -673,30 +753,16 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
|||||||
|
|
||||||
/* addresses */
|
/* addresses */
|
||||||
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) {
|
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) {
|
||||||
const NMPlatformIP6Address *src_addr = nm_ip6_config_get_address (src, i);
|
idx = _addresses_get_index (dst, nm_ip6_config_get_address (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip6_config_get_num_addresses (dst); j++) {
|
nm_ip6_config_del_address (dst, idx);
|
||||||
const NMPlatformIP6Address *dst_addr = nm_ip6_config_get_address (dst, j);
|
|
||||||
|
|
||||||
if (IN6_ARE_ADDR_EQUAL (&src_addr->address, &dst_addr->address)) {
|
|
||||||
nm_ip6_config_del_address (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nameservers */
|
/* nameservers */
|
||||||
for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) {
|
for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) {
|
||||||
const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i);
|
idx = _nameservers_get_index (dst, nm_ip6_config_get_nameserver (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip6_config_get_num_nameservers (dst); j++) {
|
nm_ip6_config_del_nameserver (dst, idx);
|
||||||
const struct in6_addr *dst_ns = nm_ip6_config_get_nameserver (dst, j);
|
|
||||||
|
|
||||||
if (IN6_ARE_ADDR_EQUAL (src_ns, dst_ns)) {
|
|
||||||
nm_ip6_config_del_nameserver (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default gateway */
|
/* default gateway */
|
||||||
@@ -710,44 +776,23 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
|||||||
|
|
||||||
/* routes */
|
/* routes */
|
||||||
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) {
|
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) {
|
||||||
const NMPlatformIP6Route *src_route = nm_ip6_config_get_route (src, i);
|
idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip6_config_get_num_routes (dst); j++) {
|
nm_ip6_config_del_route (dst, idx);
|
||||||
const NMPlatformIP6Route *dst_route = nm_ip6_config_get_route (dst, j);
|
|
||||||
|
|
||||||
if (routes_are_duplicate (src_route, dst_route, FALSE)) {
|
|
||||||
nm_ip6_config_del_route (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* domains */
|
/* domains */
|
||||||
for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) {
|
for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) {
|
||||||
const char *src_domain = nm_ip6_config_get_domain (src, i);
|
idx = _domains_get_index (dst, nm_ip6_config_get_domain (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip6_config_get_num_domains (dst); j++) {
|
nm_ip6_config_del_domain (dst, idx);
|
||||||
const char *dst_domain = nm_ip6_config_get_domain (dst, j);
|
|
||||||
|
|
||||||
if (g_strcmp0 (src_domain, dst_domain) == 0) {
|
|
||||||
nm_ip6_config_del_domain (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dns searches */
|
/* dns searches */
|
||||||
for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) {
|
for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) {
|
||||||
const char *src_search = nm_ip6_config_get_search (src, i);
|
idx = _searches_get_index (dst, nm_ip6_config_get_search (src, i));
|
||||||
|
if (idx >= 0)
|
||||||
for (j = 0; j < nm_ip6_config_get_num_searches (dst); j++) {
|
nm_ip6_config_del_search (dst, idx);
|
||||||
const char *dst_search = nm_ip6_config_get_search (dst, j);
|
|
||||||
|
|
||||||
if (g_strcmp0 (src_search, dst_search) == 0) {
|
|
||||||
nm_ip6_config_del_search (dst, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst))
|
if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst))
|
||||||
@@ -756,6 +801,76 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
|||||||
g_object_thaw_notify (G_OBJECT (dst));
|
g_object_thaw_notify (G_OBJECT (dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
gint idx;
|
||||||
|
const struct in6_addr *dst_tmp, *src_tmp;
|
||||||
|
|
||||||
|
g_return_if_fail (src != NULL);
|
||||||
|
g_return_if_fail (dst != NULL);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (dst));
|
||||||
|
|
||||||
|
/* addresses */
|
||||||
|
for (i = 0; i < nm_ip6_config_get_num_addresses (dst); ) {
|
||||||
|
idx = _addresses_get_index (src, nm_ip6_config_get_address (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip6_config_del_address (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nameservers */
|
||||||
|
for (i = 0; i < nm_ip6_config_get_num_nameservers (dst); ) {
|
||||||
|
idx = _nameservers_get_index (src, nm_ip6_config_get_nameserver (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip6_config_del_nameserver (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default gateway */
|
||||||
|
dst_tmp = nm_ip6_config_get_gateway (dst);
|
||||||
|
if (dst_tmp) {
|
||||||
|
src_tmp = nm_ip6_config_get_gateway (src);
|
||||||
|
if ( !nm_ip6_config_get_num_addresses (dst)
|
||||||
|
|| !src_tmp
|
||||||
|
|| !IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp))
|
||||||
|
nm_ip6_config_set_gateway (dst, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* routes */
|
||||||
|
for (i = 0; i < nm_ip6_config_get_num_routes (dst); ) {
|
||||||
|
idx = _routes_get_index (src, nm_ip6_config_get_route (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip6_config_del_route (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* domains */
|
||||||
|
for (i = 0; i < nm_ip6_config_get_num_domains (src); ) {
|
||||||
|
idx = _domains_get_index (src, nm_ip6_config_get_domain (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip6_config_del_domain (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dns searches */
|
||||||
|
for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) {
|
||||||
|
idx = _searches_get_index (src, nm_ip6_config_get_search (dst, i));
|
||||||
|
if (idx < 0)
|
||||||
|
nm_ip6_config_del_search (dst, i);
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (dst));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_ip6_config_replace:
|
* nm_ip6_config_replace:
|
||||||
* @dst: config which will be replaced with everything in @src
|
* @dst: config which will be replaced with everything in @src
|
||||||
|
@@ -71,6 +71,7 @@ NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config);
|
|||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src);
|
void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src);
|
||||||
void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src);
|
void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src);
|
||||||
|
void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src);
|
||||||
gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
|
gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
|
||||||
int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen);
|
int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen);
|
||||||
void nm_ip6_config_dump (const NMIP6Config *config, const char *detail);
|
void nm_ip6_config_dump (const NMIP6Config *config, const char *detail);
|
||||||
|
Reference in New Issue
Block a user