core: add handling of IP routing rules to NMDevice
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include <linux/fib_rules.h>
|
||||
|
||||
#include "nm-utils/nm-c-list.h"
|
||||
|
||||
#include "nm-common-macros.h"
|
||||
@@ -908,6 +910,48 @@ nm_match_spec_device_by_pllink (const NMPlatformLink *pllink,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMPlatformRoutingRule *
|
||||
nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule,
|
||||
NMPlatformRoutingRule *out_pl)
|
||||
{
|
||||
nm_assert (rule);
|
||||
nm_assert (nm_ip_routing_rule_validate (rule, NULL));
|
||||
nm_assert (out_pl);
|
||||
|
||||
*out_pl = (NMPlatformRoutingRule) {
|
||||
.addr_family = nm_ip_routing_rule_get_addr_family (rule),
|
||||
.flags = ( nm_ip_routing_rule_get_invert (rule)
|
||||
? FIB_RULE_INVERT
|
||||
: 0),
|
||||
.priority = nm_ip_routing_rule_get_priority (rule),
|
||||
.tos = nm_ip_routing_rule_get_tos (rule),
|
||||
.ip_proto = nm_ip_routing_rule_get_ipproto (rule),
|
||||
.fwmark = nm_ip_routing_rule_get_fwmark (rule),
|
||||
.fwmask = nm_ip_routing_rule_get_fwmask (rule),
|
||||
.sport_range = {
|
||||
.start = nm_ip_routing_rule_get_source_port_start (rule),
|
||||
.end = nm_ip_routing_rule_get_source_port_end (rule),
|
||||
},
|
||||
.dport_range = {
|
||||
.start = nm_ip_routing_rule_get_destination_port_start (rule),
|
||||
.end = nm_ip_routing_rule_get_destination_port_end (rule),
|
||||
},
|
||||
.src = *(nm_ip_routing_rule_get_from_bin (rule) ?: &nm_ip_addr_zero),
|
||||
.dst = *(nm_ip_routing_rule_get_to_bin (rule) ?: &nm_ip_addr_zero),
|
||||
.src_len = nm_ip_routing_rule_get_from_len (rule),
|
||||
.dst_len = nm_ip_routing_rule_get_to_len (rule),
|
||||
.action = nm_ip_routing_rule_get_action (rule),
|
||||
.table = nm_ip_routing_rule_get_table (rule),
|
||||
};
|
||||
|
||||
nm_ip_routing_rule_get_xifname_bin (rule, TRUE, out_pl->iifname);
|
||||
nm_ip_routing_rule_get_xifname_bin (rule, FALSE, out_pl->oifname);
|
||||
|
||||
return out_pl;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMShutdownWaitObjHandle {
|
||||
CList lst;
|
||||
GObject *watched_obj;
|
||||
|
@@ -24,6 +24,9 @@
|
||||
|
||||
#include "nm-core-utils.h"
|
||||
|
||||
#include "nm-setting-ip-config.h"
|
||||
#include "platform/nm-platform.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nm_utils_get_ip_config_method (NMConnection *connection,
|
||||
@@ -60,6 +63,11 @@ int nm_match_spec_device_by_pllink (const NMPlatformLink *pllink,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule,
|
||||
NMPlatformRoutingRule *out_pl);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* during shutdown, there are two relevant timeouts. One is
|
||||
* NM_SHUTDOWN_TIMEOUT_MS which is plenty of time, that we give for all
|
||||
* actions to complete. Of course, during shutdown components should hurry
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include "nm-manager.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
#include "platform/nmp-rules-manager.h"
|
||||
#include "ndisc/nm-ndisc.h"
|
||||
#include "ndisc/nm-lndp-ndisc.h"
|
||||
#include "dhcp/nm-dhcp-manager.h"
|
||||
@@ -6408,6 +6409,84 @@ lldp_init (NMDevice *self, gboolean restart)
|
||||
}
|
||||
}
|
||||
|
||||
/* set-mode can be:
|
||||
* - TRUE: sync with new rules.
|
||||
* - FALSE: sync, but remove all rules (== flush)
|
||||
* - DEFAULT: forget about all the rules that we previously tracked,
|
||||
* but don't actually remove them. This is when quitting NM
|
||||
* we want to keep the rules.
|
||||
* The problem is, after restart of NM, the rule manager will
|
||||
* no longer remember that NM added these rules and treat them
|
||||
* as externally added ones. Don't restart NetworkManager if
|
||||
* you care about that.
|
||||
*/
|
||||
static void
|
||||
_routing_rules_sync (NMDevice *self,
|
||||
NMTernary set_mode)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMPRulesManager *rules_manager = nm_netns_get_rules_manager (nm_device_get_netns (self));
|
||||
gboolean untrack_only_dirty = FALSE;
|
||||
gboolean keep_deleted_rules;
|
||||
gpointer user_tag;
|
||||
|
||||
user_tag = priv;
|
||||
|
||||
if (set_mode == NM_TERNARY_TRUE) {
|
||||
NMConnection *applied_connection;
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint i, num;
|
||||
int is_ipv4;
|
||||
|
||||
untrack_only_dirty = TRUE;
|
||||
nmp_rules_manager_set_dirty (rules_manager, user_tag);
|
||||
|
||||
applied_connection = nm_device_get_applied_connection (self);
|
||||
|
||||
for (is_ipv4 = 0; applied_connection && is_ipv4 < 2; is_ipv4++) {
|
||||
int addr_family = is_ipv4 ? AF_INET : AF_INET6;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip_config (applied_connection, addr_family);
|
||||
if (!s_ip)
|
||||
continue;
|
||||
|
||||
num = nm_setting_ip_config_get_num_routing_rules (s_ip);
|
||||
for (i = 0; i < num; i++) {
|
||||
NMPlatformRoutingRule plrule;
|
||||
NMIPRoutingRule *rule;
|
||||
|
||||
rule = nm_setting_ip_config_get_routing_rule (s_ip, i);
|
||||
nm_ip_routing_rule_to_platform (rule, &plrule);
|
||||
nmp_rules_manager_track (rules_manager,
|
||||
&plrule,
|
||||
10,
|
||||
user_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_untrack_all (rules_manager, user_tag, !untrack_only_dirty);
|
||||
|
||||
keep_deleted_rules = FALSE;
|
||||
if (set_mode == NM_TERNARY_DEFAULT) {
|
||||
/* when exiting NM, we leave the device up and the rules configured.
|
||||
* We just all nmp_rules_manager_sync() to forget about the synced rules,
|
||||
* but we don't actually delete them.
|
||||
*
|
||||
* FIXME: that is a problem after restart of NetworkManager, because these
|
||||
* rules will look like externally added, and NM will no longer remove
|
||||
* them.
|
||||
* To fix that, we could during "assume" mark the rules of the profile
|
||||
* as owned (and "added" by the device). The problem with that is that it
|
||||
* wouldn't cover rules that devices add by internal decision (not because
|
||||
* of a setting in the profile, e.g. WireGuard could setup policy routing).
|
||||
* Maybe it would be better to remember these orphaned rules at exit in a
|
||||
* file and track them after restart again. */
|
||||
keep_deleted_rules = TRUE;
|
||||
}
|
||||
nmp_rules_manager_sync (rules_manager, keep_deleted_rules);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tc_commit (NMDevice *self)
|
||||
{
|
||||
@@ -6519,6 +6598,8 @@ activate_stage2_device_config (NMDevice *self)
|
||||
}
|
||||
}
|
||||
|
||||
_routing_rules_sync (self, NM_TERNARY_TRUE);
|
||||
|
||||
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
||||
if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
|
||||
if (no_firmware)
|
||||
@@ -14350,6 +14431,11 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
||||
}
|
||||
}
|
||||
|
||||
_routing_rules_sync (self,
|
||||
cleanup_type == CLEANUP_TYPE_KEEP
|
||||
? NM_TERNARY_DEFAULT
|
||||
: NM_TERNARY_FALSE);
|
||||
|
||||
if (ifindex > 0)
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), ifindex, NULL);
|
||||
|
||||
|
@@ -471,7 +471,8 @@ nmp_rules_manager_untrack_all (NMPRulesManager *self,
|
||||
}
|
||||
|
||||
void
|
||||
nmp_rules_manager_sync (NMPRulesManager *self)
|
||||
nmp_rules_manager_sync (NMPRulesManager *self,
|
||||
gboolean keep_deleted_rules)
|
||||
{
|
||||
const NMDedupMultiHeadEntry *pl_head_entry;
|
||||
NMDedupMultiIter pl_iter;
|
||||
@@ -486,7 +487,7 @@ nmp_rules_manager_sync (NMPRulesManager *self)
|
||||
if (!self->by_data)
|
||||
return;
|
||||
|
||||
_LOGD ("sync");
|
||||
_LOGD ("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
|
||||
|
||||
pl_head_entry = nm_platform_lookup_obj_type (self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
|
||||
if (pl_head_entry) {
|
||||
@@ -508,6 +509,11 @@ nmp_rules_manager_sync (NMPRulesManager *self)
|
||||
obj_data->added_by_us = FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!rules_to_delete)
|
||||
rules_to_delete = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
|
||||
|
@@ -54,7 +54,8 @@ void nmp_rules_manager_untrack_all (NMPRulesManager *self,
|
||||
gconstpointer user_tag,
|
||||
gboolean all /* or only dirty */);
|
||||
|
||||
void nmp_rules_manager_sync (NMPRulesManager *self);
|
||||
void nmp_rules_manager_sync (NMPRulesManager *self,
|
||||
gboolean keep_deleted_rules);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@@ -1546,12 +1546,12 @@ again:
|
||||
USER_TAG_2);
|
||||
}
|
||||
if (nmtst_get_rand_int () % objs_sync->len == 0) {
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len);
|
||||
|
||||
for (i = 0; i < objs_sync->len; i++) {
|
||||
@@ -1578,12 +1578,12 @@ again:
|
||||
break;
|
||||
}
|
||||
if (nmtst_get_rand_int () % objs_sync->len == 0) {
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len - i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
|
||||
} else {
|
||||
for (i = 0; i < objs->len;) {
|
||||
|
Reference in New Issue
Block a user