mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 23:10:18 +01:00
wireguard: merge branch 'th/wireguard-routing'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/214
This commit is contained in:
commit
3b3596bb03
13 changed files with 670 additions and 124 deletions
7
NEWS
7
NEWS
|
|
@ -26,6 +26,13 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
|||
* Drop ibft settings plugin. This functionality is now covered by using
|
||||
nm-initrd-generator from initrd to pre-generate in-memory profiles.
|
||||
* Support "suppress_prefixlength" attribute for policy routing rules.
|
||||
This is what wg-quick uses for the "Improved Rule-based Routing" solution,
|
||||
and the user can now manually configure such policy routing rules.
|
||||
* Support "wireguard.ip4-auto-default-route" and "wireguard.ip6-auto-default-route".
|
||||
This automatically implements the "Improved Rule-based Routing" of wg-quick
|
||||
to help with routing loops. Note that this is now enabled by default, so
|
||||
there is a change in behavior if your WireGuard connection profiles had the
|
||||
default-route (0.0.0.0/0 or ::/0) in allowed-ips.
|
||||
* Rework implementation of settings plugins and how profiles are presisted
|
||||
to disk.
|
||||
* In-memory profiles are now only handled by keyfile plugin and will also be
|
||||
|
|
|
|||
|
|
@ -7137,6 +7137,12 @@ static const NMMetaPropertyInfo *const property_infos_WIREGUARD[] = {
|
|||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_MTU,
|
||||
.property_type = &_pt_gobject_mtu,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE,
|
||||
.property_type = &_pt_gobject_enum,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE,
|
||||
.property_type = &_pt_gobject_enum,
|
||||
),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -369,7 +369,9 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets. Note that \"ip4-auto-default-route\" or \"ip6-auto-default-route\" enabled, implies to automatically choose a fwmark.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE N_("Whether to enable special handling of the IPv4 default route. If enabled, the IPv4 default route will be placed to a dedicated routing-table and two policy routing rules will be added. The fwmark number is also used as routing-table for the default-route, and if fwmark is zero, a unused fwmark/table is chosen automatically. This corresponds to what wg-quick does with Table=auto. Leaving this at the default will enable this option automatically if ipv4.never-default is not set and there are any peers that use a default-route as allowed-ips.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE N_("Like ip4-auto-default-route, but for the IPv6 default route.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_LISTEN_PORT N_("The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PEER_ROUTES N_("Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively.")
|
||||
|
|
|
|||
|
|
@ -476,6 +476,13 @@ gboolean _nm_utils_generate_mac_address_mask_parse (const char *value,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gpointer
|
||||
_nm_connection_get_setting (NMConnection *connection,
|
||||
GType type)
|
||||
{
|
||||
return (gpointer) nm_connection_get_setting (connection, type);
|
||||
}
|
||||
|
||||
NMSettingIPConfig *nm_connection_get_setting_ip_config (NMConnection *connection,
|
||||
int addr_family);
|
||||
|
||||
|
|
|
|||
|
|
@ -1370,7 +1370,7 @@ nm_setting_sriov_class_init (NMSettingSriovClass *klass)
|
|||
*/
|
||||
obj_properties[PROP_AUTOPROBE_DRIVERS] =
|
||||
g_param_spec_enum (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, "", "",
|
||||
nm_ternary_get_type (),
|
||||
NM_TYPE_TERNARY,
|
||||
NM_TERNARY_DEFAULT,
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_READWRITE |
|
||||
|
|
|
|||
|
|
@ -907,6 +907,8 @@ typedef struct {
|
|||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
||||
PROP_FWMARK,
|
||||
PROP_IP4_AUTO_DEFAULT_ROUTE,
|
||||
PROP_IP6_AUTO_DEFAULT_ROUTE,
|
||||
PROP_LISTEN_PORT,
|
||||
PROP_MTU,
|
||||
PROP_PEER_ROUTES,
|
||||
|
|
@ -919,6 +921,8 @@ typedef struct {
|
|||
GPtrArray *peers_arr;
|
||||
GHashTable *peers_hash;
|
||||
NMSettingSecretFlags private_key_flags;
|
||||
NMTernary ip4_auto_default_route;
|
||||
NMTernary ip6_auto_default_route;
|
||||
guint32 fwmark;
|
||||
guint32 mtu;
|
||||
guint16 listen_port;
|
||||
|
|
@ -929,7 +933,7 @@ typedef struct {
|
|||
/**
|
||||
* NMSettingWireGuard:
|
||||
*
|
||||
* WireGuard Ethernet Settings
|
||||
* WireGuard Settings
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
|
|
@ -1070,6 +1074,38 @@ nm_setting_wireguard_get_mtu (NMSettingWireGuard *self)
|
|||
return NM_SETTING_WIREGUARD_GET_PRIVATE (self)->mtu;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_wireguard_get_ip4_auto_default_route:
|
||||
* @self: the #NMSettingWireGuard setting.
|
||||
*
|
||||
* Returns: the "ip4-auto-default-route" property of the setting.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
NMTernary
|
||||
nm_setting_wireguard_get_ip4_auto_default_route (NMSettingWireGuard *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_WIREGUARD (self), NM_TERNARY_DEFAULT);
|
||||
|
||||
return NM_SETTING_WIREGUARD_GET_PRIVATE (self)->ip4_auto_default_route;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_wireguard_get_ip6_auto_default_route:
|
||||
* @self: the #NMSettingWireGuard setting.
|
||||
*
|
||||
* Returns: the "ip6-auto-default-route" property of the setting.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
NMTernary
|
||||
nm_setting_wireguard_get_ip6_auto_default_route (NMSettingWireGuard *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_WIREGUARD (self), NM_TERNARY_DEFAULT);
|
||||
|
||||
return NM_SETTING_WIREGUARD_GET_PRIVATE (self)->ip6_auto_default_route;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -2260,6 +2296,12 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_FWMARK:
|
||||
g_value_set_uint (value, priv->fwmark);
|
||||
break;
|
||||
case PROP_IP4_AUTO_DEFAULT_ROUTE:
|
||||
g_value_set_enum (value, priv->ip4_auto_default_route);
|
||||
break;
|
||||
case PROP_IP6_AUTO_DEFAULT_ROUTE:
|
||||
g_value_set_enum (value, priv->ip6_auto_default_route);
|
||||
break;
|
||||
case PROP_LISTEN_PORT:
|
||||
g_value_set_uint (value, priv->listen_port);
|
||||
break;
|
||||
|
|
@ -2292,6 +2334,12 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_FWMARK:
|
||||
priv->fwmark = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_IP4_AUTO_DEFAULT_ROUTE:
|
||||
priv->ip4_auto_default_route = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_IP6_AUTO_DEFAULT_ROUTE:
|
||||
priv->ip6_auto_default_route = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_LISTEN_PORT:
|
||||
priv->listen_port = g_value_get_uint (value);
|
||||
break;
|
||||
|
|
@ -2334,6 +2382,8 @@ nm_setting_wireguard_init (NMSettingWireGuard *setting)
|
|||
priv->peers_arr = g_ptr_array_new ();
|
||||
priv->peers_hash = g_hash_table_new (nm_pstr_hash, nm_pstr_equal);
|
||||
priv->peer_routes = TRUE;
|
||||
priv->ip4_auto_default_route = NM_TERNARY_DEFAULT;
|
||||
priv->ip6_auto_default_route = NM_TERNARY_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2424,6 +2474,9 @@ nm_setting_wireguard_class_init (NMSettingWireGuardClass *klass)
|
|||
* The use of fwmark is optional and is by default off. Setting it to 0
|
||||
* disables it. Otherwise it is a 32-bit fwmark for outgoing packets.
|
||||
*
|
||||
* Note that "ip4-auto-default-route" or "ip6-auto-default-route" enabled,
|
||||
* implies to automatically choose a fwmark.
|
||||
*
|
||||
* Since: 1.16
|
||||
**/
|
||||
obj_properties[PROP_FWMARK] =
|
||||
|
|
@ -2487,6 +2540,45 @@ nm_setting_wireguard_class_init (NMSettingWireGuardClass *klass)
|
|||
| NM_SETTING_PARAM_INFERRABLE
|
||||
| G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* NMSettingWireGuard:ip4-auto-default-route:
|
||||
*
|
||||
* Whether to enable special handling of the IPv4 default route.
|
||||
* If enabled, the IPv4 default route will be placed to a dedicated
|
||||
* routing-table and two policy routing rules will be added.
|
||||
* The fwmark number is also used as routing-table for the default-route,
|
||||
* and if fwmark is zero, a unused fwmark/table is chosen automatically.
|
||||
* This corresponds to what wg-quick does with Table=auto.
|
||||
*
|
||||
* Leaving this at the default will enable this option automatically
|
||||
* if ipv4.never-default is not set and there are any peers that use
|
||||
* a default-route as allowed-ips.
|
||||
*
|
||||
* Since: 1.20
|
||||
**/
|
||||
obj_properties[PROP_IP4_AUTO_DEFAULT_ROUTE] =
|
||||
g_param_spec_enum (NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE, "", "",
|
||||
NM_TYPE_TERNARY,
|
||||
NM_TERNARY_DEFAULT,
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* NMSettingWireGuard:ip6-auto-default-route:
|
||||
*
|
||||
* Like ip4-auto-default-route, but for the IPv6 default route.
|
||||
*
|
||||
* Since: 1.20
|
||||
**/
|
||||
obj_properties[PROP_IP6_AUTO_DEFAULT_ROUTE] =
|
||||
g_param_spec_enum (NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE, "", "",
|
||||
NM_TYPE_TERNARY,
|
||||
NM_TERNARY_DEFAULT,
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/* ---dbus---
|
||||
* property: peers
|
||||
* format: array of 'a{sv}'
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ int nm_wireguard_peer_cmp (const NMWireGuardPeer *a,
|
|||
|
||||
#define NM_SETTING_WIREGUARD_MTU "mtu"
|
||||
#define NM_SETTING_WIREGUARD_PEER_ROUTES "peer-routes"
|
||||
#define NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE "ip4-auto-default-route"
|
||||
#define NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE "ip6-auto-default-route"
|
||||
|
||||
#define NM_WIREGUARD_PEER_ATTR_ALLOWED_IPS "allowed-ips"
|
||||
#define NM_WIREGUARD_PEER_ATTR_ENDPOINT "endpoint"
|
||||
|
|
@ -206,6 +208,12 @@ gboolean nm_setting_wireguard_get_peer_routes (NMSettingWireGuard *self);
|
|||
NM_AVAILABLE_IN_1_16
|
||||
guint32 nm_setting_wireguard_get_mtu (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_20
|
||||
NMTernary nm_setting_wireguard_get_ip4_auto_default_route (NMSettingWireGuard *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_20
|
||||
NMTernary nm_setting_wireguard_get_ip6_auto_default_route (NMSettingWireGuard *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -1624,5 +1624,7 @@ global:
|
|||
nm_setting_ovs_dpdk_get_devargs;
|
||||
nm_setting_ovs_dpdk_get_type;
|
||||
nm_setting_ovs_dpdk_new;
|
||||
nm_setting_wireguard_get_ip4_auto_default_route;
|
||||
nm_setting_wireguard_get_ip6_auto_default_route;
|
||||
nm_settings_add_connection2_flags_get_type;
|
||||
} libnm_1_18_0;
|
||||
|
|
|
|||
|
|
@ -21,12 +21,16 @@
|
|||
|
||||
#include "nm-device-wireguard.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/fib_rules.h>
|
||||
|
||||
#include "nm-setting-wireguard.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-glib-aux/nm-secret-utils.h"
|
||||
#include "nm-device-private.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
#include "platform/nmp-rules-manager.h"
|
||||
#include "nm-device-factory.h"
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-act-request.h"
|
||||
|
|
@ -134,10 +138,21 @@ typedef struct {
|
|||
GHashTable *peers;
|
||||
|
||||
gint64 resolve_next_try_at;
|
||||
guint resolve_next_try_id;
|
||||
|
||||
gint64 link_config_last_at;
|
||||
|
||||
guint resolve_next_try_id;
|
||||
guint link_config_delayed_id;
|
||||
|
||||
guint32 auto_default_route_fwmark;
|
||||
|
||||
guint32 auto_default_route_priority;
|
||||
|
||||
bool auto_default_route_enabled_4:1;
|
||||
bool auto_default_route_enabled_6:1;
|
||||
bool auto_default_route_initialized:1;
|
||||
bool auto_default_route_refresh:1;
|
||||
bool auto_default_route_priority_initialized:1;
|
||||
|
||||
} NMDeviceWireGuardPrivate;
|
||||
|
||||
struct _NMDeviceWireGuard {
|
||||
|
|
@ -177,6 +192,394 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_link_config_mode_to_string, LinkConfigMode,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_auto_default_route_get_enabled (NMSettingWireGuard *s_wg,
|
||||
NMConnection *connection,
|
||||
gboolean *out_enabled_v4,
|
||||
gboolean *out_enabled_v6)
|
||||
{
|
||||
NMTernary enabled_v4;
|
||||
NMTernary enabled_v6;
|
||||
|
||||
enabled_v4 = nm_setting_wireguard_get_ip4_auto_default_route (s_wg);
|
||||
enabled_v6 = nm_setting_wireguard_get_ip6_auto_default_route (s_wg);
|
||||
|
||||
if (enabled_v4 == NM_TERNARY_DEFAULT) {
|
||||
if (nm_setting_ip_config_get_never_default (nm_connection_get_setting_ip_config (connection, AF_INET)))
|
||||
enabled_v4 = FALSE;
|
||||
}
|
||||
if (enabled_v6 == NM_TERNARY_DEFAULT) {
|
||||
if (nm_setting_ip_config_get_never_default (nm_connection_get_setting_ip_config (connection, AF_INET6)))
|
||||
enabled_v6 = FALSE;
|
||||
}
|
||||
|
||||
if ( enabled_v4 == NM_TERNARY_DEFAULT
|
||||
|| enabled_v6 == NM_TERNARY_DEFAULT) {
|
||||
guint i, n_peers;
|
||||
|
||||
n_peers = nm_setting_wireguard_get_peers_len (s_wg);
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
NMWireGuardPeer *peer = nm_setting_wireguard_get_peer (s_wg, i);
|
||||
guint n_aips;
|
||||
guint j;
|
||||
|
||||
n_aips = nm_wireguard_peer_get_allowed_ips_len (peer);
|
||||
for (j = 0; j < n_aips; j++) {
|
||||
const char *aip;
|
||||
gboolean valid;
|
||||
int prefix;
|
||||
int addr_family;
|
||||
|
||||
aip = nm_wireguard_peer_get_allowed_ip (peer, j, &valid);
|
||||
if (!valid)
|
||||
continue;
|
||||
if (!nm_utils_parse_inaddr_prefix_bin (AF_UNSPEC,
|
||||
aip,
|
||||
&addr_family,
|
||||
NULL,
|
||||
&prefix))
|
||||
continue;
|
||||
if (prefix != 0)
|
||||
continue;
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
if (enabled_v4 == NM_TERNARY_DEFAULT) {
|
||||
enabled_v4 = TRUE;
|
||||
if (enabled_v6 != NM_TERNARY_DEFAULT)
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
if (enabled_v6 == NM_TERNARY_DEFAULT) {
|
||||
enabled_v6 = TRUE;
|
||||
if (enabled_v4 != NM_TERNARY_DEFAULT)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
;
|
||||
}
|
||||
|
||||
*out_enabled_v4 = (enabled_v4 == TRUE);
|
||||
*out_enabled_v6 = (enabled_v6 == TRUE);
|
||||
}
|
||||
|
||||
static guint32
|
||||
_auto_default_route_find_unused_table (NMPlatform *platform)
|
||||
{
|
||||
guint32 table;
|
||||
int is_ipv4;
|
||||
|
||||
for (table = 51820; TRUE; table++) {
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
const guint32 table_coerced = nm_platform_route_table_coerce (table);
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *plobj;
|
||||
|
||||
/* find a table/fwmark that is not yet in use. */
|
||||
|
||||
for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) {
|
||||
head_entry = nm_platform_lookup_object (platform,
|
||||
is_ipv4
|
||||
? NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
: NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
-1);
|
||||
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
|
||||
if (NMP_OBJECT_CAST_IP_ROUTE (plobj)->table_coerced == table_coerced)
|
||||
goto try_next_table;
|
||||
}
|
||||
}
|
||||
|
||||
head_entry = nm_platform_lookup_object_by_addr_family (platform,
|
||||
NMP_OBJECT_TYPE_ROUTING_RULE,
|
||||
AF_UNSPEC);
|
||||
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
|
||||
const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (plobj);
|
||||
|
||||
if (rr->fwmark == table)
|
||||
goto try_next_table;
|
||||
}
|
||||
|
||||
head_entry = nm_platform_lookup_obj_type (platform, NMP_OBJECT_TYPE_LINK);
|
||||
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
|
||||
const NMPObject *lnk_wg;
|
||||
|
||||
if (plobj->link.type != NM_LINK_TYPE_WIREGUARD)
|
||||
continue;
|
||||
|
||||
lnk_wg = plobj->_link.netlink.lnk;
|
||||
|
||||
if (!lnk_wg)
|
||||
continue;
|
||||
|
||||
if (NMP_OBJECT_GET_TYPE (lnk_wg) != NMP_OBJECT_TYPE_LNK_WIREGUARD)
|
||||
continue;
|
||||
|
||||
if (NMP_OBJECT_CAST_LNK_WIREGUARD (lnk_wg)->fwmark == table)
|
||||
goto try_next_table;
|
||||
}
|
||||
|
||||
return table;
|
||||
try_next_table:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#define PRIO_WIDTH ((guint32) 2)
|
||||
|
||||
static gboolean
|
||||
_auto_default_route_find_priority_exists (const NMDedupMultiHeadEntry *head_entry,
|
||||
guint32 priority)
|
||||
{
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *plobj;
|
||||
|
||||
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
|
||||
const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (plobj);
|
||||
|
||||
/* we don't differenciate between IPv4 vs. IPv6. There should be no
|
||||
* conflicting rules with the same priority. */
|
||||
if ( rr->priority >= priority
|
||||
&& rr->priority < priority + PRIO_WIDTH)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static guint32
|
||||
_auto_default_route_find_priority (NMPlatform *platform,
|
||||
const char *uuid)
|
||||
{
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
guint64 rnd_seed;
|
||||
const guint32 PRIME_NUMBER = 1111567573u;
|
||||
const guint32 RANGE_TOP = ((32766u - 2u * PRIO_WIDTH) / PRIO_WIDTH);
|
||||
const guint32 RANGE_LEN1 = 200u;
|
||||
const guint32 RANGE_LEN2 = (RANGE_TOP - 100u) - RANGE_LEN1;
|
||||
guint32 range_len;
|
||||
guint32 range_top;
|
||||
guint32 prio_candidate = 0;
|
||||
guint32 i_step;
|
||||
guint32 i;
|
||||
|
||||
/* For the auto-default-route policy routing rule we add 4 rules (2 Ipv4 and 2 IPv6).
|
||||
* Hence, we choose a priority for the first (of the two rules) and the second
|
||||
* rule gets priority + 1.
|
||||
* We want a priority that is
|
||||
* - unused so far.
|
||||
* - smaller than 32766u (which is the priority of the default rules for IPv4 and IPv6)
|
||||
* - stable for each connection but different between connections (we hash the UUID
|
||||
* as a "random" seed)
|
||||
* - if possible, close to 32766u (RANGE_LEN1). Only otherwise fallback to the entire
|
||||
* range (RANGE_LEN2).
|
||||
*/
|
||||
|
||||
rnd_seed = c_siphash_hash ((const guint8 [16]) { 0xb9, 0x39, 0x8e, 0xed, 0x15, 0xb3, 0xd1, 0xc4, 0x5f, 0x45, 0x00, 0x4f, 0xec, 0xc2, 0x2b, 0x7e },
|
||||
(const guint8 *) uuid,
|
||||
uuid ? strlen (uuid) + 1u : 0u);
|
||||
|
||||
head_entry = nm_platform_lookup_object_by_addr_family (platform,
|
||||
NMP_OBJECT_TYPE_ROUTING_RULE,
|
||||
AF_UNSPEC);
|
||||
|
||||
range_len = RANGE_LEN1;
|
||||
range_top = RANGE_TOP;
|
||||
|
||||
again:
|
||||
i_step = ((guint32) rnd_seed) % range_len;
|
||||
for (i = 0; i < range_len; i++) {
|
||||
|
||||
/* we sample the range in a stable, but somewhat arbitrary order to
|
||||
* find an unused priority. */
|
||||
i_step = (i_step + PRIME_NUMBER) % range_len;
|
||||
|
||||
nm_assert (i_step < range_top);
|
||||
|
||||
prio_candidate = (range_top - i_step) * PRIO_WIDTH;
|
||||
|
||||
nm_assert (prio_candidate < 32766u);
|
||||
|
||||
if (!_auto_default_route_find_priority_exists (head_entry, prio_candidate))
|
||||
return prio_candidate;
|
||||
}
|
||||
|
||||
if (range_len == RANGE_LEN1) {
|
||||
/* within the narrow range close to RANGE_TOP we couldn't find any unused
|
||||
* priority. Retry with the entire range... */
|
||||
range_len = RANGE_LEN2;
|
||||
range_top -= RANGE_LEN1;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Couldn't find an unused one? Very odd, this really should not happen unless there
|
||||
* are thousands of rules already. Just pick the last one we sampled. */
|
||||
return prio_candidate;
|
||||
}
|
||||
|
||||
static void
|
||||
_auto_default_route_init (NMDeviceWireGuard *self)
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
NMSettingWireGuard *s_wg;
|
||||
gboolean enabled_v4;
|
||||
gboolean enabled_v6;
|
||||
gboolean refreshing_only;
|
||||
guint32 old_fwmark;
|
||||
char sbuf1[100];
|
||||
|
||||
if (G_LIKELY ( priv->auto_default_route_initialized
|
||||
&& !priv->auto_default_route_refresh))
|
||||
return;
|
||||
|
||||
refreshing_only = priv->auto_default_route_initialized
|
||||
&& priv->auto_default_route_refresh;
|
||||
priv->auto_default_route_refresh = FALSE;
|
||||
|
||||
connection = nm_device_get_applied_connection (NM_DEVICE (self));
|
||||
|
||||
s_wg = _nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD);
|
||||
|
||||
old_fwmark = priv->auto_default_route_fwmark;
|
||||
|
||||
priv->auto_default_route_fwmark = nm_setting_wireguard_get_fwmark (s_wg);
|
||||
|
||||
_auto_default_route_get_enabled (s_wg,
|
||||
connection,
|
||||
&enabled_v4,
|
||||
&enabled_v6);
|
||||
priv->auto_default_route_enabled_4 = enabled_v4;
|
||||
priv->auto_default_route_enabled_6 = enabled_v6;
|
||||
priv->auto_default_route_initialized = TRUE;
|
||||
|
||||
if ( ( priv->auto_default_route_enabled_4
|
||||
|| priv->auto_default_route_enabled_6)
|
||||
&& priv->auto_default_route_fwmark == 0u) {
|
||||
if (refreshing_only)
|
||||
priv->auto_default_route_fwmark = old_fwmark;
|
||||
else
|
||||
priv->auto_default_route_fwmark = _auto_default_route_find_unused_table (nm_device_get_platform (NM_DEVICE (self)));
|
||||
}
|
||||
|
||||
_LOGT (LOGD_DEVICE,
|
||||
"auto-default-route is %s for IPv4 and %s for IPv6%s",
|
||||
priv->auto_default_route_enabled_4 ? "enabled" : "disabled",
|
||||
priv->auto_default_route_enabled_6 ? "enabled" : "disabled",
|
||||
priv->auto_default_route_enabled_4 || priv->auto_default_route_enabled_6
|
||||
? nm_sprintf_buf (sbuf1, " (fwmark 0x%x)", priv->auto_default_route_fwmark)
|
||||
: "");
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
get_extra_rules (NMDevice *device)
|
||||
{
|
||||
NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD (device);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
gs_unref_ptrarray GPtrArray *extra_rules = NULL;
|
||||
guint32 priority = 0;
|
||||
int is_ipv4;
|
||||
NMConnection *connection;
|
||||
|
||||
_auto_default_route_init (self);
|
||||
|
||||
connection = nm_device_get_applied_connection (device);
|
||||
if (!connection)
|
||||
return NULL;
|
||||
|
||||
for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) {
|
||||
NMSettingIPConfig *s_ip;
|
||||
int addr_family = is_ipv4 ? AF_INET : AF_INET6;
|
||||
guint32 table_main;
|
||||
guint32 fwmark;
|
||||
|
||||
if (is_ipv4) {
|
||||
if (!priv->auto_default_route_enabled_4)
|
||||
continue;
|
||||
} else {
|
||||
if (!priv->auto_default_route_enabled_6)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!extra_rules) {
|
||||
if (priv->auto_default_route_priority_initialized)
|
||||
priority = priv->auto_default_route_priority;
|
||||
else {
|
||||
priority = _auto_default_route_find_priority (nm_device_get_platform (device),
|
||||
nm_connection_get_uuid (connection));
|
||||
priv->auto_default_route_priority = priority;
|
||||
priv->auto_default_route_priority_initialized = TRUE;
|
||||
}
|
||||
extra_rules = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
}
|
||||
|
||||
s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
|
||||
table_main = nm_setting_ip_config_get_route_table (s_ip);
|
||||
if (table_main == 0)
|
||||
table_main = RT_TABLE_MAIN;
|
||||
|
||||
fwmark = priv->auto_default_route_fwmark;
|
||||
|
||||
G_STATIC_ASSERT_EXPR (PRIO_WIDTH == 2);
|
||||
|
||||
g_ptr_array_add (extra_rules,
|
||||
nmp_object_new (NMP_OBJECT_TYPE_ROUTING_RULE,
|
||||
&((const NMPlatformRoutingRule) {
|
||||
.priority = priority,
|
||||
.addr_family = addr_family,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.table = table_main,
|
||||
.suppress_prefixlen_inverse = ~((guint32) 0u),
|
||||
})));
|
||||
|
||||
g_ptr_array_add (extra_rules,
|
||||
nmp_object_new (NMP_OBJECT_TYPE_ROUTING_RULE,
|
||||
&((const NMPlatformRoutingRule) {
|
||||
.priority = priority + 1u,
|
||||
.addr_family = addr_family,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.table = fwmark,
|
||||
.flags = FIB_RULE_INVERT,
|
||||
.fwmark = fwmark,
|
||||
.fwmask = 0xFFFFFFFFu,
|
||||
})));
|
||||
}
|
||||
|
||||
return g_steal_pointer (&extra_rules);
|
||||
}
|
||||
|
||||
static guint32
|
||||
coerce_route_table (NMDevice *device,
|
||||
int addr_family,
|
||||
guint32 route_table,
|
||||
gboolean is_user_config)
|
||||
{
|
||||
NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD (device);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
gboolean auto_default_route_enabled;
|
||||
|
||||
if (route_table != 0u)
|
||||
return route_table;
|
||||
|
||||
_auto_default_route_init (self);
|
||||
|
||||
auto_default_route_enabled = (addr_family == AF_INET)
|
||||
? priv->auto_default_route_enabled_4
|
||||
: priv->auto_default_route_enabled_6;
|
||||
|
||||
if (auto_default_route_enabled) {
|
||||
/* we need to enable full-sync mode of all routing tables. */
|
||||
_LOGT (LOGD_DEVICE, "coerce ipv%c.route-table setting to \"main\" (table 254) as we enable auto-default-route handling",
|
||||
nm_utils_addr_family_to_char (addr_family));
|
||||
return RT_TABLE_MAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_peer_data_equal (gconstpointer ptr_a, gconstpointer ptr_b)
|
||||
{
|
||||
|
|
@ -1084,6 +1487,8 @@ link_config (NMDeviceWireGuard *self,
|
|||
_LOGT (LOGD_DEVICE, "wireguard link config (%s, %s)...",
|
||||
reason, _link_config_mode_to_string (config_mode));
|
||||
|
||||
_auto_default_route_init (self);
|
||||
|
||||
if (!priv->dns_manager) {
|
||||
priv->dns_manager = g_object_ref (nm_dns_manager_get ());
|
||||
g_signal_connect (priv->dns_manager, NM_DNS_MANAGER_CONFIG_CHANGED, G_CALLBACK (_dns_config_changed), self);
|
||||
|
|
@ -1130,7 +1535,7 @@ link_config (NMDeviceWireGuard *self,
|
|||
wg_lnk.listen_port = nm_setting_wireguard_get_listen_port (s_wg);
|
||||
wg_change_flags |= NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT;
|
||||
|
||||
wg_lnk.fwmark = nm_setting_wireguard_get_fwmark (s_wg);
|
||||
wg_lnk.fwmark = priv->auto_default_route_fwmark;
|
||||
wg_change_flags |= NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK;
|
||||
|
||||
if (nm_utils_base64secret_decode (nm_setting_wireguard_get_private_key (s_wg),
|
||||
|
|
@ -1256,6 +1661,7 @@ static NMIPConfig *
|
|||
_get_dev2_ip_config (NMDeviceWireGuard *self,
|
||||
int addr_family)
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
gs_unref_object NMIPConfig *ip_config = NULL;
|
||||
NMConnection *connection;
|
||||
NMSettingWireGuard *s_wg;
|
||||
|
|
@ -1264,6 +1670,9 @@ _get_dev2_ip_config (NMDeviceWireGuard *self,
|
|||
int ip_ifindex;
|
||||
guint32 route_metric;
|
||||
guint32 route_table_coerced;
|
||||
gboolean auto_default_route_enabled;
|
||||
|
||||
_auto_default_route_init (self);
|
||||
|
||||
connection = nm_device_get_applied_connection (NM_DEVICE (self));
|
||||
|
||||
|
|
@ -1303,6 +1712,10 @@ _get_dev2_ip_config (NMDeviceWireGuard *self,
|
|||
|
||||
route_table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (NM_DEVICE (self), addr_family));
|
||||
|
||||
auto_default_route_enabled = (addr_family == AF_INET)
|
||||
? priv->auto_default_route_enabled_4
|
||||
: priv->auto_default_route_enabled_6;
|
||||
|
||||
n_peers = nm_setting_wireguard_get_peers_len (s_wg);
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
NMWireGuardPeer *peer = nm_setting_wireguard_get_peer (s_wg, i);
|
||||
|
|
@ -1316,6 +1729,7 @@ _get_dev2_ip_config (NMDeviceWireGuard *self,
|
|||
const char *aip;
|
||||
gboolean valid;
|
||||
int prefix;
|
||||
guint32 rtable_coerced;
|
||||
|
||||
aip = nm_wireguard_peer_get_allowed_ip (peer, j, &valid);
|
||||
|
||||
|
|
@ -1335,13 +1749,24 @@ _get_dev2_ip_config (NMDeviceWireGuard *self,
|
|||
|
||||
nm_utils_ipx_address_clear_host_address (addr_family, &addrbin, NULL, prefix);
|
||||
|
||||
rtable_coerced = route_table_coerced;
|
||||
|
||||
if ( prefix == 0
|
||||
&& auto_default_route_enabled) {
|
||||
/* In auto-default-route mode, we place the default route in a table that
|
||||
* has the same number as the fwmark. wg-quick does that too. If you don't
|
||||
* like that, configure the rules and the default-route explicitly in the
|
||||
* connection profile. */
|
||||
rtable_coerced = nm_platform_route_table_coerce (priv->auto_default_route_fwmark);
|
||||
}
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
rt.r4 = (NMPlatformIP4Route) {
|
||||
.network = addrbin.addr4,
|
||||
.plen = prefix,
|
||||
.ifindex = ip_ifindex,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
.table_coerced = route_table_coerced,
|
||||
.table_coerced = rtable_coerced,
|
||||
.metric = route_metric,
|
||||
};
|
||||
} else {
|
||||
|
|
@ -1350,7 +1775,7 @@ _get_dev2_ip_config (NMDeviceWireGuard *self,
|
|||
.plen = prefix,
|
||||
.ifindex = ip_ifindex,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
.table_coerced = route_table_coerced,
|
||||
.table_coerced = rtable_coerced,
|
||||
.metric = route_metric,
|
||||
};
|
||||
}
|
||||
|
|
@ -1405,21 +1830,29 @@ get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source)
|
|||
out_source);
|
||||
}
|
||||
|
||||
static void
|
||||
_device_cleanup (NMDeviceWireGuard *self)
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
|
||||
_peers_remove_all (priv);
|
||||
|
||||
_secrets_cancel (self);
|
||||
|
||||
priv->auto_default_route_initialized = FALSE;
|
||||
priv->auto_default_route_priority_initialized = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
device_state_changed (NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason)
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv;
|
||||
|
||||
if (new_state <= NM_DEVICE_STATE_ACTIVATED)
|
||||
return;
|
||||
|
||||
priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (device);
|
||||
|
||||
_peers_remove_all (priv);
|
||||
_secrets_cancel (NM_DEVICE_WIREGUARD (device));
|
||||
_device_cleanup (NM_DEVICE_WIREGUARD (device));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1440,6 +1873,8 @@ can_reapply_change (NMDevice *device,
|
|||
NM_SETTING_WIREGUARD_SETTING_NAME,
|
||||
error,
|
||||
NM_SETTING_WIREGUARD_FWMARK,
|
||||
NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE,
|
||||
NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
NM_SETTING_WIREGUARD_PEERS,
|
||||
NM_SETTING_WIREGUARD_PEER_ROUTES,
|
||||
|
|
@ -1461,9 +1896,12 @@ reapply_connection (NMDevice *device,
|
|||
NMConnection *con_new)
|
||||
{
|
||||
NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD (device);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
gs_unref_object NMIPConfig *ip4_config = NULL;
|
||||
gs_unref_object NMIPConfig *ip6_config = NULL;
|
||||
|
||||
priv->auto_default_route_refresh = TRUE;
|
||||
|
||||
ip4_config = _get_dev2_ip_config (self, AF_INET);
|
||||
ip6_config = _get_dev2_ip_config (self, AF_INET6);
|
||||
|
||||
|
|
@ -1567,11 +2005,8 @@ static void
|
|||
dispose (GObject *object)
|
||||
{
|
||||
NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD (object);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self);
|
||||
|
||||
_secrets_cancel (self);
|
||||
|
||||
_peers_remove_all (priv);
|
||||
_device_cleanup (self);
|
||||
|
||||
G_OBJECT_CLASS (nm_device_wireguard_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
@ -1633,6 +2068,8 @@ nm_device_wireguard_class_init (NMDeviceWireGuardClass *klass)
|
|||
device_class->can_reapply_change = can_reapply_change;
|
||||
device_class->reapply_connection = reapply_connection;
|
||||
device_class->get_configured_mtu = get_configured_mtu;
|
||||
device_class->get_extra_rules = get_extra_rules;
|
||||
device_class->coerce_route_table = coerce_route_table;
|
||||
|
||||
obj_properties[PROP_PUBLIC_KEY] =
|
||||
g_param_spec_variant (NM_DEVICE_WIREGUARD_PUBLIC_KEY,
|
||||
|
|
|
|||
|
|
@ -2265,9 +2265,11 @@ _get_route_table (NMDevice *self,
|
|||
int addr_family)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMDeviceClass *klass;
|
||||
NMConnection *connection;
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint32 route_table = 0;
|
||||
gboolean is_user_config = TRUE;
|
||||
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
|
|
@ -2288,16 +2290,26 @@ _get_route_table (NMDevice *self,
|
|||
route_table = nm_setting_ip_config_get_route_table (s_ip);
|
||||
}
|
||||
if (route_table == 0u) {
|
||||
route_table = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
|
||||
addr_family == AF_INET
|
||||
? NM_CON_DEFAULT ("ipv4.route-table")
|
||||
: NM_CON_DEFAULT ("ipv6.route-table"),
|
||||
self,
|
||||
0,
|
||||
G_MAXUINT32,
|
||||
0);
|
||||
gint64 v;
|
||||
|
||||
v = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
|
||||
addr_family == AF_INET
|
||||
? NM_CON_DEFAULT ("ipv4.route-table")
|
||||
: NM_CON_DEFAULT ("ipv6.route-table"),
|
||||
self,
|
||||
0,
|
||||
G_MAXUINT32,
|
||||
-1);
|
||||
if (v != -1) {
|
||||
route_table = v;
|
||||
is_user_config = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
klass = NM_DEVICE_GET_CLASS (self);
|
||||
if (klass->coerce_route_table)
|
||||
route_table = klass->coerce_route_table (self, addr_family, route_table, is_user_config);
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
priv->v4_route_table_initialized = TRUE;
|
||||
priv->v4_route_table = route_table;
|
||||
|
|
@ -6587,11 +6599,15 @@ _routing_rules_sync (NMDevice *self,
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMPRulesManager *rules_manager = nm_netns_get_rules_manager (nm_device_get_netns (self));
|
||||
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
||||
gboolean untrack_only_dirty = FALSE;
|
||||
gboolean keep_deleted_rules;
|
||||
gpointer user_tag;
|
||||
gpointer user_tag_1;
|
||||
gpointer user_tag_2;
|
||||
|
||||
user_tag = priv;
|
||||
/* take two arbitrary user-tag pointers that belong to @self. */
|
||||
user_tag_1 = &priv->v4_route_table;
|
||||
user_tag_2 = &priv->v6_route_table;
|
||||
|
||||
if (set_mode == NM_TERNARY_TRUE) {
|
||||
NMConnection *applied_connection;
|
||||
|
|
@ -6600,7 +6616,9 @@ _routing_rules_sync (NMDevice *self,
|
|||
int is_ipv4;
|
||||
|
||||
untrack_only_dirty = TRUE;
|
||||
nmp_rules_manager_set_dirty (rules_manager, user_tag);
|
||||
nmp_rules_manager_set_dirty (rules_manager, user_tag_1);
|
||||
if (klass->get_extra_rules)
|
||||
nmp_rules_manager_set_dirty (rules_manager, user_tag_2);
|
||||
|
||||
applied_connection = nm_device_get_applied_connection (self);
|
||||
|
||||
|
|
@ -6625,13 +6643,30 @@ _routing_rules_sync (NMDevice *self,
|
|||
nmp_rules_manager_track (rules_manager,
|
||||
&plrule,
|
||||
10,
|
||||
user_tag,
|
||||
user_tag_1,
|
||||
NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
if (klass->get_extra_rules) {
|
||||
gs_unref_ptrarray GPtrArray *extra_rules = NULL;
|
||||
|
||||
extra_rules = klass->get_extra_rules (self);
|
||||
if (extra_rules) {
|
||||
for (i = 0; i < extra_rules->len; i++) {
|
||||
nmp_rules_manager_track (rules_manager,
|
||||
NMP_OBJECT_CAST_ROUTING_RULE (extra_rules->pdata[i]),
|
||||
10,
|
||||
user_tag_2,
|
||||
NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_untrack_all (rules_manager, user_tag, !untrack_only_dirty);
|
||||
nmp_rules_manager_untrack_all (rules_manager, user_tag_1, !untrack_only_dirty);
|
||||
if (klass->get_extra_rules)
|
||||
nmp_rules_manager_untrack_all (rules_manager, user_tag_2, !untrack_only_dirty);
|
||||
|
||||
keep_deleted_rules = FALSE;
|
||||
if (set_mode == NM_TERNARY_DEFAULT) {
|
||||
|
|
@ -11532,6 +11567,12 @@ check_and_reapply_connection (NMDevice *self,
|
|||
|
||||
/**************************************************************************
|
||||
* Reapply changes
|
||||
*
|
||||
* Note that reapply_connection() is called as very first. This is for example
|
||||
* important for NMDeviceWireGuard, which implements coerce_route_table()
|
||||
* and get_extra_rules().
|
||||
* That is because NMDeviceWireGuard caches settings, so during reapply that
|
||||
* cache must be updated *first*.
|
||||
*************************************************************************/
|
||||
klass->reapply_connection (self, con_old, con_new);
|
||||
|
||||
|
|
@ -11550,6 +11591,8 @@ check_and_reapply_connection (NMDevice *self,
|
|||
nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new);
|
||||
nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new);
|
||||
|
||||
_routing_rules_sync (self, NM_TERNARY_TRUE);
|
||||
|
||||
reactivate_proxy_config (self);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -320,6 +320,12 @@ typedef struct _NMDeviceClass {
|
|||
|
||||
void (* set_enabled) (NMDevice *self, gboolean enabled);
|
||||
|
||||
/* let the subclass return additional NMPlatformRoutingRule (in form of NMPObject
|
||||
* pointers) that shall be added to the rules provided by this device.
|
||||
* The returned GPtrArray will be g_ptr_array_unref()'ed. The subclass may or
|
||||
* may not keep an additional reference and return this array again and again. */
|
||||
GPtrArray *(*get_extra_rules) (NMDevice *self);
|
||||
|
||||
/* allow derived classes to override the result of nm_device_autoconnect_allowed().
|
||||
* If the value changes, the class should call nm_device_emit_recheck_auto_activate(),
|
||||
* which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */
|
||||
|
|
@ -331,6 +337,13 @@ typedef struct _NMDeviceClass {
|
|||
|
||||
guint32 (*get_configured_mtu) (NMDevice *self, NMDeviceMtuSource *out_source);
|
||||
|
||||
/* allow the subclass to overwrite the routing table. This is mainly useful
|
||||
* to change from partial mode (route-table=0) to full-sync mode (route-table=254). */
|
||||
guint32 (*coerce_route_table) (NMDevice *self,
|
||||
int addr_family,
|
||||
guint32 route_table,
|
||||
gboolean is_user_config);
|
||||
|
||||
const char *(*get_auto_ip_config_method) (NMDevice *self, int addr_family);
|
||||
|
||||
/* Checks whether the connection is compatible with the device using
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ _nmp_object_new_from_class (const NMPClass *klass)
|
|||
}
|
||||
|
||||
NMPObject *
|
||||
nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plobj)
|
||||
nmp_object_new (NMPObjectType obj_type, gconstpointer plobj)
|
||||
{
|
||||
const NMPClass *klass = nmp_class_from_type (obj_type);
|
||||
NMPObject *obj;
|
||||
|
|
@ -2146,9 +2146,12 @@ nmp_lookup_init_object_by_addr_family (NMPLookup *lookup,
|
|||
NMPObject *o;
|
||||
|
||||
nm_assert (lookup);
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_ROUTING_RULE));
|
||||
|
||||
if (addr_family == AF_UNSPEC)
|
||||
return nmp_lookup_init_obj_type (lookup, obj_type);
|
||||
|
||||
nm_assert_addr_family (addr_family);
|
||||
o = _nmp_object_stackinit_from_type (&lookup->selector_obj, obj_type);
|
||||
NMP_OBJECT_CAST_ROUTING_RULE (o)->addr_family = addr_family;
|
||||
lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY;
|
||||
|
|
|
|||
|
|
@ -534,101 +534,27 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type)
|
|||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->obj_with_ifindex : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_LINK(obj) \
|
||||
#define _NMP_OBJECT_CAST(obj, field, ...) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_LINK); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->link : NULL; \
|
||||
nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), __VA_ARGS__)); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->field : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP_ADDRESS(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip_address : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ipx_address : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip4_address : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip6_address : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ipx_route : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP_ROUTE(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip_route : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP4_ROUTE(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ROUTE); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip4_route : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_IP6_ROUTE(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ROUTE); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->ip6_route : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_ROUTING_RULE(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_ROUTING_RULE); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->routing_rule : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_QDISC(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_QDISC); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->qdisc : NULL; \
|
||||
})
|
||||
|
||||
#define NMP_OBJECT_CAST_TFILTER(obj) \
|
||||
({ \
|
||||
typeof (obj) _obj = (obj); \
|
||||
\
|
||||
nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_TFILTER); \
|
||||
_obj ? &NM_CONSTCAST (NMPObject, _obj)->tfilter : NULL; \
|
||||
})
|
||||
#define NMP_OBJECT_CAST_LINK(obj) _NMP_OBJECT_CAST (obj, link, NMP_OBJECT_TYPE_LINK)
|
||||
#define NMP_OBJECT_CAST_IP_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
|
||||
#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ipx_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
|
||||
#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip4_address, NMP_OBJECT_TYPE_IP4_ADDRESS)
|
||||
#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip6_address, NMP_OBJECT_TYPE_IP6_ADDRESS)
|
||||
#define NMP_OBJECT_CAST_IP_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
|
||||
#define NMP_OBJECT_CAST_IPX_ROUTE(obj) _NMP_OBJECT_CAST (obj, ipx_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
|
||||
#define NMP_OBJECT_CAST_IP4_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip4_route, NMP_OBJECT_TYPE_IP4_ROUTE)
|
||||
#define NMP_OBJECT_CAST_IP6_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip6_route, NMP_OBJECT_TYPE_IP6_ROUTE)
|
||||
#define NMP_OBJECT_CAST_ROUTING_RULE(obj) _NMP_OBJECT_CAST (obj, routing_rule, NMP_OBJECT_TYPE_ROUTING_RULE)
|
||||
#define NMP_OBJECT_CAST_QDISC(obj) _NMP_OBJECT_CAST (obj, qdisc, NMP_OBJECT_TYPE_QDISC)
|
||||
#define NMP_OBJECT_CAST_TFILTER(obj) _NMP_OBJECT_CAST (obj, tfilter, NMP_OBJECT_TYPE_TFILTER)
|
||||
#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) _NMP_OBJECT_CAST (obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD)
|
||||
|
||||
static inline const NMPObject *
|
||||
nmp_object_ref (const NMPObject *obj)
|
||||
|
|
@ -673,7 +599,7 @@ nmp_object_unref (const NMPObject *obj)
|
|||
_changed; \
|
||||
})
|
||||
|
||||
NMPObject *nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plob);
|
||||
NMPObject *nmp_object_new (NMPObjectType obj_type, gconstpointer plobj);
|
||||
NMPObject *nmp_object_new_link (int ifindex);
|
||||
|
||||
const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue