mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-14 06:20:37 +01:00
core: merge branch 'th/l3cfg-1'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/583
This commit is contained in:
commit
4cc93e1f80
22 changed files with 2002 additions and 268 deletions
|
|
@ -2170,6 +2170,11 @@ src_libNetworkManager_la_SOURCES = \
|
|||
src/nm-checkpoint-manager.c \
|
||||
src/nm-checkpoint-manager.h \
|
||||
\
|
||||
src/nm-l3-config-data.c \
|
||||
src/nm-l3-config-data.h \
|
||||
src/nm-l3cfg.c \
|
||||
src/nm-l3cfg.h \
|
||||
\
|
||||
src/devices/nm-acd-manager.c \
|
||||
src/devices/nm-acd-manager.h \
|
||||
src/devices/nm-lldp-listener.c \
|
||||
|
|
|
|||
|
|
@ -352,6 +352,19 @@ nm_hash_obfuscate_ptr (guint static_seed, gconstpointer val)
|
|||
* values in a global context. */
|
||||
#define NM_HASH_OBFUSCATE_PTR(ptr) (nm_hash_obfuscate_ptr (1678382159u, ptr))
|
||||
|
||||
static inline const char *
|
||||
nm_hash_obfuscated_ptr_str (gconstpointer ptr, char buf[static 17])
|
||||
{
|
||||
int l;
|
||||
|
||||
nm_assert (buf);
|
||||
l = g_snprintf (buf, 17, NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR (ptr));
|
||||
nm_assert (l < 17);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define nm_hash_obfuscated_ptr_str_a(ptr) (nm_hash_obfuscated_ptr_str ((ptr), g_alloca (17)))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_HASH_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -700,24 +700,40 @@ static GParamSpec *obj_properties##suffix[_PROPERTY_ENUMS_LAST##suffix] = { NULL
|
|||
static inline void \
|
||||
_nm_gobject_notify_together_impl##suffix (obj_type *obj, guint n, const _PropertyEnums##suffix *props) \
|
||||
{ \
|
||||
const gboolean freeze_thaw = (n > 1); \
|
||||
GObject *const gobj = (GObject *) obj; \
|
||||
GParamSpec *pspec_first = NULL; \
|
||||
gboolean frozen = FALSE; \
|
||||
\
|
||||
nm_assert (G_IS_OBJECT (obj)); \
|
||||
nm_assert (n > 0); \
|
||||
\
|
||||
if (freeze_thaw) \
|
||||
g_object_freeze_notify ((GObject *) obj); \
|
||||
while (n-- > 0) { \
|
||||
const _PropertyEnums##suffix prop = *props++; \
|
||||
GParamSpec *pspec; \
|
||||
\
|
||||
if (prop != PROP_0##suffix) { \
|
||||
nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties##suffix)); \
|
||||
nm_assert (obj_properties##suffix[prop]); \
|
||||
g_object_notify_by_pspec ((GObject *) obj, obj_properties##suffix[prop]); \
|
||||
if (prop == PROP_0##suffix) \
|
||||
continue; \
|
||||
\
|
||||
nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties##suffix)); \
|
||||
pspec = obj_properties##suffix[prop]; \
|
||||
nm_assert (pspec); \
|
||||
\
|
||||
if (!frozen) { \
|
||||
if (!pspec_first) { \
|
||||
pspec_first = pspec; \
|
||||
continue; \
|
||||
} \
|
||||
frozen = TRUE; \
|
||||
g_object_freeze_notify (gobj); \
|
||||
g_object_notify_by_pspec (gobj, pspec_first); \
|
||||
} \
|
||||
g_object_notify_by_pspec (gobj, pspec); \
|
||||
} \
|
||||
if (freeze_thaw) \
|
||||
g_object_thaw_notify ((GObject *) obj); \
|
||||
\
|
||||
if (frozen) \
|
||||
g_object_thaw_notify (gobj); \
|
||||
else if (pspec_first) \
|
||||
g_object_notify_by_pspec (gobj, pspec_first); \
|
||||
} \
|
||||
\
|
||||
_nm_unused static inline void \
|
||||
|
|
@ -809,6 +825,26 @@ nm_g_object_unref (gpointer obj)
|
|||
_changed; \
|
||||
})
|
||||
|
||||
#define nm_g_object_ref_set_take(pp, obj) \
|
||||
({ \
|
||||
typeof (*(pp)) *const _pp = (pp); \
|
||||
typeof (*_pp) const _obj = (obj); \
|
||||
typeof (*_pp) _p; \
|
||||
gboolean _changed = FALSE; \
|
||||
\
|
||||
nm_assert (!_pp || !*_pp || G_IS_OBJECT (*_pp)); \
|
||||
nm_assert (!_obj || G_IS_OBJECT (_obj)); \
|
||||
\
|
||||
if ( _pp \
|
||||
&& ((_p = *_pp) != _obj)) { \
|
||||
*_pp = _obj; \
|
||||
nm_g_object_unref (_p); \
|
||||
_changed = TRUE; \
|
||||
} else \
|
||||
nm_g_object_unref (_obj); \
|
||||
_changed; \
|
||||
})
|
||||
|
||||
/* basically, replaces
|
||||
* g_clear_pointer (&location, g_free)
|
||||
* with
|
||||
|
|
|
|||
|
|
@ -965,7 +965,7 @@ nm_utils_parse_inaddr_prefix_bin (int addr_family,
|
|||
|
||||
slash = strchr (text, '/');
|
||||
if (slash)
|
||||
addrstr = addrstr_free = g_strndup (text, slash - text);
|
||||
addrstr = nm_strndup_a (300, text, slash - text, &addrstr_free);
|
||||
else
|
||||
addrstr = text;
|
||||
|
||||
|
|
@ -975,9 +975,12 @@ nm_utils_parse_inaddr_prefix_bin (int addr_family,
|
|||
if (slash) {
|
||||
/* For IPv4, `ip addr add` supports the prefix-length as a netmask. We don't
|
||||
* do that. */
|
||||
prefix = _nm_utils_ascii_str_to_int64 (slash + 1, 10,
|
||||
prefix = _nm_utils_ascii_str_to_int64 (&slash[1],
|
||||
10,
|
||||
0,
|
||||
addr_family == AF_INET ? 32 : 128,
|
||||
addr_family == AF_INET
|
||||
? 32
|
||||
: 128,
|
||||
-1);
|
||||
if (prefix == -1)
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -68,42 +68,6 @@ G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline char
|
||||
nm_utils_addr_family_to_char (int addr_family)
|
||||
{
|
||||
switch (addr_family) {
|
||||
case AF_UNSPEC: return 'X';
|
||||
case AF_INET: return '4';
|
||||
case AF_INET6: return '6';
|
||||
}
|
||||
g_return_val_if_reached ('?');
|
||||
}
|
||||
|
||||
static inline gsize
|
||||
nm_utils_addr_family_to_size (int addr_family)
|
||||
{
|
||||
switch (addr_family) {
|
||||
case AF_INET: return sizeof (in_addr_t);
|
||||
case AF_INET6: return sizeof (struct in6_addr);
|
||||
}
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_utils_addr_family_from_size (gsize len)
|
||||
{
|
||||
switch (len) {
|
||||
case sizeof (in_addr_t): return AF_INET;
|
||||
case sizeof (struct in6_addr): return AF_INET6;
|
||||
}
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
|
||||
#define nm_assert_addr_family(addr_family) \
|
||||
nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
guint8 addr_ptr[1];
|
||||
|
|
@ -1555,6 +1519,18 @@ nm_g_array_len (const GArray *arr)
|
|||
return arr ? arr->len : 0u;
|
||||
}
|
||||
|
||||
#define nm_g_array_append_new(arr, type) \
|
||||
({ \
|
||||
GArray *_arr = (arr); \
|
||||
gsize _l; \
|
||||
\
|
||||
nm_assert (_arr); \
|
||||
_l = ((gsize) _arr->len) + 1u; \
|
||||
nm_assert (_l > _arr->len); \
|
||||
g_array_set_size (_arr, _l); \
|
||||
&g_array_index (arr, type, _l); \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline guint
|
||||
|
|
@ -1779,6 +1755,17 @@ GSource *nm_utils_g_main_context_create_integrate_source (GMainContext *internal
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline GPtrArray *
|
||||
nm_strv_ptrarray_ensure (GPtrArray **p_arr)
|
||||
{
|
||||
nm_assert (p_arr);
|
||||
|
||||
if (G_UNLIKELY (!*p_arr))
|
||||
*p_arr = g_ptr_array_new_with_free_func (g_free);
|
||||
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_strv_ptrarray_add_string_take (GPtrArray *cmd,
|
||||
char *str)
|
||||
|
|
@ -1817,6 +1804,22 @@ nm_strv_ptrarray_take_gstring (GPtrArray *cmd,
|
|||
FALSE));
|
||||
}
|
||||
|
||||
static inline gssize
|
||||
nm_strv_ptrarray_find_first (const GPtrArray *strv,
|
||||
const char *str)
|
||||
{
|
||||
if (!strv)
|
||||
return -1;
|
||||
return nm_utils_strv_find_first ((char **) strv->pdata, strv->len, str);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_strv_ptrarray_contains (const GPtrArray *strv,
|
||||
const char *str)
|
||||
{
|
||||
return nm_strv_ptrarray_find_first (strv, str) >= 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int nm_utils_getpagesize (void);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,16 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_STATIC_ASSERT (NM_AF_UNSPEC == AF_UNSPEC);
|
||||
G_STATIC_ASSERT (NM_AF_INET == AF_INET);
|
||||
G_STATIC_ASSERT (NM_AF_INET6 == AF_INET6);
|
||||
|
||||
G_STATIC_ASSERT (NM_AF_INET_SIZE == sizeof (in_addr_t));
|
||||
G_STATIC_ASSERT (NM_AF_INET_SIZE == sizeof (struct in_addr));
|
||||
G_STATIC_ASSERT (NM_AF_INET6_SIZE == sizeof (struct in6_addr));
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_gpid (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -622,4 +622,58 @@ nm_steal_fd (int *p_fd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_AF_UNSPEC 0 /* AF_UNSPEC */
|
||||
#define NM_AF_INET 2 /* AF_INET */
|
||||
#define NM_AF_INET6 10 /* AF_INET6 */
|
||||
|
||||
#define NM_AF_INET_SIZE 4 /* sizeof (in_addr_t) */
|
||||
#define NM_AF_INET6_SIZE 16 /* sizeof (stuct in6_addr) */
|
||||
|
||||
static inline char
|
||||
nm_utils_addr_family_to_char (int addr_family)
|
||||
{
|
||||
switch (addr_family) {
|
||||
case NM_AF_UNSPEC: return 'X';
|
||||
case NM_AF_INET: return '4';
|
||||
case NM_AF_INET6: return '6';
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
return '?';
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
nm_utils_addr_family_to_size (int addr_family)
|
||||
{
|
||||
switch (addr_family) {
|
||||
case NM_AF_INET: return NM_AF_INET_SIZE;
|
||||
case NM_AF_INET6: return NM_AF_INET6_SIZE;
|
||||
}
|
||||
nm_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_utils_addr_family_from_size (size_t len)
|
||||
{
|
||||
switch (len) {
|
||||
case NM_AF_INET_SIZE: return NM_AF_INET;
|
||||
case NM_AF_INET6_SIZE: return NM_AF_INET6;
|
||||
}
|
||||
return NM_AF_UNSPEC;
|
||||
}
|
||||
|
||||
#define nm_assert_addr_family(addr_family) \
|
||||
nm_assert (NM_IN_SET ((addr_family), NM_AF_INET, NM_AF_INET6))
|
||||
|
||||
#define NM_IS_IPv4(addr_family) \
|
||||
({ \
|
||||
const int _addr_family = (addr_family); \
|
||||
\
|
||||
nm_assert_addr_family (_addr_family); \
|
||||
\
|
||||
(_addr_family == NM_AF_INET); \
|
||||
})
|
||||
|
||||
#endif /* __NM_STD_AUX_H__ */
|
||||
|
|
|
|||
|
|
@ -1186,7 +1186,7 @@ nm_utils_qdiscs_from_tc_setting (NMPlatform *platform,
|
|||
GET_ATTR ("limit", qdisc->tbf.limit, UINT32, uint32, 0);
|
||||
GET_ATTR ("latency", qdisc->tbf.latency, UINT32, uint32, 0);
|
||||
}
|
||||
#undef GET_ADDR
|
||||
#undef GET_ATTR
|
||||
|
||||
g_ptr_array_add (qdiscs, q);
|
||||
}
|
||||
|
|
@ -1263,3 +1263,106 @@ nm_utils_tfilters_from_tc_setting (NMPlatform *platform,
|
|||
|
||||
return tfilters;
|
||||
}
|
||||
|
||||
void
|
||||
nm_utils_ip_route_attribute_to_platform (int addr_family,
|
||||
NMIPRoute *s_route,
|
||||
NMPlatformIPRoute *r,
|
||||
guint32 route_table)
|
||||
{
|
||||
GVariant *variant;
|
||||
guint32 table;
|
||||
NMIPAddr addr;
|
||||
NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
|
||||
NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
|
||||
gboolean onlink;
|
||||
|
||||
nm_assert (s_route);
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (r);
|
||||
|
||||
#define GET_ATTR(name, dst, variant_type, type, dflt) \
|
||||
G_STMT_START { \
|
||||
GVariant *_variant = nm_ip_route_get_attribute (s_route, ""name""); \
|
||||
\
|
||||
if ( _variant \
|
||||
&& g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||||
(dst) = g_variant_get_ ## type (_variant); \
|
||||
else \
|
||||
(dst) = (dflt); \
|
||||
} G_STMT_END
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TYPE))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
guint8 type;
|
||||
|
||||
type = nm_utils_route_type_by_name (g_variant_get_string (variant, NULL));
|
||||
nm_assert (NM_IN_SET (type,
|
||||
RTN_UNICAST,
|
||||
RTN_LOCAL));
|
||||
|
||||
r->type_coerced = nm_platform_route_type_coerce (type);
|
||||
} else
|
||||
r->type_coerced = nm_platform_route_type_coerce (RTN_UNICAST);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
|
||||
|
||||
if ( !table
|
||||
&& r->type_coerced == nm_platform_route_type_coerce (RTN_LOCAL))
|
||||
r->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
|
||||
else
|
||||
r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
guint8 scope;
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_SCOPE, scope, BYTE, byte, RT_SCOPE_NOWHERE);
|
||||
r4->scope_inv = nm_platform_route_scope_inv (scope);
|
||||
}
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
|
||||
|
||||
r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, r->window, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, r->cwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, r->initcwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, r->initrwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, r->mtu, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, r->lock_window, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, r->lock_cwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, r->lock_initcwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, r->lock_initrwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, r->lock_mtu, BOOLEAN, boolean, FALSE);
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
if (inet_pton (addr_family, g_variant_get_string (variant, NULL), &addr) == 1) {
|
||||
if (addr_family == AF_INET)
|
||||
r4->pref_src = addr.addr4;
|
||||
else
|
||||
r6->pref_src = addr.addr6;
|
||||
}
|
||||
}
|
||||
|
||||
if ( addr_family == AF_INET6
|
||||
&& (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
int prefix;
|
||||
|
||||
if (nm_utils_parse_inaddr_prefix_bin (addr_family,
|
||||
g_variant_get_string (variant, NULL),
|
||||
NULL,
|
||||
&addr,
|
||||
&prefix)) {
|
||||
if (prefix < 0)
|
||||
prefix = 128;
|
||||
r6->src = addr.addr6;
|
||||
r6->src_plen = prefix;
|
||||
}
|
||||
}
|
||||
#undef GET_ATTR
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -141,4 +141,9 @@ GPtrArray *nm_utils_tfilters_from_tc_setting (NMPlatform *platform,
|
|||
NMSettingTCConfig *s_tc,
|
||||
int ip_ifindex);
|
||||
|
||||
void nm_utils_ip_route_attribute_to_platform (int addr_family,
|
||||
NMIPRoute *s_route,
|
||||
NMPlatformIPRoute *r,
|
||||
guint32 route_table);
|
||||
|
||||
#endif /* __NETWORKMANAGER_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -285,6 +285,16 @@ typedef struct _NMDevicePrivate {
|
|||
char * udi;
|
||||
char * path;
|
||||
|
||||
union {
|
||||
NML3Cfg *const l3cfg;
|
||||
NML3Cfg *l3cfg_;
|
||||
};
|
||||
|
||||
union {
|
||||
NML3Cfg *const ip_l3cfg;
|
||||
NML3Cfg *ip_l3cfg_;
|
||||
};
|
||||
|
||||
union {
|
||||
const char *const iface;
|
||||
char * iface_;
|
||||
|
|
@ -1761,6 +1771,45 @@ nm_device_get_iface (NMDevice *self)
|
|||
return NM_DEVICE_GET_PRIVATE (self)->iface;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_ifindex (NMDevice *self, int ifindex, gboolean is_ip_ifindex)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gs_unref_object NML3Cfg *l3cfg_old = NULL;
|
||||
NML3Cfg **p_l3cfg;
|
||||
int *p_ifindex;
|
||||
|
||||
if (ifindex < 0)
|
||||
ifindex = 0;
|
||||
|
||||
p_ifindex = is_ip_ifindex
|
||||
? &priv->ip_ifindex_
|
||||
: &priv->ifindex_;
|
||||
|
||||
if (*p_ifindex == ifindex)
|
||||
return FALSE;
|
||||
|
||||
*p_ifindex = ifindex;
|
||||
|
||||
p_l3cfg = is_ip_ifindex
|
||||
? &priv->ip_l3cfg_
|
||||
: &priv->l3cfg_;
|
||||
|
||||
l3cfg_old = g_steal_pointer (p_l3cfg);
|
||||
if (ifindex > 0)
|
||||
*p_l3cfg = nm_netns_access_l3cfg (priv->netns, ifindex);
|
||||
|
||||
_LOGD (LOGD_DEVICE,
|
||||
"ifindex: set %sifindex %d%s%s%s%s%s%s",
|
||||
is_ip_ifindex ? "ip-" : "",
|
||||
ifindex,
|
||||
NM_PRINT_FMT_QUOTED (l3cfg_old, " (old-l3cfg: ", nm_hash_obfuscated_ptr_str_a (l3cfg_old), ")", ""),
|
||||
NM_PRINT_FMT_QUOTED (*p_l3cfg, " (l3cfg: ", nm_hash_obfuscated_ptr_str_a (*p_l3cfg), ")", ""));
|
||||
|
||||
_notify (self, PROP_IFINDEX);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_take_over_link:
|
||||
* @self: the #NMDevice
|
||||
|
|
@ -1825,10 +1874,7 @@ nm_device_take_over_link (NMDevice *self, int ifindex, char **old_name, GError *
|
|||
NM_SET_OUT (old_name, g_steal_pointer (&name));
|
||||
}
|
||||
|
||||
if (priv->ifindex != ifindex) {
|
||||
priv->ifindex_ = ifindex;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
}
|
||||
_set_ifindex (self, ifindex, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1931,7 +1977,8 @@ _set_ip_ifindex (NMDevice *self,
|
|||
NM_PRINT_FMT_QUOTE_STRING (ifname),
|
||||
ifindex);
|
||||
|
||||
priv->ip_ifindex_ = ifindex;
|
||||
_set_ifindex (self, ifindex, TRUE);
|
||||
|
||||
if (!eq_name) {
|
||||
g_free (priv->ip_iface_);
|
||||
priv->ip_iface_ = g_strdup (ifname);
|
||||
|
|
@ -2003,36 +2050,6 @@ nm_device_set_ip_iface (NMDevice *self, const char *ifname)
|
|||
return ifindex > 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ip_iface_update (NMDevice *self, const char *ip_iface)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
g_return_val_if_fail (priv->ip_iface, FALSE);
|
||||
g_return_val_if_fail (priv->ip_ifindex > 0, FALSE);
|
||||
g_return_val_if_fail (ip_iface, FALSE);
|
||||
|
||||
if (!ip_iface[0])
|
||||
return FALSE;
|
||||
|
||||
if (nm_streq (priv->ip_iface, ip_iface))
|
||||
return FALSE;
|
||||
|
||||
_LOGI (LOGD_DEVICE, "ip-ifname: interface index %d renamed ip_iface (%d) from '%s' to '%s'",
|
||||
priv->ifindex,
|
||||
priv->ip_ifindex,
|
||||
priv->ip_iface,
|
||||
ip_iface);
|
||||
g_free (priv->ip_iface_);
|
||||
priv->ip_iface_ = g_strdup (ip_iface);
|
||||
_notify (self, PROP_IP_IFACE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
|
|
@ -2197,17 +2214,23 @@ _stats_update_counters (NMDevice *self,
|
|||
guint64 rx_bytes)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
gboolean tx_changed = FALSE;
|
||||
gboolean rx_changed = FALSE;
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->stats.tx_bytes != tx_bytes) {
|
||||
priv->stats.tx_bytes = tx_bytes;
|
||||
_notify (self, PROP_STATISTICS_TX_BYTES);
|
||||
tx_changed = TRUE;
|
||||
}
|
||||
if (priv->stats.rx_bytes != rx_bytes) {
|
||||
priv->stats.rx_bytes = rx_bytes;
|
||||
_notify (self, PROP_STATISTICS_RX_BYTES);
|
||||
rx_changed = TRUE;
|
||||
}
|
||||
|
||||
nm_gobject_notify_together (self,
|
||||
tx_changed ? PROP_STATISTICS_TX_BYTES : PROP_0,
|
||||
rx_changed ? PROP_STATISTICS_RX_BYTES : PROP_0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4463,23 +4486,42 @@ device_ip_link_changed (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
const NMPlatformLink *pllink;
|
||||
const char *ip_iface;
|
||||
|
||||
priv->device_ip_link_changed_id = 0;
|
||||
|
||||
if (!priv->ip_ifindex)
|
||||
if (priv->ip_ifindex <= 0)
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
nm_assert (priv->ip_iface);
|
||||
|
||||
pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ip_ifindex);
|
||||
if (!pllink)
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
if (priv->ifindex <= 0 && pllink->mtu)
|
||||
if ( priv->ifindex <= 0
|
||||
&& pllink->mtu)
|
||||
_set_mtu (self, pllink->mtu);
|
||||
|
||||
_stats_update_counters_from_pllink (self, pllink);
|
||||
|
||||
if (_ip_iface_update (self, pllink->name))
|
||||
ip_iface = pllink->name;
|
||||
|
||||
if (!ip_iface[0])
|
||||
return FALSE;
|
||||
|
||||
if (!nm_streq (priv->ip_iface, ip_iface)) {
|
||||
_LOGI (LOGD_DEVICE, "ip-ifname: interface index %d renamed ip_iface (%d) from '%s' to '%s'",
|
||||
priv->ifindex,
|
||||
priv->ip_ifindex,
|
||||
priv->ip_iface,
|
||||
ip_iface);
|
||||
g_free (priv->ip_iface_);
|
||||
priv->ip_iface_ = g_strdup (ip_iface);
|
||||
_notify (self, PROP_IP_IFACE);
|
||||
|
||||
nm_device_update_dynamic_ip_setup (self);
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
|
@ -4695,7 +4737,7 @@ nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
const char *str;
|
||||
int ifindex;
|
||||
gboolean ifindex_changed;
|
||||
guint32 mtu;
|
||||
|
||||
if (!NM_DEVICE_GET_CLASS (self)->can_update_from_platform_link (self, plink))
|
||||
|
|
@ -4740,12 +4782,12 @@ nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink
|
|||
mtu = plink ? plink->mtu : 0;
|
||||
_set_mtu (self, mtu);
|
||||
|
||||
ifindex = plink ? plink->ifindex : 0;
|
||||
if (priv->ifindex != ifindex) {
|
||||
priv->ifindex_ = ifindex;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
ifindex_changed = _set_ifindex (self,
|
||||
plink ? plink->ifindex : 0,
|
||||
FALSE);
|
||||
|
||||
if (ifindex_changed)
|
||||
NM_DEVICE_GET_CLASS (self)->link_changed (self, plink);
|
||||
}
|
||||
|
||||
device_update_interface_flags (self, plink);
|
||||
}
|
||||
|
|
@ -5215,11 +5257,8 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
|
|||
|
||||
_parent_set_ifindex (self, 0, FALSE);
|
||||
|
||||
if (priv->ifindex > 0) {
|
||||
priv->ifindex_ = 0;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
}
|
||||
priv->ip_ifindex_ = 0;
|
||||
_set_ifindex (self, 0, FALSE);
|
||||
_set_ifindex (self, 0, TRUE);
|
||||
if (nm_clear_g_free (&priv->ip_iface_))
|
||||
_notify (self, PROP_IP_IFACE);
|
||||
|
||||
|
|
@ -17788,7 +17827,7 @@ constructor (GType type,
|
|||
pllink = nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface);
|
||||
|
||||
if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) {
|
||||
priv->ifindex_ = pllink->ifindex;
|
||||
_set_ifindex (self, pllink->ifindex, FALSE);
|
||||
priv->up = NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP);
|
||||
}
|
||||
}
|
||||
|
|
@ -17908,10 +17947,8 @@ dispose (GObject *object)
|
|||
|
||||
carrier_disconnected_action_cancel (self);
|
||||
|
||||
if (priv->ifindex > 0) {
|
||||
priv->ifindex_ = 0;
|
||||
_notify (self, PROP_IFINDEX);
|
||||
}
|
||||
_set_ifindex (self, 0, FALSE);
|
||||
_set_ifindex (self, 0, TRUE);
|
||||
|
||||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self);
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ sources = files(
|
|||
'nm-auth-manager.c',
|
||||
'nm-auth-utils.c',
|
||||
'nm-dbus-manager.c',
|
||||
'nm-l3-config-data.c',
|
||||
'nm-l3cfg.c',
|
||||
'nm-checkpoint.c',
|
||||
'nm-checkpoint-manager.c',
|
||||
'nm-config.c',
|
||||
|
|
|
|||
|
|
@ -400,12 +400,12 @@ _nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NM
|
|||
&& NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cmp), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE))
|
||||
|| NMP_OBJECT_GET_TYPE (obj_cur) == NMP_OBJECT_GET_TYPE (obj_cmp));
|
||||
nm_assert ( !obj_cur
|
||||
|| nm_ip_config_best_default_route_is (obj_cur));
|
||||
|| nmp_object_ip_route_is_best_defaut_route (obj_cur));
|
||||
|
||||
/* assumes that @obj_cur is already the best default route (or NULL). It checks whether
|
||||
* @obj_cmp is also a default route and returns the best of both. */
|
||||
if ( obj_cmp
|
||||
&& nm_ip_config_best_default_route_is (obj_cmp)) {
|
||||
&& nmp_object_ip_route_is_best_defaut_route (obj_cmp)) {
|
||||
guint32 metric_cur, metric_cmp;
|
||||
|
||||
if (!obj_cur)
|
||||
|
|
@ -436,23 +436,12 @@ _nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NM
|
|||
return obj_cur;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate)
|
||||
{
|
||||
if (new_candidate == *best_default_route)
|
||||
return FALSE;
|
||||
nmp_object_ref (new_candidate);
|
||||
nm_clear_nmp_object (best_default_route);
|
||||
*best_default_route = new_candidate;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate)
|
||||
{
|
||||
new_candidate = _nm_ip_config_best_default_route_find_better (*best_default_route,
|
||||
new_candidate);
|
||||
return _nm_ip_config_best_default_route_set (best_default_route, new_candidate);
|
||||
return nmp_object_ref_set (best_default_route, new_candidate);
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
|
|
@ -858,110 +847,6 @@ nm_ip4_config_commit (const NMIP4Config *self,
|
|||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
_nm_ip_config_merge_route_attributes (int addr_family,
|
||||
NMIPRoute *s_route,
|
||||
NMPlatformIPRoute *r,
|
||||
guint32 route_table)
|
||||
{
|
||||
GVariant *variant;
|
||||
guint32 table;
|
||||
NMIPAddr addr;
|
||||
NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
|
||||
NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
|
||||
gboolean onlink;
|
||||
|
||||
nm_assert (s_route);
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (r);
|
||||
|
||||
#define GET_ATTR(name, dst, variant_type, type, dflt) \
|
||||
G_STMT_START { \
|
||||
GVariant *_variant = nm_ip_route_get_attribute (s_route, ""name""); \
|
||||
\
|
||||
if ( _variant \
|
||||
&& g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||||
(dst) = g_variant_get_ ## type (_variant); \
|
||||
else \
|
||||
(dst) = (dflt); \
|
||||
} G_STMT_END
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TYPE))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
guint8 type;
|
||||
|
||||
type = nm_utils_route_type_by_name (g_variant_get_string (variant, NULL));
|
||||
nm_assert (NM_IN_SET (type,
|
||||
RTN_UNICAST,
|
||||
RTN_LOCAL));
|
||||
|
||||
r->type_coerced = nm_platform_route_type_coerce (type);
|
||||
} else
|
||||
r->type_coerced = nm_platform_route_type_coerce (RTN_UNICAST);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
|
||||
|
||||
if ( !table
|
||||
&& r->type_coerced == nm_platform_route_type_coerce (RTN_LOCAL))
|
||||
r->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
|
||||
else
|
||||
r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
guint8 scope;
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_SCOPE, scope, BYTE, byte, RT_SCOPE_NOWHERE);
|
||||
r4->scope_inv = nm_platform_route_scope_inv (scope);
|
||||
}
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
|
||||
|
||||
r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u);
|
||||
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, r->window, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND, r->cwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, r->initcwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, r->initrwnd, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU, r->mtu, UINT32, uint32, 0);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, r->lock_window, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, r->lock_cwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, r->lock_initcwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, r->lock_initrwnd, BOOLEAN, boolean, FALSE);
|
||||
GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, r->lock_mtu, BOOLEAN, boolean, FALSE);
|
||||
|
||||
if ( (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
if (inet_pton (addr_family, g_variant_get_string (variant, NULL), &addr) == 1) {
|
||||
if (addr_family == AF_INET)
|
||||
r4->pref_src = addr.addr4;
|
||||
else
|
||||
r6->pref_src = addr.addr6;
|
||||
}
|
||||
}
|
||||
|
||||
if ( addr_family == AF_INET6
|
||||
&& (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM))
|
||||
&& g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
|
||||
gs_free char *string = NULL;
|
||||
guint8 plen = 128;
|
||||
char *sep;
|
||||
|
||||
string = g_variant_dup_string (variant, NULL);
|
||||
sep = strchr (string, '/');
|
||||
if (sep) {
|
||||
*sep = 0;
|
||||
plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255);
|
||||
}
|
||||
if ( plen <= 128
|
||||
&& inet_pton (AF_INET6, string, &addr) == 1) {
|
||||
r6->src = addr.addr6;
|
||||
r6->src_plen = plen;
|
||||
}
|
||||
}
|
||||
#undef GET_ATTR
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip4_config_merge_setting (NMIP4Config *self,
|
||||
NMSettingIPConfig *setting,
|
||||
|
|
@ -1051,10 +936,10 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
|
|||
|
||||
route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen);
|
||||
|
||||
_nm_ip_config_merge_route_attributes (AF_INET,
|
||||
s_route,
|
||||
NM_PLATFORM_IP_ROUTE_CAST (&route),
|
||||
route_table);
|
||||
nm_utils_ip_route_attribute_to_platform (AF_INET,
|
||||
s_route,
|
||||
NM_PLATFORM_IP_ROUTE_CAST (&route),
|
||||
route_table);
|
||||
_add_route (self, NULL, &route, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1505,8 +1390,8 @@ nm_ip4_config_subtract (NMIP4Config *dst,
|
|||
}
|
||||
}
|
||||
if (changed_default_route) {
|
||||
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
|
||||
_nm_ip4_config_best_default_route_find (dst));
|
||||
nmp_object_ref_set (&dst_priv->best_default_route,
|
||||
_nm_ip4_config_best_default_route_find (dst));
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1659,7 +1544,7 @@ _nm_ip4_config_intersect_helper (NMIP4Config *dst,
|
|||
nm_assert_not_reached ();
|
||||
changed = TRUE;
|
||||
}
|
||||
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) {
|
||||
if (nmp_object_ref_set (&dst_priv->best_default_route, new_best_default_route)) {
|
||||
nm_assert (changed);
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
}
|
||||
|
|
@ -1896,7 +1781,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
|
|||
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
||||
}
|
||||
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes, FALSE);
|
||||
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
|
||||
if (nmp_object_ref_set (&dst_priv->best_default_route, new_best_default_route))
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
_notify_routes (dst);
|
||||
}
|
||||
|
|
@ -2990,8 +2875,8 @@ nm_ip4_config_nmpobj_remove (NMIP4Config *self,
|
|||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
if (priv->best_default_route == obj_old) {
|
||||
if (_nm_ip_config_best_default_route_set (&priv->best_default_route,
|
||||
_nm_ip4_config_best_default_route_find (self)))
|
||||
if (nmp_object_ref_set (&priv->best_default_route,
|
||||
_nm_ip4_config_best_default_route_find (self)))
|
||||
_notify (self, PROP_GATEWAY);
|
||||
}
|
||||
_notify_routes (self);
|
||||
|
|
|
|||
|
|
@ -69,26 +69,7 @@ nm_ip_config_iter_ip4_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatfor
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
nm_ip_config_best_default_route_is (const NMPObject *obj)
|
||||
{
|
||||
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (obj);
|
||||
|
||||
/* return whether @obj is considered a default-route.
|
||||
*
|
||||
* NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because
|
||||
* at various places we act differently depending on whether there is a default-route
|
||||
* configured.
|
||||
*
|
||||
* Note that this only considers the main routing table. */
|
||||
return r
|
||||
&& NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
|
||||
&& nm_platform_route_table_is_main (r->table_coerced)
|
||||
&& r->type_coerced == nm_platform_route_type_coerce (1 /*RTN_UNICAST*/);
|
||||
}
|
||||
|
||||
const NMPObject *_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp);
|
||||
gboolean _nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate);
|
||||
gboolean _nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -108,11 +89,6 @@ const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex
|
|||
const NMPObject *needle,
|
||||
NMPlatformIPRouteCmpType cmp_type);
|
||||
|
||||
void _nm_ip_config_merge_route_attributes (int addr_family,
|
||||
NMIPRoute *s_route,
|
||||
NMPlatformIPRoute *r,
|
||||
guint32 route_table);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ())
|
||||
|
|
|
|||
|
|
@ -721,10 +721,10 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
|
|||
|
||||
nm_utils_ip6_address_clear_host_address (&route.network, &route.network, route.plen);
|
||||
|
||||
_nm_ip_config_merge_route_attributes (AF_INET6,
|
||||
s_route,
|
||||
NM_PLATFORM_IP_ROUTE_CAST (&route),
|
||||
route_table);
|
||||
nm_utils_ip_route_attribute_to_platform (AF_INET6,
|
||||
s_route,
|
||||
NM_PLATFORM_IP_ROUTE_CAST (&route),
|
||||
route_table);
|
||||
_add_route (self, NULL, &route, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1120,8 +1120,8 @@ nm_ip6_config_subtract (NMIP6Config *dst,
|
|||
}
|
||||
}
|
||||
if (changed_default_route) {
|
||||
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
|
||||
_nm_ip6_config_best_default_route_find (dst));
|
||||
nmp_object_ref_set (&dst_priv->best_default_route,
|
||||
_nm_ip6_config_best_default_route_find (dst));
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1244,7 +1244,7 @@ _nm_ip6_config_intersect_helper (NMIP6Config *dst,
|
|||
nm_assert_not_reached ();
|
||||
changed = TRUE;
|
||||
}
|
||||
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) {
|
||||
if (nmp_object_ref_set (&dst_priv->best_default_route, new_best_default_route)) {
|
||||
nm_assert (changed);
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
}
|
||||
|
|
@ -1481,7 +1481,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
|
|||
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
|
||||
}
|
||||
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, FALSE);
|
||||
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
|
||||
if (nmp_object_ref_set (&dst_priv->best_default_route, new_best_default_route))
|
||||
_notify (dst, PROP_GATEWAY);
|
||||
_notify_routes (dst);
|
||||
}
|
||||
|
|
@ -1955,7 +1955,7 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
|||
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
|
||||
changed = TRUE;
|
||||
|
||||
if (_nm_ip_config_best_default_route_set (&priv->best_default_route, new_best_default_route)) {
|
||||
if (nmp_object_ref_set (&priv->best_default_route, new_best_default_route)) {
|
||||
changed = TRUE;
|
||||
_notify (self, PROP_GATEWAY);
|
||||
}
|
||||
|
|
@ -2458,8 +2458,8 @@ nm_ip6_config_nmpobj_remove (NMIP6Config *self,
|
|||
break;
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
if (priv->best_default_route == obj_old) {
|
||||
if (_nm_ip_config_best_default_route_set (&priv->best_default_route,
|
||||
_nm_ip6_config_best_default_route_find (self)))
|
||||
if (nmp_object_ref_set (&priv->best_default_route,
|
||||
_nm_ip6_config_best_default_route_find (self)))
|
||||
_notify (self, PROP_GATEWAY);
|
||||
}
|
||||
_notify_routes (self);
|
||||
|
|
|
|||
868
src/nm-l3-config-data.c
Normal file
868
src/nm-l3-config-data.c
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-l3-config-data.h"
|
||||
|
||||
#include "nm-core-internal.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMDedupMultiIdxType parent;
|
||||
NMPObjectType obj_type;
|
||||
} DedupMultiIdxType;
|
||||
|
||||
struct _NML3ConfigData {
|
||||
NMDedupMultiIndex *multi_idx;
|
||||
|
||||
union {
|
||||
struct {
|
||||
DedupMultiIdxType idx_addresses_6;
|
||||
DedupMultiIdxType idx_addresses_4;
|
||||
};
|
||||
DedupMultiIdxType idx_addresses_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
DedupMultiIdxType idx_routes_6;
|
||||
DedupMultiIdxType idx_routes_4;
|
||||
};
|
||||
DedupMultiIdxType idx_routes_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
const NMPObject *best_default_route_6;
|
||||
const NMPObject *best_default_route_4;
|
||||
};
|
||||
const NMPObject *best_default_route_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
GArray *nameservers_6;
|
||||
GArray *nameservers_4;
|
||||
};
|
||||
GArray *nameservers_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
GPtrArray *domains_6;
|
||||
GPtrArray *domains_4;
|
||||
};
|
||||
GPtrArray *domains_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
GPtrArray *searches_6;
|
||||
GPtrArray *searches_4;
|
||||
};
|
||||
GPtrArray *searches_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
GPtrArray *dns_options_6;
|
||||
GPtrArray *dns_options_4;
|
||||
};
|
||||
GPtrArray *dns_options_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
int dns_priority_6;
|
||||
int dns_priority_4;
|
||||
};
|
||||
int dns_priority_x[2];
|
||||
};
|
||||
|
||||
NMSettingConnectionMdns mdns;
|
||||
NMSettingConnectionLlmnr llmnr;
|
||||
|
||||
int ref_count;
|
||||
|
||||
bool is_sealed:1;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_route_valid_4 (const NMPlatformIP4Route *r)
|
||||
{
|
||||
return r
|
||||
&& r->plen <= 32
|
||||
&& r->network == nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_route_valid_6 (const NMPlatformIP6Route *r)
|
||||
{
|
||||
struct in6_addr n;
|
||||
|
||||
return r
|
||||
&& r->plen <= 128
|
||||
&& (memcmp (&r->network,
|
||||
nm_utils_ip6_address_clear_host_address (&n, &r->network, r->plen),
|
||||
sizeof (n)) == 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_route_valid (int addr_family, gconstpointer r)
|
||||
{
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
return addr_family == AF_INET
|
||||
? _route_valid_4 (r)
|
||||
: _route_valid_6 (r);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
NM_IS_L3_CONFIG_DATA (const NML3ConfigData *self, gboolean allow_sealed)
|
||||
{
|
||||
return self
|
||||
&& self->ref_count > 0
|
||||
&& ( allow_sealed
|
||||
|| !self->is_sealed);
|
||||
}
|
||||
|
||||
static GArray *
|
||||
_garray_ensure_for_addrbin (GArray **p_arr,
|
||||
int addr_family)
|
||||
{
|
||||
nm_assert (p_arr);
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
if (G_UNLIKELY (!*p_arr)) {
|
||||
*p_arr = g_array_new (FALSE,
|
||||
FALSE,
|
||||
nm_utils_addr_family_to_size (addr_family));
|
||||
}
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
static void
|
||||
_idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type,
|
||||
const NMDedupMultiObj *obj,
|
||||
NMHashState *h)
|
||||
{
|
||||
nmp_object_id_hash_update ((NMPObject *) obj, h);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_idx_obj_id_equal (const NMDedupMultiIdxType *idx_type,
|
||||
const NMDedupMultiObj *obj_a,
|
||||
const NMDedupMultiObj *obj_b)
|
||||
{
|
||||
return nmp_object_id_equal ((NMPObject *) obj_a, (NMPObject *) obj_b);
|
||||
}
|
||||
|
||||
static void
|
||||
_idx_type_init (DedupMultiIdxType *idx_type,
|
||||
NMPObjectType obj_type)
|
||||
{
|
||||
static const NMDedupMultiIdxTypeClass idx_type_class = {
|
||||
.idx_obj_id_hash_update = _idx_obj_id_hash_update,
|
||||
.idx_obj_id_equal = _idx_obj_id_equal,
|
||||
};
|
||||
|
||||
nm_dedup_multi_idx_type_init (&idx_type->parent,
|
||||
&idx_type_class);
|
||||
idx_type->obj_type = obj_type;
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
nm_l3_config_data_new (NMDedupMultiIndex *multi_idx)
|
||||
{
|
||||
NML3ConfigData *self;
|
||||
|
||||
nm_assert (multi_idx);
|
||||
|
||||
self = g_slice_new (NML3ConfigData);
|
||||
*self = (NML3ConfigData) {
|
||||
.ref_count = 1,
|
||||
.multi_idx = nm_dedup_multi_index_ref (multi_idx),
|
||||
.mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT,
|
||||
.llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT,
|
||||
};
|
||||
|
||||
_idx_type_init (&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS);
|
||||
_idx_type_init (&self->idx_addresses_6, NMP_OBJECT_TYPE_IP4_ADDRESS);
|
||||
_idx_type_init (&self->idx_routes_4, NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||
_idx_type_init (&self->idx_routes_6, NMP_OBJECT_TYPE_IP6_ROUTE);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
nm_l3_config_data_ref (NML3ConfigData *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
self->ref_count++;
|
||||
return self;
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
nm_l3_config_data_ref_and_seal (NML3ConfigData *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
self->is_sealed = TRUE;
|
||||
self->ref_count++;
|
||||
return self;
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
nm_l3_config_data_seal (NML3ConfigData *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
self->is_sealed = TRUE;
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3_config_data_is_sealed (NML3ConfigData *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
return self->is_sealed;
|
||||
}
|
||||
|
||||
void
|
||||
nm_l3_config_data_unref (NML3ConfigData *self)
|
||||
{
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
if (--self->ref_count > 0)
|
||||
return;
|
||||
|
||||
nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_addresses_4.parent);
|
||||
nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_addresses_6.parent);
|
||||
nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_routes_4.parent);
|
||||
nm_dedup_multi_index_remove_idx (self->multi_idx, &self->idx_routes_6.parent);
|
||||
|
||||
nmp_object_unref (self->best_default_route_4);
|
||||
nmp_object_unref (self->best_default_route_6);
|
||||
|
||||
nm_clear_pointer (&self->nameservers_4, g_array_unref);
|
||||
nm_clear_pointer (&self->nameservers_6, g_array_unref);
|
||||
|
||||
nm_clear_pointer (&self->domains_4, g_ptr_array_unref);
|
||||
nm_clear_pointer (&self->domains_6, g_ptr_array_unref);
|
||||
|
||||
nm_clear_pointer (&self->searches_4, g_ptr_array_unref);
|
||||
nm_clear_pointer (&self->searches_6, g_ptr_array_unref);
|
||||
|
||||
nm_clear_pointer (&self->dns_options_4, g_ptr_array_unref);
|
||||
nm_clear_pointer (&self->dns_options_6, g_ptr_array_unref);
|
||||
|
||||
nm_dedup_multi_index_unref (self->multi_idx);
|
||||
|
||||
nm_g_slice_free (self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMDedupMultiHeadEntry *
|
||||
nm_l3_config_data_lookup_addresses (const NML3ConfigData *self,
|
||||
int addr_family)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
return nm_dedup_multi_index_lookup_head (self->multi_idx,
|
||||
&self->idx_addresses_x[NM_IS_IPv4 (addr_family)].parent,
|
||||
NULL);
|
||||
}
|
||||
|
||||
const NMDedupMultiHeadEntry *
|
||||
nm_l3_config_data_lookup_routes (const NML3ConfigData *self,
|
||||
int addr_family)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
return nm_dedup_multi_index_lookup_head (self->multi_idx,
|
||||
&self->idx_routes_x[NM_IS_IPv4 (addr_family)].parent,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_l3_config_data_add_obj (NMDedupMultiIndex *multi_idx,
|
||||
DedupMultiIdxType *idx_type,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformObject *pl_new,
|
||||
gboolean merge,
|
||||
gboolean append_force,
|
||||
const NMPObject **out_obj_old /* returns a reference! */,
|
||||
const NMPObject **out_obj_new /* does not return a reference */)
|
||||
{
|
||||
NMPObject obj_new_stackinit;
|
||||
const NMDedupMultiEntry *entry_old;
|
||||
const NMDedupMultiEntry *entry_new;
|
||||
|
||||
nm_assert (multi_idx);
|
||||
nm_assert (idx_type);
|
||||
nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS,
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
NMP_OBJECT_TYPE_IP6_ADDRESS,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
nm_assert (ifindex > 0);
|
||||
|
||||
/* we go through extra lengths to accept a full obj_new object. That one,
|
||||
* can be reused by increasing the ref-count. */
|
||||
if (!obj_new) {
|
||||
nm_assert (pl_new);
|
||||
obj_new = nmp_object_stackinit (&obj_new_stackinit, idx_type->obj_type, pl_new);
|
||||
NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (&obj_new_stackinit)->ifindex = ifindex;
|
||||
} else {
|
||||
nm_assert (!pl_new);
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (obj_new) == idx_type->obj_type);
|
||||
if (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj_new)->ifindex != ifindex) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (&obj_new_stackinit)->ifindex = ifindex;
|
||||
}
|
||||
}
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (obj_new) == idx_type->obj_type);
|
||||
nm_assert (nmp_object_is_alive (obj_new));
|
||||
|
||||
entry_old = nm_dedup_multi_index_lookup_obj (multi_idx, &idx_type->parent, obj_new);
|
||||
|
||||
if (entry_old) {
|
||||
gboolean modified = FALSE;
|
||||
const NMPObject *obj_old = entry_old->obj;
|
||||
|
||||
if (nmp_object_equal (obj_new, obj_old)) {
|
||||
nm_dedup_multi_entry_set_dirty (entry_old, FALSE);
|
||||
goto append_force_and_out;
|
||||
}
|
||||
|
||||
/* if @merge, we merge the new object with the existing one.
|
||||
* Otherwise, we replace it entirely. */
|
||||
if (merge) {
|
||||
switch (idx_type->obj_type) {
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
/* for addresses that we read from the kernel, we keep the timestamps as defined
|
||||
* by the previous source (item_old). The reason is, that the other source configured the lifetimes
|
||||
* with "what should be" and the kernel values are "what turned out after configuring it".
|
||||
*
|
||||
* For other sources, the longer lifetime wins. */
|
||||
if ( ( obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
|
||||
&& obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
|
||||
|| nm_platform_ip_address_cmp_expiry (NMP_OBJECT_CAST_IP_ADDRESS (obj_old), NMP_OBJECT_CAST_IP_ADDRESS(obj_new)) > 0) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.timestamp = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->timestamp;
|
||||
obj_new_stackinit.ip_address.lifetime = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->lifetime;
|
||||
obj_new_stackinit.ip_address.preferred = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->preferred;
|
||||
modified = TRUE;
|
||||
}
|
||||
|
||||
/* keep the maximum addr_source. */
|
||||
if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
/* keep the maximum rt_source. */
|
||||
if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( modified
|
||||
&& nmp_object_equal (obj_new, obj_old)) {
|
||||
nm_dedup_multi_entry_set_dirty (entry_old, FALSE);
|
||||
goto append_force_and_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nm_dedup_multi_index_add_full (multi_idx,
|
||||
&idx_type->parent,
|
||||
obj_new,
|
||||
append_force
|
||||
? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE
|
||||
: NM_DEDUP_MULTI_IDX_MODE_APPEND,
|
||||
NULL,
|
||||
entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
|
||||
NULL,
|
||||
&entry_new,
|
||||
out_obj_old)) {
|
||||
nm_assert_not_reached ();
|
||||
NM_SET_OUT (out_obj_new, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_obj_new, entry_new->obj);
|
||||
return TRUE;
|
||||
|
||||
append_force_and_out:
|
||||
NM_SET_OUT (out_obj_old, nmp_object_ref (entry_old->obj));
|
||||
NM_SET_OUT (out_obj_new, entry_old->obj);
|
||||
if (append_force) {
|
||||
if (nm_dedup_multi_entry_reorder (entry_old, NULL, TRUE))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const NMPObject *
|
||||
_l3_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp)
|
||||
{
|
||||
nm_assert ( !obj_cur
|
||||
|| NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cur), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
nm_assert ( !obj_cmp
|
||||
|| ( !obj_cur
|
||||
&& NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cmp), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE))
|
||||
|| NMP_OBJECT_GET_TYPE (obj_cur) == NMP_OBJECT_GET_TYPE (obj_cmp));
|
||||
nm_assert ( !obj_cur
|
||||
|| nmp_object_ip_route_is_best_defaut_route (obj_cur));
|
||||
|
||||
/* assumes that @obj_cur is already the best default route (or NULL). It checks whether
|
||||
* @obj_cmp is also a default route and returns the best of both. */
|
||||
if ( obj_cmp
|
||||
&& nmp_object_ip_route_is_best_defaut_route (obj_cmp)) {
|
||||
guint32 metric_cur, metric_cmp;
|
||||
|
||||
if (!obj_cur)
|
||||
return obj_cmp;
|
||||
|
||||
if (obj_cur == obj_cmp)
|
||||
return obj_cmp;
|
||||
|
||||
metric_cur = NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric;
|
||||
metric_cmp = NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric;
|
||||
|
||||
if (metric_cmp < metric_cur)
|
||||
return obj_cmp;
|
||||
|
||||
if (metric_cmp == metric_cur) {
|
||||
int c;
|
||||
|
||||
/* Routes have the same metric. We still want to deterministically
|
||||
* prefer one or the other. It's important to consistently choose one
|
||||
* or the other, so that the order doesn't matter how routes are added
|
||||
* (and merged). */
|
||||
c = nmp_object_cmp (obj_cur, obj_cmp);
|
||||
if (c != 0)
|
||||
return c < 0 ? obj_cur : obj_cmp;
|
||||
|
||||
/* as last resort, compare pointers. */
|
||||
if (((uintptr_t) ((void *) (obj_cmp))) < ((uintptr_t) ((void *) (obj_cur))))
|
||||
return obj_cmp;
|
||||
}
|
||||
}
|
||||
return obj_cur;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_l3_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate)
|
||||
{
|
||||
new_candidate = _l3_config_best_default_route_find_better (*best_default_route,
|
||||
new_candidate);
|
||||
return nmp_object_ref_set (best_default_route, new_candidate);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_add_route (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformIPRoute *pl_new,
|
||||
const NMPObject **out_obj_new,
|
||||
gboolean *out_changed_best_default_route)
|
||||
{
|
||||
const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family);
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
const NMPObject *obj_new_2;
|
||||
gboolean changed = FALSE;
|
||||
gboolean changed_best_default_route = FALSE;
|
||||
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (ifindex > 0);
|
||||
nm_assert ((!pl_new) != (!obj_new));
|
||||
nm_assert ( !pl_new
|
||||
|| _route_valid (addr_family, pl_new));
|
||||
nm_assert ( !obj_new
|
||||
|| ( NMP_OBJECT_GET_ADDR_FAMILY (obj_new) == addr_family
|
||||
&& _route_valid (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_new))));
|
||||
|
||||
if (_l3_config_data_add_obj (self->multi_idx,
|
||||
addr_family == AF_INET
|
||||
? &self->idx_routes_4
|
||||
: &self->idx_routes_6,
|
||||
ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) pl_new,
|
||||
TRUE,
|
||||
FALSE,
|
||||
&obj_old,
|
||||
&obj_new_2)) {
|
||||
|
||||
if ( self->best_default_route_x[IS_IPv4] == obj_old
|
||||
&& obj_old != obj_new_2) {
|
||||
changed_best_default_route = TRUE;
|
||||
nm_clear_nmp_object (&self->best_default_route_x[IS_IPv4]);
|
||||
}
|
||||
|
||||
if (_l3_config_best_default_route_merge (&self->best_default_route_x[IS_IPv4],
|
||||
obj_new_2))
|
||||
changed_best_default_route = TRUE;
|
||||
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
|
||||
NM_SET_OUT (out_changed_best_default_route, changed_best_default_route);
|
||||
return changed;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_add_address (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformIPAddress *pl_new)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (ifindex > 0);
|
||||
nm_assert ((!pl_new) != (!obj_new));
|
||||
nm_assert ( !obj_new
|
||||
|| NMP_OBJECT_GET_ADDR_FAMILY (obj_new) == addr_family);
|
||||
|
||||
return _l3_config_data_add_obj (self->multi_idx,
|
||||
addr_family == AF_INET
|
||||
? &self->idx_addresses_4
|
||||
: &self->idx_addresses_6,
|
||||
ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) pl_new,
|
||||
TRUE,
|
||||
FALSE,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_check_and_add_domain (GPtrArray **p_arr, const char *domain)
|
||||
{
|
||||
gs_free char *copy = NULL;
|
||||
gsize len;
|
||||
|
||||
nm_assert (p_arr);
|
||||
g_return_val_if_fail (domain, FALSE);
|
||||
|
||||
if (domain[0] == '\0')
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
if (domain[0] == '.' || strstr (domain, ".."))
|
||||
return FALSE;
|
||||
|
||||
len = strlen (domain);
|
||||
if (domain[len - 1] == '.') {
|
||||
copy = g_strndup (domain, len - 1);
|
||||
domain = copy;
|
||||
}
|
||||
|
||||
if (nm_strv_ptrarray_contains (*p_arr, domain))
|
||||
return FALSE;
|
||||
|
||||
nm_strv_ptrarray_add_string_take (nm_strv_ptrarray_ensure (p_arr),
|
||||
g_steal_pointer (©)
|
||||
?: g_strdup (domain));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_add_domain (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *domain)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
return _check_and_add_domain (&self->domains_x[NM_IS_IPv4 (addr_family)], domain);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_add_search (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *search)
|
||||
{
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
return _check_and_add_domain (&self->searches_x[NM_IS_IPv4 (addr_family)], search);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_add_dns_option (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *dns_option)
|
||||
{
|
||||
GPtrArray **p_arr;
|
||||
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
g_return_val_if_fail (dns_option, FALSE);
|
||||
|
||||
if (!dns_option[0])
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
p_arr = &self->dns_options_x[NM_IS_IPv4 (addr_family)];
|
||||
|
||||
if (nm_strv_ptrarray_contains (*p_arr, dns_option))
|
||||
return FALSE;
|
||||
|
||||
nm_strv_ptrarray_add_string_dup (nm_strv_ptrarray_ensure (p_arr),
|
||||
dns_option);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_l3_config_data_set_dns_priority (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int dns_priority)
|
||||
{
|
||||
int *p_val;
|
||||
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert_addr_family (addr_family);
|
||||
|
||||
p_val = &self->dns_priority_x[NM_IS_IPv4 (addr_family)];
|
||||
if (*p_val == dns_priority)
|
||||
return FALSE;
|
||||
|
||||
*p_val = dns_priority;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_init_from_connection_ip (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
NMConnection *connection,
|
||||
guint32 route_table,
|
||||
guint32 route_metric)
|
||||
{
|
||||
const gboolean IS_IPv4 = NM_IS_IPv4 (addr_family);
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint naddresses;
|
||||
guint nroutes;
|
||||
guint nnameservers;
|
||||
guint nsearches;
|
||||
const char *gateway_str;
|
||||
NMIPAddr gateway_bin;
|
||||
guint i;
|
||||
int idx;
|
||||
|
||||
nm_assert (NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
nm_assert (ifindex > 0);
|
||||
nm_assert_addr_family (addr_family);
|
||||
nm_assert (!connection || NM_IS_CONNECTION (connection));
|
||||
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
|
||||
if (!s_ip)
|
||||
return;
|
||||
|
||||
if ( !nm_setting_ip_config_get_never_default (s_ip)
|
||||
&& (gateway_str = nm_setting_ip_config_get_gateway (s_ip))
|
||||
&& inet_pton (addr_family, gateway_str, &gateway_bin) == 1
|
||||
&& !nm_ip_addr_is_null (addr_family, &gateway_bin)) {
|
||||
NMPlatformIPXRoute r;
|
||||
|
||||
if (IS_IPv4) {
|
||||
r.r4 = (NMPlatformIP4Route) {
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
.gateway = gateway_bin.addr4,
|
||||
.table_coerced = nm_platform_route_table_coerce (route_table),
|
||||
.metric = route_metric,
|
||||
};
|
||||
} else {
|
||||
r.r6 = (NMPlatformIP6Route) {
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
.gateway = gateway_bin.addr6,
|
||||
.table_coerced = nm_platform_route_table_coerce (route_table),
|
||||
.metric = route_metric,
|
||||
};
|
||||
}
|
||||
|
||||
_nm_l3_config_data_add_route (self, addr_family, ifindex, NULL, &r.rx, NULL, NULL);
|
||||
}
|
||||
|
||||
naddresses = nm_setting_ip_config_get_num_addresses (s_ip);
|
||||
for (i = 0; i < naddresses; i++) {
|
||||
NMIPAddress *s_addr = nm_setting_ip_config_get_address (s_ip, i);
|
||||
NMPlatformIPXAddress a;
|
||||
NMIPAddr addr_bin;
|
||||
GVariant *label;
|
||||
|
||||
nm_assert (nm_ip_address_get_family (s_addr) == addr_family);
|
||||
|
||||
nm_ip_address_get_address_binary (s_addr, &addr_bin);
|
||||
|
||||
if (IS_IPv4) {
|
||||
a.a4 = (NMPlatformIP4Address) {
|
||||
.address = addr_bin.addr4,
|
||||
.peer_address = addr_bin.addr4,
|
||||
.plen = nm_ip_address_get_prefix (s_addr),
|
||||
.lifetime = NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
.preferred = NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
};
|
||||
label = nm_ip_address_get_attribute (s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
||||
if (label)
|
||||
g_strlcpy (a.a4.label, g_variant_get_string (label, NULL), sizeof (a.a4.label));
|
||||
|
||||
nm_assert (a.a4.plen <= 32);
|
||||
} else {
|
||||
a.a6 = (NMPlatformIP6Address) {
|
||||
.address = addr_bin.addr6,
|
||||
.plen = nm_ip_address_get_prefix (s_addr),
|
||||
.lifetime = NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
.preferred = NM_PLATFORM_LIFETIME_PERMANENT,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
};
|
||||
|
||||
nm_assert (a.a6.plen <= 128);
|
||||
}
|
||||
|
||||
_nm_l3_config_data_add_address (self, addr_family, ifindex, NULL, &a.ax);
|
||||
}
|
||||
|
||||
nroutes = nm_setting_ip_config_get_num_routes (s_ip);
|
||||
for (i = 0; i < nroutes; i++) {
|
||||
NMIPRoute *s_route = nm_setting_ip_config_get_route (s_ip, i);
|
||||
NMPlatformIPXRoute r;
|
||||
NMIPAddr network_bin;
|
||||
NMIPAddr next_hop_bin;
|
||||
gint64 metric64;
|
||||
guint32 metric;
|
||||
guint plen;
|
||||
|
||||
nm_assert (nm_ip_route_get_family (s_route) == addr_family);
|
||||
|
||||
nm_ip_route_get_dest_binary (s_route, &network_bin);
|
||||
nm_ip_route_get_next_hop_binary (s_route, &next_hop_bin);
|
||||
|
||||
metric64 = nm_ip_route_get_metric (s_route);
|
||||
if (metric64 < 0)
|
||||
metric = route_metric;
|
||||
else
|
||||
metric = metric64;
|
||||
metric = nm_utils_ip_route_metric_normalize (addr_family, metric);
|
||||
|
||||
plen = nm_ip_route_get_prefix (s_route);
|
||||
|
||||
nm_utils_ipx_address_clear_host_address (addr_family, &network_bin, &network_bin, plen);
|
||||
|
||||
if (IS_IPv4) {
|
||||
r.r4 = (NMPlatformIP4Route) {
|
||||
.network = network_bin.addr4,
|
||||
.plen = nm_ip_route_get_prefix (s_route),
|
||||
.gateway = next_hop_bin.addr4,
|
||||
.metric = metric,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
};
|
||||
nm_assert (r.r4.plen <= 32);
|
||||
} else {
|
||||
r.r6 = (NMPlatformIP6Route) {
|
||||
.network = network_bin.addr6,
|
||||
.plen = nm_ip_route_get_prefix (s_route),
|
||||
.gateway = next_hop_bin.addr6,
|
||||
.metric = metric,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_USER,
|
||||
};
|
||||
nm_assert (r.r6.plen <= 128);
|
||||
}
|
||||
|
||||
nm_utils_ip_route_attribute_to_platform (addr_family,
|
||||
s_route,
|
||||
&r.rx,
|
||||
route_table);
|
||||
|
||||
_nm_l3_config_data_add_route (self, addr_family, ifindex, NULL, &r.rx, NULL, NULL);
|
||||
}
|
||||
|
||||
nnameservers = nm_setting_ip_config_get_num_dns (s_ip);
|
||||
for (i = 0; i < nnameservers; i++) {
|
||||
const char *s;
|
||||
NMIPAddr ip;
|
||||
|
||||
s = nm_setting_ip_config_get_dns (s_ip, i);
|
||||
if (!nm_utils_parse_inaddr_bin (addr_family, s, NULL, &ip))
|
||||
continue;
|
||||
g_array_append_vals (_garray_ensure_for_addrbin (&self->nameservers_x[IS_IPv4], addr_family),
|
||||
&ip,
|
||||
1);
|
||||
}
|
||||
|
||||
nsearches = nm_setting_ip_config_get_num_dns_searches (s_ip);
|
||||
for (i = 0; i < nsearches; i++) {
|
||||
_nm_l3_config_data_add_search (self,
|
||||
addr_family,
|
||||
nm_setting_ip_config_get_dns_search (s_ip, i));
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
while ((idx = nm_setting_ip_config_next_valid_dns_option (s_ip, i)) >= 0) {
|
||||
_nm_l3_config_data_add_dns_option (self,
|
||||
addr_family,
|
||||
nm_setting_ip_config_get_dns_option (s_ip, i));
|
||||
idx++;
|
||||
}
|
||||
|
||||
_nm_l3_config_data_set_dns_priority (self,
|
||||
addr_family,
|
||||
nm_setting_ip_config_get_dns_priority (s_ip));
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index,
|
||||
int ifindex,
|
||||
NMConnection *connection,
|
||||
NMSettingConnectionMdns mdns,
|
||||
NMSettingConnectionLlmnr llmnr,
|
||||
guint32 route_table,
|
||||
guint32 route_metric)
|
||||
{
|
||||
NML3ConfigData *self;
|
||||
|
||||
self = nm_l3_config_data_new (multi_index);
|
||||
|
||||
_init_from_connection_ip (self, AF_INET, ifindex, connection, route_table, route_metric);
|
||||
_init_from_connection_ip (self, AF_INET6, ifindex, connection, route_table, route_metric);
|
||||
|
||||
self->mdns = mdns;
|
||||
self->llmnr = llmnr;
|
||||
|
||||
return self;
|
||||
}
|
||||
63
src/nm-l3-config-data.h
Normal file
63
src/nm-l3-config-data.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
#ifndef __NM_L3_CONFIG_DATA_H__
|
||||
#define __NM_L3_CONFIG_DATA_H__
|
||||
|
||||
#include "nm-glib-aux/nm-dedup-multi.h"
|
||||
#include "nm-setting-connection.h"
|
||||
#include "platform/nm-platform.h"
|
||||
|
||||
typedef struct _NML3ConfigData NML3ConfigData;
|
||||
|
||||
NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx);
|
||||
NML3ConfigData *nm_l3_config_data_ref (NML3ConfigData *self);
|
||||
NML3ConfigData *nm_l3_config_data_ref_and_seal (NML3ConfigData *self);
|
||||
NML3ConfigData *nm_l3_config_data_seal (NML3ConfigData *self);
|
||||
void nm_l3_config_data_unref (NML3ConfigData *self);
|
||||
|
||||
gboolean nm_l3_config_data_is_sealed (NML3ConfigData *self);
|
||||
|
||||
const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_addresses (const NML3ConfigData *self, int addr_family);
|
||||
const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_routes (const NML3ConfigData *self, int addr_family);
|
||||
|
||||
NML3ConfigData *nm_l3_config_data_new_from_connection (NMDedupMultiIndex *multi_index,
|
||||
int ifindex,
|
||||
NMConnection *connection,
|
||||
NMSettingConnectionMdns mdns,
|
||||
NMSettingConnectionLlmnr llmnr,
|
||||
guint32 route_table,
|
||||
guint32 route_metric);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean _nm_l3_config_data_add_address (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformIPAddress *pl_new);
|
||||
|
||||
gboolean _nm_l3_config_data_add_route (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformIPRoute *pl_new,
|
||||
const NMPObject **out_obj_new,
|
||||
gboolean *out_changed_best_default_route);
|
||||
|
||||
gboolean _nm_l3_config_data_add_domain (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *domain);
|
||||
|
||||
gboolean _nm_l3_config_data_add_search (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *search);
|
||||
|
||||
gboolean _nm_l3_config_data_add_dns_option (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
const char *dns_option);
|
||||
|
||||
gboolean _nm_l3_config_data_set_dns_priority (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
int dns_priority);
|
||||
|
||||
#endif /* __NM_L3_CONFIG_DATA_H__ */
|
||||
341
src/nm-l3cfg.c
Normal file
341
src/nm-l3cfg.c
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-l3cfg.h"
|
||||
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
#include "nm-netns.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NML3Cfg,
|
||||
PROP_NETNS,
|
||||
PROP_IFINDEX,
|
||||
);
|
||||
|
||||
typedef struct _NML3CfgPrivate {
|
||||
GArray *property_emit_list;
|
||||
} NML3CfgPrivate;
|
||||
|
||||
struct _NML3CfgClass {
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (NML3Cfg, nm_l3cfg, G_TYPE_OBJECT)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_CORE
|
||||
#define _NMLOG_PREFIX_NAME "l3cfg"
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START { \
|
||||
nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \
|
||||
"l3cfg["NM_HASH_OBFUSCATE_PTR_FMT",ifindex=%d]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
NM_HASH_OBFUSCATE_PTR (self), \
|
||||
nm_l3cfg_get_ifindex (self) \
|
||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void _property_emit_notify (NML3Cfg *self, NML3CfgPropertyEmitType emit_type);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_load_link (NML3Cfg *self, gboolean initial)
|
||||
{
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
const NMPObject *obj;
|
||||
const char *ifname;
|
||||
const char *ifname_old;
|
||||
|
||||
obj = nm_platform_link_get_obj (self->priv.platform, self->priv.ifindex, TRUE);
|
||||
|
||||
if ( initial
|
||||
&& obj == self->priv.pllink)
|
||||
return;
|
||||
|
||||
obj_old = g_steal_pointer (&self->priv.pllink);
|
||||
self->priv.pllink = nmp_object_ref (obj);
|
||||
|
||||
ifname_old = nmp_object_link_get_ifname (obj_old);
|
||||
ifname = nmp_object_link_get_ifname (self->priv.pllink);
|
||||
|
||||
if (initial) {
|
||||
_LOGT ("link ifname changed: %s%s%s (initial)",
|
||||
NM_PRINT_FMT_QUOTE_STRING (ifname));
|
||||
} else if (!nm_streq0 (ifname, ifname_old)) {
|
||||
_LOGT ("link ifname changed: %s%s%s (was %s%s%s)",
|
||||
NM_PRINT_FMT_QUOTE_STRING (ifname),
|
||||
NM_PRINT_FMT_QUOTE_STRING (ifname_old));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
_nm_l3cfg_notify_platform_change_on_idle (NML3Cfg *self, guint32 obj_type_flags)
|
||||
{
|
||||
if (NM_FLAGS_ANY (obj_type_flags, nmp_object_type_to_flags (NMP_OBJECT_TYPE_LINK)))
|
||||
_load_link (self, FALSE);
|
||||
if (NM_FLAGS_ANY (obj_type_flags, nmp_object_type_to_flags (NMP_OBJECT_TYPE_IP4_ROUTE)))
|
||||
_property_emit_notify (self, NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE);
|
||||
if (NM_FLAGS_ANY (obj_type_flags, nmp_object_type_to_flags (NMP_OBJECT_TYPE_IP6_ROUTE)))
|
||||
_property_emit_notify (self, NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GObject *target_obj;
|
||||
const GParamSpec *target_property;
|
||||
NML3CfgPropertyEmitType emit_type;
|
||||
} PropertyEmitData;
|
||||
|
||||
static void
|
||||
_property_emit_notify (NML3Cfg *self, NML3CfgPropertyEmitType emit_type)
|
||||
{
|
||||
gs_free PropertyEmitData *collected_heap = NULL;
|
||||
PropertyEmitData *collected = NULL;
|
||||
PropertyEmitData *emit_data;
|
||||
guint num;
|
||||
guint i;
|
||||
guint j;
|
||||
|
||||
if (!self->priv.p->property_emit_list)
|
||||
return;
|
||||
|
||||
num = 0;
|
||||
emit_data = &g_array_index (self->priv.p->property_emit_list, PropertyEmitData, 0);
|
||||
for (i = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) {
|
||||
if (emit_data->emit_type == emit_type) {
|
||||
collected = emit_data;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num == 0)
|
||||
return;
|
||||
|
||||
if (num == 1) {
|
||||
g_object_notify_by_pspec (collected->target_obj, (GParamSpec *) collected->target_property);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num < 300u / sizeof (*collected))
|
||||
collected = g_alloca (sizeof (PropertyEmitData) * num);
|
||||
else {
|
||||
collected_heap = g_new (PropertyEmitData, num);
|
||||
collected = collected_heap;
|
||||
}
|
||||
|
||||
emit_data = &g_array_index (self->priv.p->property_emit_list, PropertyEmitData, 0);
|
||||
for (i = 0, j = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) {
|
||||
if (emit_data->emit_type == emit_type) {
|
||||
collected[j++] = *emit_data;
|
||||
g_object_ref (collected->target_obj);
|
||||
}
|
||||
}
|
||||
|
||||
nm_assert (j == num);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
g_object_notify_by_pspec (collected[i].target_obj, (GParamSpec *) collected[i].target_property);
|
||||
if (i > 0)
|
||||
g_object_unref (collected[i].target_obj);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nm_l3cfg_property_emit_register (NML3Cfg *self,
|
||||
GObject *target_obj,
|
||||
const GParamSpec *target_property,
|
||||
NML3CfgPropertyEmitType emit_type)
|
||||
{
|
||||
PropertyEmitData *emit_data;
|
||||
guint i;
|
||||
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
nm_assert (G_IS_OBJECT (target_obj));
|
||||
nm_assert (target_property);
|
||||
nm_assert (NM_IN_SET (emit_type, NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE,
|
||||
NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE));
|
||||
nm_assert (target_property == nm_g_object_class_find_property_from_gtype (G_OBJECT_TYPE (target_obj),
|
||||
target_property->name));
|
||||
|
||||
if (!self->priv.p->property_emit_list)
|
||||
self->priv.p->property_emit_list = g_array_new (FALSE, FALSE, sizeof (PropertyEmitData));
|
||||
else {
|
||||
emit_data = &g_array_index (self->priv.p->property_emit_list, PropertyEmitData, 0);
|
||||
for (i = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) {
|
||||
if ( emit_data->target_obj != target_obj
|
||||
|| emit_data->target_property != target_property)
|
||||
continue;
|
||||
nm_assert (emit_data->emit_type == emit_type);
|
||||
emit_data->emit_type = emit_type;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emit_data = nm_g_array_append_new (self->priv.p->property_emit_list, PropertyEmitData);
|
||||
*emit_data = (PropertyEmitData) {
|
||||
.target_obj = target_obj,
|
||||
.target_property = target_property,
|
||||
.emit_type = emit_type,
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
nm_l3cfg_property_emit_unregister (NML3Cfg *self,
|
||||
GObject *target_obj,
|
||||
const GParamSpec *target_property)
|
||||
{
|
||||
PropertyEmitData *emit_data;
|
||||
guint i;
|
||||
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
nm_assert (G_IS_OBJECT (target_obj));
|
||||
nm_assert ( !target_property
|
||||
|| target_property == nm_g_object_class_find_property_from_gtype (G_OBJECT_TYPE (target_obj),
|
||||
target_property->name));
|
||||
|
||||
if (!self->priv.p->property_emit_list)
|
||||
return;
|
||||
|
||||
for (i = self->priv.p->property_emit_list->len; i > 0; i--) {
|
||||
emit_data = &g_array_index (self->priv.p->property_emit_list, PropertyEmitData, i);
|
||||
|
||||
if (emit_data->target_obj != target_obj)
|
||||
continue;
|
||||
if ( target_property
|
||||
&& emit_data->target_property != target_property)
|
||||
continue;
|
||||
|
||||
g_array_remove_index_fast (self->priv.p->property_emit_list, i);
|
||||
|
||||
if (target_property) {
|
||||
/* if a target-property is given, we don't have another entry in
|
||||
* the list. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NML3Cfg *self = NM_L3CFG (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NETNS:
|
||||
/* construct-only */
|
||||
self->priv.netns = g_object_ref (g_value_get_pointer (value));
|
||||
nm_assert (NM_IS_NETNS (self->priv.netns));
|
||||
break;
|
||||
case PROP_IFINDEX:
|
||||
/* construct-only */
|
||||
self->priv.ifindex = g_value_get_int (value);
|
||||
nm_assert (self->priv.ifindex > 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_l3cfg_init (NML3Cfg *self)
|
||||
{
|
||||
NML3CfgPrivate *p;
|
||||
|
||||
p = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_L3CFG, NML3CfgPrivate);
|
||||
|
||||
self->priv.p = p;
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
NML3Cfg *self = NM_L3CFG (object);
|
||||
|
||||
nm_assert (NM_IS_NETNS (self->priv.netns));
|
||||
nm_assert (self->priv.ifindex > 0);
|
||||
|
||||
self->priv.platform = g_object_ref (nm_netns_get_platform (self->priv.netns));
|
||||
nm_assert (NM_IS_PLATFORM (self->priv.platform));
|
||||
|
||||
_LOGT ("created (netns="NM_HASH_OBFUSCATE_PTR_FMT")",
|
||||
NM_HASH_OBFUSCATE_PTR (self->priv.netns));
|
||||
|
||||
G_OBJECT_CLASS (nm_l3cfg_parent_class)->constructed (object);
|
||||
|
||||
_load_link (self, TRUE);
|
||||
}
|
||||
|
||||
NML3Cfg *
|
||||
nm_l3cfg_new (NMNetns *netns, int ifindex)
|
||||
{
|
||||
nm_assert (NM_IS_NETNS (netns));
|
||||
nm_assert (ifindex > 0);
|
||||
|
||||
return g_object_new (NM_TYPE_L3CFG,
|
||||
NM_L3CFG_NETNS, netns,
|
||||
NM_L3CFG_IFINDEX, ifindex,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
NML3Cfg *self = NM_L3CFG (object);
|
||||
|
||||
nm_assert (nm_g_array_len (self->priv.p->property_emit_list) == 0u);
|
||||
|
||||
g_clear_object (&self->priv.netns);
|
||||
g_clear_object (&self->priv.platform);
|
||||
|
||||
nm_clear_pointer (&self->priv.pllink, nmp_object_unref);
|
||||
|
||||
_LOGT ("finalized");
|
||||
|
||||
G_OBJECT_CLASS (nm_l3cfg_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_l3cfg_class_init (NML3CfgClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NML3CfgPrivate));
|
||||
|
||||
object_class->set_property = set_property;
|
||||
object_class->constructed = constructed;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
obj_properties[PROP_NETNS] =
|
||||
g_param_spec_pointer (NM_L3CFG_NETNS, "", "",
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_properties[PROP_IFINDEX] =
|
||||
g_param_spec_int (NM_L3CFG_IFINDEX, "", "",
|
||||
0,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
}
|
||||
92
src/nm-l3cfg.h
Normal file
92
src/nm-l3cfg.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
#ifndef __NM_L3CFG_H__
|
||||
#define __NM_L3CFG_H__
|
||||
|
||||
#include "platform/nmp-object.h"
|
||||
|
||||
#define NM_TYPE_L3CFG (nm_l3cfg_get_type ())
|
||||
#define NM_L3CFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_L3CFG, NML3Cfg))
|
||||
#define NM_L3CFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_L3CFG, NML3CfgClass))
|
||||
#define NM_IS_L3CFG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_L3CFG))
|
||||
#define NM_IS_L3CFG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_L3CFG))
|
||||
#define NM_L3CFG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_L3CFG, NML3CfgClass))
|
||||
|
||||
#define NM_L3CFG_NETNS "netns"
|
||||
#define NM_L3CFG_IFINDEX "ifindex"
|
||||
|
||||
struct _NML3CfgPrivate;
|
||||
|
||||
struct _NML3Cfg {
|
||||
GObject parent;
|
||||
struct {
|
||||
NMNetns *netns;
|
||||
NMPlatform *platform;
|
||||
int ifindex;
|
||||
const NMPObject *pllink;
|
||||
struct _NML3CfgPrivate *p;
|
||||
} priv;
|
||||
};
|
||||
|
||||
typedef struct _NML3CfgClass NML3CfgClass;
|
||||
|
||||
GType nm_l3cfg_get_type (void);
|
||||
|
||||
NML3Cfg *nm_l3cfg_new (NMNetns *netns, int ifindex);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void _nm_l3cfg_notify_platform_change_on_idle (NML3Cfg *self, guint32 obj_type_flags);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
nm_l3cfg_get_ifindex (const NML3Cfg *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return self->priv.ifindex;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nm_l3cfg_get_ifname (const NML3Cfg *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return nmp_object_link_get_ifname (self->priv.pllink);
|
||||
}
|
||||
|
||||
static inline NMNetns *
|
||||
nm_l3cfg_get_netns (const NML3Cfg *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return self->priv.netns;
|
||||
}
|
||||
|
||||
static inline NMPlatform *
|
||||
nm_l3cfg_get_platform (const NML3Cfg *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return self->priv.platform;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
NM_L3CFG_PROPERTY_EMIT_TYPE_ANY,
|
||||
NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE,
|
||||
NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE,
|
||||
} NML3CfgPropertyEmitType;
|
||||
|
||||
void nm_l3cfg_property_emit_register (NML3Cfg *self,
|
||||
GObject *target_obj,
|
||||
const GParamSpec *target_property,
|
||||
NML3CfgPropertyEmitType emit_type);
|
||||
|
||||
void nm_l3cfg_property_emit_unregister (NML3Cfg *self,
|
||||
GObject *target_obj,
|
||||
const GParamSpec *target_property);
|
||||
|
||||
#endif /* __NM_L3CFG_H__ */
|
||||
161
src/nm-netns.c
161
src/nm-netns.c
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-l3cfg.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-netns.h"
|
||||
#include "platform/nmp-rules-manager.h"
|
||||
|
|
@ -22,9 +23,13 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
|||
);
|
||||
|
||||
typedef struct {
|
||||
NMNetns *_self_signal_user_data;
|
||||
NMPlatform *platform;
|
||||
NMPNetns *platform_netns;
|
||||
NMPRulesManager *rules_manager;
|
||||
GHashTable *l3cfgs;
|
||||
CList l3cfg_signal_pending_lst_head;
|
||||
guint signal_pending_idle_id;
|
||||
} NMNetnsPrivate;
|
||||
|
||||
struct _NMNetns {
|
||||
|
|
@ -42,6 +47,18 @@ G_DEFINE_TYPE (NMNetns, nm_netns, G_TYPE_OBJECT);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_CORE
|
||||
#define _NMLOG_PREFIX_NAME "netns"
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START { \
|
||||
nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \
|
||||
"netns["NM_HASH_OBFUSCATE_PTR_FMT"]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
NM_HASH_OBFUSCATE_PTR (self) \
|
||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER (NMNetns, nm_netns_get, NM_TYPE_NETNS);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -72,6 +89,131 @@ nm_netns_get_multi_idx (NMNetns *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int ifindex;
|
||||
guint32 signal_pending_flag;
|
||||
NML3Cfg *l3cfg;
|
||||
CList signal_pending_lst;
|
||||
} L3CfgData;
|
||||
|
||||
static void
|
||||
_l3cfg_data_free (gpointer ptr)
|
||||
{
|
||||
L3CfgData *l3cfg_data = ptr;
|
||||
|
||||
c_list_unlink_stale (&l3cfg_data->signal_pending_lst);
|
||||
|
||||
nm_g_slice_free (l3cfg_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_l3cfg_weak_notify (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
NMNetns *self = NM_NETNS (data);
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(data);
|
||||
NML3Cfg *l3cfg = NM_L3CFG (where_the_object_was);
|
||||
int ifindex = nm_l3cfg_get_ifindex (l3cfg);
|
||||
|
||||
if (!g_hash_table_remove (priv->l3cfgs, &ifindex))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
if (NM_UNLIKELY (g_hash_table_size (priv->l3cfgs) == 0))
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
NML3Cfg *
|
||||
nm_netns_access_l3cfg (NMNetns *self,
|
||||
int ifindex)
|
||||
{
|
||||
NMNetnsPrivate *priv;
|
||||
L3CfgData *l3cfg_data;
|
||||
|
||||
g_return_val_if_fail (NM_IS_NETNS (self), NULL);
|
||||
g_return_val_if_fail (ifindex > 0, NULL);
|
||||
|
||||
priv = NM_NETNS_GET_PRIVATE (self);
|
||||
|
||||
l3cfg_data = g_hash_table_lookup (priv->l3cfgs, &ifindex);
|
||||
|
||||
if (l3cfg_data) {
|
||||
nm_log_trace (LOGD_CORE,
|
||||
"l3cfg["NM_HASH_OBFUSCATE_PTR_FMT",ifindex=%d] %s",
|
||||
NM_HASH_OBFUSCATE_PTR (l3cfg_data->l3cfg),
|
||||
ifindex,
|
||||
"referenced");
|
||||
return g_object_ref (l3cfg_data->l3cfg);
|
||||
}
|
||||
|
||||
l3cfg_data = g_slice_new (L3CfgData);
|
||||
*l3cfg_data = (L3CfgData) {
|
||||
.ifindex = ifindex,
|
||||
.l3cfg = nm_l3cfg_new (self, ifindex),
|
||||
.signal_pending_lst = C_LIST_INIT (l3cfg_data->signal_pending_lst),
|
||||
};
|
||||
|
||||
if (!g_hash_table_add (priv->l3cfgs, l3cfg_data))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
if (NM_UNLIKELY (g_hash_table_size (priv->l3cfgs) == 1))
|
||||
g_object_ref (self);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (l3cfg_data->l3cfg),
|
||||
_l3cfg_weak_notify,
|
||||
self);
|
||||
|
||||
/* Transfer ownership! We keep only a weak ref. */
|
||||
return l3cfg_data->l3cfg;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_platform_signal_on_idle_cb (gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMNetns *self = g_object_ref (NM_NETNS (user_data));
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||
L3CfgData *l3cfg_data;
|
||||
|
||||
while ((l3cfg_data = c_list_first_entry (&priv->l3cfg_signal_pending_lst_head, L3CfgData, signal_pending_lst))) {
|
||||
c_list_unlink (&l3cfg_data->signal_pending_lst);
|
||||
_nm_l3cfg_notify_platform_change_on_idle (l3cfg_data->l3cfg,
|
||||
nm_steal_int (&l3cfg_data->signal_pending_flag));
|
||||
}
|
||||
|
||||
priv->signal_pending_idle_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
_platform_signal_cb (NMPlatform *platform,
|
||||
int obj_type_i,
|
||||
int ifindex,
|
||||
gconstpointer platform_object,
|
||||
int change_type_i,
|
||||
NMNetns **p_self)
|
||||
{
|
||||
NMNetns *self = NM_NETNS (*p_self);
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||
const NMPObjectType obj_type = obj_type_i;
|
||||
L3CfgData *l3cfg_data;
|
||||
|
||||
l3cfg_data = g_hash_table_lookup (priv->l3cfgs, &ifindex);
|
||||
if (!l3cfg_data)
|
||||
return;
|
||||
|
||||
l3cfg_data->signal_pending_flag |= nmp_object_type_to_flags (obj_type);
|
||||
|
||||
if (!c_list_is_empty (&l3cfg_data->signal_pending_lst))
|
||||
return;
|
||||
|
||||
c_list_link_tail (&priv->l3cfg_signal_pending_lst_head, &l3cfg_data->signal_pending_lst);
|
||||
if (priv->signal_pending_idle_id == 0)
|
||||
priv->signal_pending_idle_id = g_idle_add (_platform_signal_on_idle_cb, self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
|
|
@ -98,6 +240,10 @@ set_property (GObject *object, guint prop_id,
|
|||
static void
|
||||
nm_netns_init (NMNetns *self)
|
||||
{
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||
|
||||
priv->_self_signal_user_data = self;
|
||||
c_list_init (&priv->l3cfg_signal_pending_lst_head);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -109,6 +255,8 @@ constructed (GObject *object)
|
|||
if (!priv->platform)
|
||||
g_return_if_reached ();
|
||||
|
||||
priv->l3cfgs = g_hash_table_new_full (nm_pint_hash, nm_pint_equals, _l3cfg_data_free, NULL);
|
||||
|
||||
priv->platform_netns = nm_platform_netns_get (priv->platform);
|
||||
|
||||
priv->rules_manager = nmp_rules_manager_new (priv->platform);
|
||||
|
|
@ -136,6 +284,10 @@ constructed (GObject *object)
|
|||
NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG);
|
||||
|
||||
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
|
||||
|
||||
g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_platform_signal_cb), &priv->_self_signal_user_data);
|
||||
g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_platform_signal_cb), &priv->_self_signal_user_data);
|
||||
g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_platform_signal_cb), &priv->_self_signal_user_data);
|
||||
}
|
||||
|
||||
NMNetns *
|
||||
|
|
@ -152,7 +304,16 @@ dispose (GObject *object)
|
|||
NMNetns *self = NM_NETNS (object);
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||
|
||||
nm_assert (nm_g_hash_table_size (priv->l3cfgs) == 0);
|
||||
nm_assert (c_list_is_empty (&priv->l3cfg_signal_pending_lst_head));
|
||||
|
||||
nm_clear_g_source (&priv->signal_pending_idle_id);
|
||||
|
||||
if (priv->platform)
|
||||
g_signal_handlers_disconnect_by_data (priv->platform, &priv->_self_signal_user_data);
|
||||
|
||||
g_clear_object (&priv->platform);
|
||||
g_clear_pointer (&priv->l3cfgs, g_hash_table_unref);
|
||||
|
||||
nm_clear_pointer (&priv->rules_manager, nmp_rules_manager_unref);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,4 +31,7 @@ struct _NMDedupMultiIndex *nm_netns_get_multi_idx (NMNetns *self);
|
|||
|
||||
#define NM_NETNS_GET (nm_netns_get ())
|
||||
|
||||
NML3Cfg *nm_netns_access_l3cfg (NMNetns *netns,
|
||||
int ifindex);
|
||||
|
||||
#endif /* __NM_NETNS_H__ */
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ typedef struct _NMDBusManager NMDBusManager;
|
|||
typedef struct _NMConfig NMConfig;
|
||||
typedef struct _NMConfigData NMConfigData;
|
||||
typedef struct _NMConnectivity NMConnectivity;
|
||||
typedef struct _NML3Cfg NML3Cfg;
|
||||
typedef struct _NMDevice NMDevice;
|
||||
typedef struct _NMDhcpConfig NMDhcpConfig;
|
||||
typedef struct _NMProxyConfig NMProxyConfig;
|
||||
|
|
@ -235,6 +236,17 @@ typedef enum {
|
|||
NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1,
|
||||
} NMPObjectType;
|
||||
|
||||
static inline guint32
|
||||
nmp_object_type_to_flags (NMPObjectType obj_type)
|
||||
{
|
||||
G_STATIC_ASSERT_EXPR (NMP_OBJECT_TYPE_MAX < 32);
|
||||
|
||||
nm_assert (_NM_INT_NOT_NEGATIVE (obj_type));
|
||||
nm_assert (obj_type < NMP_OBJECT_TYPE_MAX);
|
||||
|
||||
return ((guint32) 1u) << obj_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* NMIPConfigMergeFlags:
|
||||
* @NM_IP_CONFIG_MERGE_DEFAULT: no flags set
|
||||
|
|
|
|||
|
|
@ -556,6 +556,21 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type)
|
|||
#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 int
|
||||
NMP_OBJECT_GET_ADDR_FAMILY (const NMPObject *obj)
|
||||
{
|
||||
switch (NMP_OBJECT_GET_TYPE (obj)) {
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
return AF_INET;
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
return AF_INET6;
|
||||
default:
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const NMPObject *
|
||||
nmp_object_ref (const NMPObject *obj)
|
||||
{
|
||||
|
|
@ -599,6 +614,25 @@ nmp_object_unref (const NMPObject *obj)
|
|||
_changed; \
|
||||
})
|
||||
|
||||
static inline gboolean
|
||||
nmp_object_ref_set (const NMPObject **pp, const NMPObject *obj)
|
||||
{
|
||||
gboolean _changed = FALSE;
|
||||
const NMPObject *p;
|
||||
|
||||
nm_assert (!pp || !*pp || NMP_OBJECT_IS_VALID (*pp));
|
||||
nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
if ( pp
|
||||
&& ((p = *pp) != obj)) {
|
||||
nmp_object_ref (obj);
|
||||
*pp = obj;
|
||||
nmp_object_unref (p);
|
||||
_changed = TRUE;
|
||||
}
|
||||
return _changed;
|
||||
}
|
||||
|
||||
NMPObject *nmp_object_new (NMPObjectType obj_type, gconstpointer plobj);
|
||||
NMPObject *nmp_object_new_link (int ifindex);
|
||||
|
||||
|
|
@ -995,4 +1029,32 @@ nm_platform_lookup_object_by_addr_family (NMPlatform *platform,
|
|||
return nm_platform_lookup (platform, &lookup);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline const char *
|
||||
nmp_object_link_get_ifname (const NMPObject *obj)
|
||||
{
|
||||
if (!obj)
|
||||
return NULL;
|
||||
return NMP_OBJECT_CAST_LINK (obj)->name;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nmp_object_ip_route_is_best_defaut_route (const NMPObject *obj)
|
||||
{
|
||||
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (obj);
|
||||
|
||||
/* return whether @obj is considered a default-route.
|
||||
*
|
||||
* NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because
|
||||
* at various places we act differently depending on whether there is a default-route
|
||||
* configured.
|
||||
*
|
||||
* Note that this only considers the main routing table. */
|
||||
return r
|
||||
&& NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
|
||||
&& nm_platform_route_table_is_main (r->table_coerced)
|
||||
&& r->type_coerced == nm_platform_route_type_coerce (1 /* RTN_UNICAST */);
|
||||
}
|
||||
|
||||
#endif /* __NMP_OBJECT_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue