2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: LGPL-2.1+
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
#include "nm-default.h"
|
|
|
|
|
|
|
|
|
|
#include "nmp-rules-manager.h"
|
|
|
|
|
|
|
|
|
|
#include <linux/fib_rules.h>
|
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
|
|
2019-04-14 13:36:32 +02:00
|
|
|
#include "nm-std-aux/c-list-util.h"
|
2019-03-11 11:37:40 +01:00
|
|
|
#include "nmp-object.h"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
struct _NMPRulesManager {
|
|
|
|
|
NMPlatform *platform;
|
|
|
|
|
GHashTable *by_obj;
|
|
|
|
|
GHashTable *by_user_tag;
|
|
|
|
|
GHashTable *by_data;
|
|
|
|
|
guint ref_count;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void _rules_init (NMPRulesManager *self);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#define _NMLOG_DOMAIN LOGD_PLATFORM
|
|
|
|
|
#define _NMLOG_PREFIX_NAME "rules-manager"
|
|
|
|
|
|
|
|
|
|
#define _NMLOG(level, ...) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
const NMLogLevel __level = (level); \
|
|
|
|
|
\
|
|
|
|
|
if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \
|
|
|
|
|
_nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \
|
|
|
|
|
"%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
|
|
|
|
|
_NMLOG_PREFIX_NAME \
|
|
|
|
|
_NM_UTILS_MACRO_REST (__VA_ARGS__)); \
|
|
|
|
|
} \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
NMP_IS_RULES_MANAGER (gpointer self)
|
|
|
|
|
{
|
|
|
|
|
return self
|
|
|
|
|
&& ((NMPRulesManager *) self)->ref_count > 0
|
|
|
|
|
&& NM_IS_PLATFORM (((NMPRulesManager *) self)->platform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr (1240261787u, (user_tag))
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const NMPObject *obj;
|
|
|
|
|
gconstpointer user_tag;
|
|
|
|
|
CList obj_lst;
|
|
|
|
|
CList user_tag_lst;
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
/* track_priority_val zero is special: those are weakly tracked rules.
|
|
|
|
|
* That means: NetworkManager will restore them only if it removed them earlier.
|
|
|
|
|
* But it will not remove or add them otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Otherwise, the track_priority_val goes together with track_priority_present.
|
2019-03-11 12:00:32 +01:00
|
|
|
* In case of one rule being tracked multiple times (with different priorities),
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
* the one with higher priority wins. See _rules_obj_get_best_data().
|
|
|
|
|
* Then, the winning present state either enforces that the rule is present
|
|
|
|
|
* or absent.
|
|
|
|
|
*
|
|
|
|
|
* If a rules is not tracked at all, it is ignored by NetworkManager. Assuming
|
|
|
|
|
* that it was added externally by the user. But unlike weakly tracked rules,
|
|
|
|
|
* NM will *not* restore such rules if NetworkManager themself removed them. */
|
2019-04-10 13:21:24 +02:00
|
|
|
guint32 track_priority_val;
|
2019-04-10 13:25:10 +02:00
|
|
|
bool track_priority_present:1;
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
bool dirty:1;
|
|
|
|
|
} RulesData;
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
typedef enum {
|
|
|
|
|
CONFIG_STATE_NONE = 0,
|
|
|
|
|
CONFIG_STATE_ADDED_BY_US = 1,
|
|
|
|
|
CONFIG_STATE_REMOVED_BY_US = 2,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
|
|
|
|
|
/* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE).
|
|
|
|
|
*
|
|
|
|
|
* Maybe we would only need to track whether we touched the rule at all. But we
|
|
|
|
|
* track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US)
|
|
|
|
|
* or did we remove it (CONFIG_STATE_REMOVED_BY_US)?
|
|
|
|
|
* Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively
|
|
|
|
|
* add/remove it, but whenever we are about to undo the add/remove, we need to do it.
|
|
|
|
|
* In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally
|
|
|
|
|
* force the state next time when necessary. */
|
|
|
|
|
CONFIG_STATE_OWNED_BY_US = 3,
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
} ConfigState;
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
typedef struct {
|
|
|
|
|
const NMPObject *obj;
|
|
|
|
|
CList obj_lst_head;
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
/* indicates whether we configured/removed the rule (during sync()). We need that, so
|
|
|
|
|
* if the rule gets untracked, that we know to remove/restore it.
|
2019-03-11 11:37:40 +01:00
|
|
|
*
|
|
|
|
|
* This makes NMPRulesManager stateful (beyond the configuration that indicates
|
|
|
|
|
* which rules are tracked).
|
|
|
|
|
* After a restart, NetworkManager would no longer remember which rules were added
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
* by us.
|
|
|
|
|
*
|
|
|
|
|
* That is partially fixed by NetworkManager taking over the rules that it
|
|
|
|
|
* actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
ConfigState config_state;
|
2019-03-11 11:37:40 +01:00
|
|
|
} RulesObjData;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
gconstpointer user_tag;
|
|
|
|
|
CList user_tag_lst_head;
|
|
|
|
|
} RulesUserTagData;
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void _rules_data_untrack (NMPRulesManager *self,
|
|
|
|
|
RulesData *rules_data,
|
|
|
|
|
gboolean remove_user_tag_data,
|
|
|
|
|
gboolean make_owned_by_us);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
static void
|
|
|
|
|
_rules_data_assert (const RulesData *rules_data, gboolean linked)
|
|
|
|
|
{
|
|
|
|
|
nm_assert (rules_data);
|
|
|
|
|
nm_assert (NMP_OBJECT_GET_TYPE (rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
|
|
|
|
|
nm_assert (nmp_object_is_visible (rules_data->obj));
|
|
|
|
|
nm_assert (rules_data->user_tag);
|
|
|
|
|
nm_assert (!linked || !c_list_is_empty (&rules_data->obj_lst));
|
|
|
|
|
nm_assert (!linked || !c_list_is_empty (&rules_data->user_tag_lst));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
_rules_data_hash (gconstpointer data)
|
|
|
|
|
{
|
|
|
|
|
const RulesData *rules_data = data;
|
|
|
|
|
NMHashState h;
|
|
|
|
|
|
|
|
|
|
_rules_data_assert (rules_data, FALSE);
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, 269297543u);
|
|
|
|
|
nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (rules_data->obj),
|
|
|
|
|
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
|
|
|
|
|
&h);
|
|
|
|
|
nm_hash_update_val (&h, rules_data->user_tag);
|
|
|
|
|
return nm_hash_complete (&h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_rules_data_equal (gconstpointer data_a, gconstpointer data_b)
|
|
|
|
|
{
|
|
|
|
|
const RulesData *rules_data_a = data_a;
|
|
|
|
|
const RulesData *rules_data_b = data_b;
|
|
|
|
|
|
|
|
|
|
_rules_data_assert (rules_data_a, FALSE);
|
|
|
|
|
_rules_data_assert (rules_data_b, FALSE);
|
|
|
|
|
|
|
|
|
|
return rules_data_a->user_tag == rules_data_b->user_tag
|
|
|
|
|
&& (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (rules_data_a->obj),
|
|
|
|
|
NMP_OBJECT_CAST_ROUTING_RULE (rules_data_b->obj),
|
|
|
|
|
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_rules_data_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
RulesData *rules_data = data;
|
|
|
|
|
|
|
|
|
|
_rules_data_assert (rules_data, FALSE);
|
|
|
|
|
|
|
|
|
|
c_list_unlink_stale (&rules_data->obj_lst);
|
|
|
|
|
c_list_unlink_stale (&rules_data->user_tag_lst);
|
|
|
|
|
nmp_object_unref (rules_data->obj);
|
|
|
|
|
g_slice_free (RulesData, rules_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const RulesData *
|
|
|
|
|
_rules_obj_get_best_data (RulesObjData *obj_data)
|
|
|
|
|
{
|
|
|
|
|
RulesData *rules_data;
|
|
|
|
|
const RulesData *rd_best = NULL;
|
|
|
|
|
|
|
|
|
|
c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) {
|
|
|
|
|
|
|
|
|
|
_rules_data_assert (rules_data, TRUE);
|
|
|
|
|
|
|
|
|
|
if (rd_best) {
|
2019-04-10 13:21:24 +02:00
|
|
|
if (rd_best->track_priority_val > rules_data->track_priority_val)
|
2019-03-11 11:37:40 +01:00
|
|
|
continue;
|
2019-04-10 13:21:24 +02:00
|
|
|
if (rd_best->track_priority_val == rules_data->track_priority_val) {
|
|
|
|
|
if ( rd_best->track_priority_present
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
|| !rules_data->track_priority_present) {
|
|
|
|
|
/* if the priorities are identical, then "present" wins over
|
|
|
|
|
* "!present" (absent). */
|
2019-03-11 11:37:40 +01:00
|
|
|
continue;
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
}
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rd_best = rules_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rd_best;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
_rules_obj_hash (gconstpointer data)
|
|
|
|
|
{
|
|
|
|
|
const RulesObjData *obj_data = data;
|
|
|
|
|
NMHashState h;
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, 432817559u);
|
|
|
|
|
nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj),
|
|
|
|
|
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
|
|
|
|
|
&h);
|
|
|
|
|
return nm_hash_complete (&h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_rules_obj_equal (gconstpointer data_a, gconstpointer data_b)
|
|
|
|
|
{
|
|
|
|
|
const RulesObjData *obj_data_a = data_a;
|
|
|
|
|
const RulesObjData *obj_data_b = data_b;
|
|
|
|
|
|
|
|
|
|
return (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (obj_data_a->obj),
|
|
|
|
|
NMP_OBJECT_CAST_ROUTING_RULE (obj_data_b->obj),
|
|
|
|
|
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_rules_obj_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
RulesObjData *obj_data = data;
|
|
|
|
|
|
|
|
|
|
c_list_unlink_stale (&obj_data->obj_lst_head);
|
|
|
|
|
nmp_object_unref (obj_data->obj);
|
|
|
|
|
g_slice_free (RulesObjData, obj_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
_rules_user_tag_hash (gconstpointer data)
|
|
|
|
|
{
|
|
|
|
|
const RulesUserTagData *user_tag_data = data;
|
|
|
|
|
|
|
|
|
|
return nm_hash_val (644693447u, user_tag_data->user_tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_rules_user_tag_equal (gconstpointer data_a, gconstpointer data_b)
|
|
|
|
|
{
|
|
|
|
|
const RulesUserTagData *user_tag_data_a = data_a;
|
|
|
|
|
const RulesUserTagData *user_tag_data_b = data_b;
|
|
|
|
|
|
|
|
|
|
return user_tag_data_a->user_tag == user_tag_data_b->user_tag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_rules_user_tag_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
RulesUserTagData *user_tag_data = data;
|
|
|
|
|
|
|
|
|
|
c_list_unlink_stale (&user_tag_data->user_tag_lst_head);
|
|
|
|
|
g_slice_free (RulesUserTagData, user_tag_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RulesData *
|
|
|
|
|
_rules_data_lookup (GHashTable *by_data,
|
|
|
|
|
const NMPObject *obj,
|
|
|
|
|
gconstpointer user_tag)
|
|
|
|
|
{
|
|
|
|
|
RulesData rules_data_needle = {
|
|
|
|
|
.obj = obj,
|
|
|
|
|
.user_tag = user_tag,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return g_hash_table_lookup (by_data, &rules_data_needle);
|
|
|
|
|
}
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
/**
|
|
|
|
|
* nmp_rules_manager_track:
|
|
|
|
|
* @self: the #NMPRulesManager instance
|
|
|
|
|
* @routing_rule: the #NMPlatformRoutingRule to track or untrack
|
|
|
|
|
* @track_priority: the priority for tracking the rule. Note that
|
|
|
|
|
* negative values indicate a forced absence of the rule. Priorities
|
|
|
|
|
* are compared with their absolute values (with higher absolute
|
|
|
|
|
* value being more important). For example, if you track the same
|
|
|
|
|
* rule twice, once with priority -5 and +10, then the rule is
|
|
|
|
|
* present (because the positive number is more important).
|
|
|
|
|
* The special value 0 indicates weakly-tracked rules.
|
|
|
|
|
* @user_tag: the tag associated with tracking this rule. The same tag
|
|
|
|
|
* must be used to untrack the rule later.
|
|
|
|
|
* @user_tag_untrack: if not %NULL, at the same time untrack this user-tag
|
|
|
|
|
* for the same rule. Note that this is different from a plain nmp_rules_manager_untrack(),
|
|
|
|
|
* because it enforces ownership of the now tracked rule. On the other hand,
|
|
|
|
|
* a plain nmp_rules_manager_untrack() merely forgets about the tracking.
|
|
|
|
|
* The purpose here is to set this to %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG.
|
|
|
|
|
*/
|
2019-03-11 11:37:40 +01:00
|
|
|
void
|
|
|
|
|
nmp_rules_manager_track (NMPRulesManager *self,
|
|
|
|
|
const NMPlatformRoutingRule *routing_rule,
|
2019-04-10 13:21:24 +02:00
|
|
|
gint32 track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
gconstpointer user_tag,
|
|
|
|
|
gconstpointer user_tag_untrack)
|
2019-03-11 11:37:40 +01:00
|
|
|
{
|
|
|
|
|
NMPObject obj_stack;
|
|
|
|
|
const NMPObject *p_obj_stack;
|
|
|
|
|
RulesData *rules_data;
|
|
|
|
|
RulesObjData *obj_data;
|
|
|
|
|
RulesUserTagData *user_tag_data;
|
|
|
|
|
gboolean changed = FALSE;
|
2019-04-10 13:21:24 +02:00
|
|
|
guint32 track_priority_val;
|
|
|
|
|
gboolean track_priority_present;
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
g_return_if_fail (routing_rule);
|
|
|
|
|
g_return_if_fail (user_tag);
|
2019-04-10 13:21:24 +02:00
|
|
|
nm_assert (track_priority != G_MININT32);
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
_rules_init (self);
|
|
|
|
|
|
|
|
|
|
p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
|
|
|
|
|
|
|
|
|
|
nm_assert (nmp_object_is_visible (p_obj_stack));
|
|
|
|
|
|
2019-04-10 13:21:24 +02:00
|
|
|
if (track_priority >= 0) {
|
|
|
|
|
track_priority_val = track_priority;
|
|
|
|
|
track_priority_present = TRUE;
|
2019-03-11 11:37:40 +01:00
|
|
|
} else {
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority_val = -track_priority;
|
|
|
|
|
track_priority_present = FALSE;
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag);
|
|
|
|
|
|
|
|
|
|
if (!rules_data) {
|
|
|
|
|
rules_data = g_slice_new (RulesData);
|
|
|
|
|
*rules_data = (RulesData) {
|
2019-04-10 13:21:24 +02:00
|
|
|
.obj = nm_dedup_multi_index_obj_intern (nm_platform_get_multi_idx (self->platform),
|
|
|
|
|
p_obj_stack),
|
|
|
|
|
.user_tag = user_tag,
|
|
|
|
|
.track_priority_val = track_priority_val,
|
|
|
|
|
.track_priority_present = track_priority_present,
|
|
|
|
|
.dirty = FALSE,
|
2019-03-11 11:37:40 +01:00
|
|
|
};
|
|
|
|
|
g_hash_table_add (self->by_data, rules_data);
|
|
|
|
|
|
|
|
|
|
obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj);
|
|
|
|
|
if (!obj_data) {
|
|
|
|
|
obj_data = g_slice_new (RulesObjData);
|
|
|
|
|
*obj_data = (RulesObjData) {
|
|
|
|
|
.obj = nmp_object_ref (rules_data->obj),
|
|
|
|
|
.obj_lst_head = C_LIST_INIT (obj_data->obj_lst_head),
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
.config_state = CONFIG_STATE_NONE,
|
2019-03-11 11:37:40 +01:00
|
|
|
};
|
|
|
|
|
g_hash_table_add (self->by_obj, obj_data);
|
|
|
|
|
}
|
|
|
|
|
c_list_link_tail (&obj_data->obj_lst_head, &rules_data->obj_lst);
|
|
|
|
|
|
|
|
|
|
user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag);
|
|
|
|
|
if (!user_tag_data) {
|
|
|
|
|
user_tag_data = g_slice_new (RulesUserTagData);
|
|
|
|
|
*user_tag_data = (RulesUserTagData) {
|
|
|
|
|
.user_tag = user_tag,
|
|
|
|
|
.user_tag_lst_head = C_LIST_INIT (user_tag_data->user_tag_lst_head),
|
|
|
|
|
};
|
|
|
|
|
g_hash_table_add (self->by_user_tag, user_tag_data);
|
|
|
|
|
}
|
|
|
|
|
c_list_link_tail (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst);
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
rules_data->dirty = FALSE;
|
2019-04-10 13:21:24 +02:00
|
|
|
if ( rules_data->track_priority_val != track_priority_val
|
|
|
|
|
|| rules_data->track_priority_present != track_priority_present) {
|
|
|
|
|
rules_data->track_priority_val = track_priority_val;
|
|
|
|
|
rules_data->track_priority_present = track_priority_present;
|
2019-03-11 11:37:40 +01:00
|
|
|
changed = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (user_tag_untrack) {
|
|
|
|
|
if (user_tag != user_tag_untrack) {
|
|
|
|
|
RulesData *rules_data_untrack;
|
|
|
|
|
|
|
|
|
|
rules_data_untrack = _rules_data_lookup (self->by_data, p_obj_stack, user_tag_untrack);
|
|
|
|
|
if (rules_data_untrack)
|
|
|
|
|
_rules_data_untrack (self, rules_data_untrack, FALSE, TRUE);
|
|
|
|
|
} else
|
|
|
|
|
nm_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
_rules_data_assert (rules_data, TRUE);
|
|
|
|
|
|
|
|
|
|
if (changed) {
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
_LOGD ("routing-rule: track ["NM_HASH_OBFUSCATE_PTR_FMT",%s%u] \"%s\")",
|
2019-03-11 11:37:40 +01:00
|
|
|
_USER_TAG_LOG (rules_data->user_tag),
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
( rules_data->track_priority_val == 0
|
|
|
|
|
? ""
|
|
|
|
|
: ( rules_data->track_priority_present
|
|
|
|
|
? "+"
|
|
|
|
|
: "-")),
|
2019-04-10 13:21:24 +02:00
|
|
|
(guint) rules_data->track_priority_val,
|
2019-03-11 11:37:40 +01:00
|
|
|
nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_rules_data_untrack (NMPRulesManager *self,
|
|
|
|
|
RulesData *rules_data,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
gboolean remove_user_tag_data,
|
|
|
|
|
gboolean make_owned_by_us)
|
2019-03-11 11:37:40 +01:00
|
|
|
{
|
|
|
|
|
RulesObjData *obj_data;
|
|
|
|
|
|
|
|
|
|
nm_assert (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
_rules_data_assert (rules_data, TRUE);
|
|
|
|
|
nm_assert (self->by_data);
|
|
|
|
|
nm_assert (g_hash_table_lookup (self->by_data, rules_data) == rules_data);
|
|
|
|
|
|
|
|
|
|
_LOGD ("routing-rule: untrack ["NM_HASH_OBFUSCATE_PTR_FMT"] \"%s\"",
|
|
|
|
|
_USER_TAG_LOG (rules_data->user_tag),
|
|
|
|
|
nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
|
|
|
|
|
|
|
|
|
#if NM_MORE_ASSERTS
|
|
|
|
|
{
|
|
|
|
|
RulesUserTagData *user_tag_data;
|
|
|
|
|
|
|
|
|
|
user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag);
|
|
|
|
|
nm_assert (user_tag_data);
|
|
|
|
|
nm_assert (c_list_contains (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
nm_assert (!c_list_is_empty (&rules_data->user_tag_lst));
|
|
|
|
|
|
|
|
|
|
obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj);
|
|
|
|
|
nm_assert (obj_data);
|
|
|
|
|
nm_assert (c_list_contains (&obj_data->obj_lst_head, &rules_data->obj_lst));
|
|
|
|
|
nm_assert (obj_data == g_hash_table_lookup (self->by_obj, &rules_data->obj));
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (make_owned_by_us) {
|
|
|
|
|
if (obj_data->config_state == CONFIG_STATE_NONE) {
|
|
|
|
|
/* we need to mark this entry that it requires a touch on the next
|
|
|
|
|
* sync. */
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_OWNED_BY_US;
|
|
|
|
|
}
|
|
|
|
|
} else if ( remove_user_tag_data
|
|
|
|
|
&& c_list_length_is (&rules_data->user_tag_lst, 1))
|
|
|
|
|
g_hash_table_remove (self->by_user_tag, &rules_data->user_tag);
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
/* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry
|
|
|
|
|
* around for the next sync -- so that we can undo what we did earlier. */
|
|
|
|
|
if ( obj_data->config_state == CONFIG_STATE_NONE
|
2019-03-11 11:37:40 +01:00
|
|
|
&& c_list_length_is (&rules_data->obj_lst, 1))
|
|
|
|
|
g_hash_table_remove (self->by_obj, &rules_data->obj);
|
|
|
|
|
|
|
|
|
|
g_hash_table_remove (self->by_data, rules_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmp_rules_manager_untrack (NMPRulesManager *self,
|
|
|
|
|
const NMPlatformRoutingRule *routing_rule,
|
|
|
|
|
gconstpointer user_tag)
|
|
|
|
|
{
|
|
|
|
|
NMPObject obj_stack;
|
|
|
|
|
const NMPObject *p_obj_stack;
|
|
|
|
|
RulesData *rules_data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
g_return_if_fail (routing_rule);
|
|
|
|
|
g_return_if_fail (user_tag);
|
|
|
|
|
|
|
|
|
|
_rules_init (self);
|
|
|
|
|
|
|
|
|
|
p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
|
|
|
|
|
|
|
|
|
|
nm_assert (nmp_object_is_visible (p_obj_stack));
|
|
|
|
|
|
|
|
|
|
rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag);
|
|
|
|
|
if (rules_data)
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
_rules_data_untrack (self, rules_data, TRUE, FALSE);
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmp_rules_manager_set_dirty (NMPRulesManager *self,
|
|
|
|
|
gconstpointer user_tag)
|
|
|
|
|
{
|
|
|
|
|
RulesData *rules_data;
|
|
|
|
|
RulesUserTagData *user_tag_data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
g_return_if_fail (user_tag);
|
|
|
|
|
|
|
|
|
|
if (!self->by_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag);
|
|
|
|
|
if (!user_tag_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst)
|
|
|
|
|
rules_data->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmp_rules_manager_untrack_all (NMPRulesManager *self,
|
|
|
|
|
gconstpointer user_tag,
|
|
|
|
|
gboolean all /* or only dirty */)
|
|
|
|
|
{
|
|
|
|
|
RulesData *rules_data;
|
|
|
|
|
RulesData *rules_data_safe;
|
|
|
|
|
RulesUserTagData *user_tag_data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
g_return_if_fail (user_tag);
|
|
|
|
|
|
|
|
|
|
if (!self->by_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag);
|
|
|
|
|
if (!user_tag_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
c_list_for_each_entry_safe (rules_data, rules_data_safe, &user_tag_data->user_tag_lst_head, user_tag_lst) {
|
|
|
|
|
if ( all
|
|
|
|
|
|| rules_data->dirty)
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
_rules_data_untrack (self, rules_data, FALSE, FALSE);
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
if (c_list_is_empty (&user_tag_data->user_tag_lst_head))
|
|
|
|
|
g_hash_table_remove (self->by_user_tag, user_tag_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-03-23 15:09:29 +01:00
|
|
|
nmp_rules_manager_sync (NMPRulesManager *self,
|
|
|
|
|
gboolean keep_deleted_rules)
|
2019-03-11 11:37:40 +01:00
|
|
|
{
|
|
|
|
|
const NMDedupMultiHeadEntry *pl_head_entry;
|
|
|
|
|
NMDedupMultiIter pl_iter;
|
|
|
|
|
const NMPObject *plobj;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *rules_to_delete = NULL;
|
|
|
|
|
RulesObjData *obj_data;
|
|
|
|
|
GHashTableIter h_iter;
|
|
|
|
|
guint i;
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
const RulesData *rd_best;
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
|
|
|
|
|
if (!self->by_data)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-03-23 15:09:29 +01:00
|
|
|
_LOGD ("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
pl_head_entry = nm_platform_lookup_obj_type (self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
|
|
|
|
|
if (pl_head_entry) {
|
|
|
|
|
nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) {
|
|
|
|
|
obj_data = g_hash_table_lookup (self->by_obj, &plobj);
|
|
|
|
|
|
|
|
|
|
if (!obj_data) {
|
|
|
|
|
/* this rule is not tracked. It was externally added, hence we
|
|
|
|
|
* ignore it. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
rd_best = _rules_obj_get_best_data (obj_data);
|
|
|
|
|
if (rd_best) {
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (rd_best->track_priority_present) {
|
|
|
|
|
if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
|
2019-03-11 11:37:40 +01:00
|
|
|
continue;
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
}
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
if (rd_best->track_priority_val == 0) {
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_ADDED_BY_US,
|
|
|
|
|
CONFIG_STATE_OWNED_BY_US)) {
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_NONE;
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
continue;
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
}
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
obj_data->config_state = CONFIG_STATE_NONE;
|
|
|
|
|
}
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
|
2019-03-23 15:09:29 +01:00
|
|
|
if (keep_deleted_rules) {
|
|
|
|
|
_LOGD ("forget/leak rule added by us: %s", nmp_object_to_string (plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
if (!rules_to_delete)
|
|
|
|
|
rules_to_delete = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (rules_to_delete, (gpointer) nmp_object_ref (plobj));
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rules_to_delete) {
|
|
|
|
|
for (i = 0; i < rules_to_delete->len; i++)
|
|
|
|
|
nm_platform_object_delete (self->platform, rules_to_delete->pdata[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&h_iter, self->by_obj);
|
|
|
|
|
while (g_hash_table_iter_next (&h_iter, (gpointer *) &obj_data, NULL)) {
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
rd_best = _rules_obj_get_best_data (obj_data);
|
|
|
|
|
|
|
|
|
|
if (!rd_best) {
|
2019-03-11 11:37:40 +01:00
|
|
|
g_hash_table_iter_remove (&h_iter);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (!rd_best->track_priority_present) {
|
|
|
|
|
if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
|
2019-03-11 11:37:40 +01:00
|
|
|
continue;
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
}
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
if (rd_best->track_priority_val == 0) {
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_REMOVED_BY_US,
|
|
|
|
|
CONFIG_STATE_OWNED_BY_US)) {
|
|
|
|
|
obj_data->config_state = CONFIG_STATE_NONE;
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
continue;
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
}
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
obj_data->config_state = CONFIG_STATE_NONE;
|
|
|
|
|
}
|
2019-03-11 11:37:40 +01:00
|
|
|
|
|
|
|
|
plobj = nm_platform_lookup_obj (self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj);
|
|
|
|
|
if (plobj)
|
|
|
|
|
continue;
|
|
|
|
|
|
platform: support weakly tracked routing rules in NMPRulesManager
Policy routing rules are global, and unlike routes not tied to an interface by ifindex.
That means, while we take full control over all routes of an interface during a sync,
we need to consider that multiple parties can contribute to the global set of rules.
That might be muliple connection profiles providing the same rule, or rules that are added
externally by the user. NMPRulesManager mediates for that.
This is done by NMPRulesManager "tracking" rules.
Rules that are not tracked by NMPRulesManager are completely ignored (and
considered externally added).
When tracking a rule, the caller provides a track-priority. If multiple
parties track a rule, then the highest (absolute value of the) priority
wins.
If the highest track-priority is positive, NMPRulesManager will add the rule if
it's not present.
When the highest track-priority is negative, then NMPRulesManager will remove the
rule if it's present (enforce its absence).
The complicated part is, when a rule that was previously tracked becomes no
longer tracked. In that case, we need to restore the previous state.
If NetworkManager added the rule earlier, then untracking the rule
NMPRulesManager will remove the rule again (restore its previous absent
state).
By default, if NetworkManager had a negative tracking-priority and removed the
rule earlier (enforced it to be absent), then when the rule becomes no
longer tracked, NetworkManager will not restore the rule.
Consider: the user adds a rule externally, and then activates a profile that
enforces the absence of the rule (causing NetworkManager to remove it).
When deactivating the profile, by default NetworkManager will not
restore such a rule! It's unclear whether that is a good idea, but it's
also unclear why the rule is there and whether NetworkManager should
really restore it.
Add weakly tracked rules to account for that. A tracking-priority of
zero indicates such weakly tracked rules. The only difference between an untracked
rule and a weakly tracked rule is, that when NetworkManager earlier removed the
rule (due to a negative tracking-priority), it *will* restore weakly
tracked rules when the rules becomes no longer (negatively) tracked.
And it attmpts to do that only once.
Likewise, if the rule is weakly tracked and already exists when
NMPRulesManager starts posively tracking the rule, then it would not
remove again, when no longer positively tracking it.
2019-04-10 13:47:52 +02:00
|
|
|
obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
|
2019-03-11 11:37:40 +01:00
|
|
|
nm_platform_routing_rule_add (self->platform, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-10 13:08:23 +02:00
|
|
|
void
|
|
|
|
|
nmp_rules_manager_track_from_platform (NMPRulesManager *self,
|
|
|
|
|
NMPlatform *platform,
|
|
|
|
|
int addr_family,
|
|
|
|
|
gint32 tracking_priority,
|
|
|
|
|
gconstpointer user_tag)
|
|
|
|
|
{
|
|
|
|
|
NMPLookup lookup;
|
|
|
|
|
const NMDedupMultiHeadEntry *head_entry;
|
|
|
|
|
NMDedupMultiIter iter;
|
|
|
|
|
const NMPObject *o;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
|
|
|
|
|
if (!platform)
|
|
|
|
|
platform = self->platform;
|
|
|
|
|
else
|
|
|
|
|
g_return_if_fail (NM_IS_PLATFORM (platform));
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
|
|
|
|
|
|
|
|
|
|
nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
|
|
|
|
|
head_entry = nm_platform_lookup (platform, &lookup);
|
|
|
|
|
nmp_cache_iter_for_each (&iter, head_entry, &o) {
|
|
|
|
|
const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (o);
|
|
|
|
|
|
|
|
|
|
if ( addr_family != AF_UNSPEC
|
|
|
|
|
&& rr->addr_family != addr_family)
|
|
|
|
|
continue;
|
|
|
|
|
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
nmp_rules_manager_track (self, rr, tracking_priority, user_tag, NULL);
|
2019-04-10 13:08:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmp_rules_manager_track_default (NMPRulesManager *self,
|
|
|
|
|
int addr_family,
|
2019-04-10 13:25:10 +02:00
|
|
|
gint32 track_priority,
|
2019-03-11 11:37:40 +01:00
|
|
|
gconstpointer user_tag)
|
|
|
|
|
{
|
2019-04-10 13:25:10 +02:00
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
|
|
|
|
|
|
2019-03-11 11:37:40 +01:00
|
|
|
/* track the default rules. See also `man ip-rule`. */
|
|
|
|
|
|
|
|
|
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) {
|
|
|
|
|
nmp_rules_manager_track (self,
|
|
|
|
|
&((NMPlatformRoutingRule) {
|
|
|
|
|
.addr_family = AF_INET,
|
|
|
|
|
.priority = 0,
|
|
|
|
|
.table = RT_TABLE_LOCAL,
|
|
|
|
|
.action = FR_ACT_TO_TBL,
|
2019-03-24 09:38:59 +01:00
|
|
|
.protocol = RTPROT_KERNEL,
|
2019-03-11 11:37:40 +01:00
|
|
|
}),
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
user_tag,
|
|
|
|
|
NULL);
|
2019-03-11 11:37:40 +01:00
|
|
|
nmp_rules_manager_track (self,
|
|
|
|
|
&((NMPlatformRoutingRule) {
|
|
|
|
|
.addr_family = AF_INET,
|
|
|
|
|
.priority = 32766,
|
|
|
|
|
.table = RT_TABLE_MAIN,
|
|
|
|
|
.action = FR_ACT_TO_TBL,
|
2019-03-24 09:38:59 +01:00
|
|
|
.protocol = RTPROT_KERNEL,
|
2019-03-11 11:37:40 +01:00
|
|
|
}),
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
user_tag,
|
|
|
|
|
NULL);
|
2019-03-11 11:37:40 +01:00
|
|
|
nmp_rules_manager_track (self,
|
|
|
|
|
&((NMPlatformRoutingRule) {
|
|
|
|
|
.addr_family = AF_INET,
|
|
|
|
|
.priority = 32767,
|
|
|
|
|
.table = RT_TABLE_DEFAULT,
|
|
|
|
|
.action = FR_ACT_TO_TBL,
|
2019-03-24 09:38:59 +01:00
|
|
|
.protocol = RTPROT_KERNEL,
|
2019-03-11 11:37:40 +01:00
|
|
|
}),
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
user_tag,
|
|
|
|
|
NULL);
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) {
|
|
|
|
|
nmp_rules_manager_track (self,
|
|
|
|
|
&((NMPlatformRoutingRule) {
|
|
|
|
|
.addr_family = AF_INET6,
|
|
|
|
|
.priority = 0,
|
|
|
|
|
.table = RT_TABLE_LOCAL,
|
|
|
|
|
.action = FR_ACT_TO_TBL,
|
2019-03-24 09:38:59 +01:00
|
|
|
.protocol = RTPROT_KERNEL,
|
2019-03-11 11:37:40 +01:00
|
|
|
}),
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
user_tag,
|
|
|
|
|
NULL);
|
2019-03-11 11:37:40 +01:00
|
|
|
nmp_rules_manager_track (self,
|
|
|
|
|
&((NMPlatformRoutingRule) {
|
|
|
|
|
.addr_family = AF_INET6,
|
|
|
|
|
.priority = 32766,
|
|
|
|
|
.table = RT_TABLE_MAIN,
|
|
|
|
|
.action = FR_ACT_TO_TBL,
|
2019-03-24 09:38:59 +01:00
|
|
|
.protocol = RTPROT_KERNEL,
|
2019-03-11 11:37:40 +01:00
|
|
|
}),
|
2019-04-10 13:21:24 +02:00
|
|
|
track_priority,
|
policy-routing: take ownership of externally configured rules
IP addresses, routes, TC and QDiscs are all tied to a certain interface.
So when NetworkManager manages an interface, it can be confident that
all related entires should be managed, deleted and modified by NetworkManager.
Routing policy rules are global. For that we have NMPRulesManager which
keeps track of whether NetworkManager owns a rule. This allows multiple
connection profiles to specify the same rule, and NMPRulesManager can
consolidate this information to know whether to add or remove the rule.
NMPRulesManager would also support to explicitly block a rule by
tracking it with negative priority. However that is still unused at
the moment. All that devices do is to add rules (track with positive
priority) and remove them (untrack) once the profile gets deactivated.
As rules are not exclusively owned by NetworkManager, NetworkManager
tries not to interfere with rules that it knows nothing about. That
means in particular, when NetworkManager starts it will "weakly track"
all rules that are present. "weakly track" is mostly interesting for two
cases:
- when NMPRulesManager had the same rule explicitly tracked (added) by a
device, then deactivating the device will leave the rule in place.
- when NMPRulesManager had the same rule explicitly blocked (tracked
with negative priority), then it would restore the rule when that
block gets removed (as said, currently nobody actually does this).
Note that when restarting NetworkManager, then the device may stay and
the rules kept. However after restart, NetworkManager no longer knows
that it previously added this route, so it would weakly track it and
never remove them again.
That is a problem. Avoid that, by whenever explicitly tracking a rule we
also make sure to no longer weakly track it. Most likely this rule was
indeed previously managed by NetworkManager. If this was really a rule
added by externally, then the user really should choose distinct
rule priorities to avoid such conflicts altogether.
2019-07-12 11:19:43 +02:00
|
|
|
user_tag,
|
|
|
|
|
NULL);
|
2019-03-11 11:37:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_rules_init (NMPRulesManager *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->by_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self->by_data = g_hash_table_new_full (_rules_data_hash, _rules_data_equal, NULL, _rules_data_destroy);
|
|
|
|
|
self->by_obj = g_hash_table_new_full (_rules_obj_hash, _rules_obj_equal, NULL, _rules_obj_destroy);
|
|
|
|
|
self->by_user_tag = g_hash_table_new_full (_rules_user_tag_hash, _rules_user_tag_equal, NULL, _rules_user_tag_destroy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
NMPRulesManager *
|
2019-04-10 12:52:56 +02:00
|
|
|
nmp_rules_manager_new (NMPlatform *platform)
|
2019-03-11 11:37:40 +01:00
|
|
|
{
|
|
|
|
|
NMPRulesManager *self;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL);
|
|
|
|
|
|
|
|
|
|
self = g_slice_new (NMPRulesManager);
|
|
|
|
|
*self = (NMPRulesManager) {
|
|
|
|
|
.ref_count = 1,
|
|
|
|
|
.platform = g_object_ref (platform),
|
|
|
|
|
};
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmp_rules_manager_ref (NMPRulesManager *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
|
|
|
|
|
self->ref_count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmp_rules_manager_unref (NMPRulesManager *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (NMP_IS_RULES_MANAGER (self));
|
|
|
|
|
|
|
|
|
|
if (--self->ref_count > 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (self->by_data) {
|
|
|
|
|
g_hash_table_destroy (self->by_user_tag);
|
|
|
|
|
g_hash_table_destroy (self->by_obj);
|
|
|
|
|
g_hash_table_destroy (self->by_data);
|
|
|
|
|
}
|
|
|
|
|
g_object_unref (self->platform);
|
|
|
|
|
g_slice_free (NMPRulesManager, self);
|
|
|
|
|
}
|