l3cfg: support tracking NML3ConfigData in NML3Cfg

NML3Cfg is supposed to manage an interface (by ifindex).

As such, it later will itself implement DHCP and similar addressing
methods.

However, in various cases we get additional IP configuration from
external (e.g. from a VPN connection). To support that, let NML3Cfg
track any number of NML3ConfigData instances.
This commit is contained in:
Thomas Haller 2020-07-23 16:15:26 +02:00
parent 297eb4d169
commit 81cf493b96
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 622 additions and 28 deletions

View file

@ -143,6 +143,44 @@ _garray_inaddr_clone (const GArray *src,
return dst;
}
static void
_garray_inaddr_merge (GArray **p_dst,
const GArray *src,
int addr_family)
{
guint dst_initial_len;
const char *p_dst_arr;
const char *p_src;
gsize elt_size;
guint i;
guint j;
if (nm_g_array_len (src) == 0)
return;
if (!*p_dst) {
*p_dst = _garray_inaddr_clone (src, addr_family);
return;
}
elt_size = nm_utils_addr_family_to_size (addr_family);
dst_initial_len = (*p_dst)->len;
p_dst_arr = (*p_dst)->data;
p_src = src->data;
for (i = 0; i < src->len; i++, p_src += elt_size) {
for (j = 0; j < dst_initial_len; j++) {
if (memcmp (&p_dst_arr[j * elt_size], p_src, elt_size) == 0)
goto next;
}
g_array_append_vals (*p_dst, p_src, 1);
p_dst_arr = (*p_dst)->data;
next:
;
}
}
static gssize
_garray_inaddr_find (GArray *arr,
int addr_family,
@ -204,6 +242,36 @@ _garray_inaddr_cmp (const GArray *a, const GArray *b, int addr_family)
return 0;
}
static void
_strv_ptrarray_merge (GPtrArray **p_dst, const GPtrArray *src)
{
guint dst_initial_len;
guint i;
if (nm_g_ptr_array_len (src) == 0)
return;
if (!*p_dst) {
/* we trust src to contain unique strings. Just clone it. */
*p_dst = nm_strv_ptrarray_clone (src, TRUE);
return;
}
nm_strv_ptrarray_ensure (p_dst);
dst_initial_len = (*p_dst)->len;
for (i = 0; i < src->len; i++) {
const char *s = src->pdata[i];
if ( dst_initial_len > 0
&& nm_utils_strv_find_first ((char **) ((*p_dst)->pdata), dst_initial_len, s) >= 0)
continue;
g_ptr_array_add (*p_dst, g_strdup (s));
}
}
/*****************************************************************************/
static gboolean
@ -1316,13 +1384,143 @@ nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_idx,
/*****************************************************************************/
static void
_init_merge (NML3ConfigData *self,
const NML3ConfigData *src,
NML3ConfigMergeFlags merge_flags,
const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */)
{
NMDedupMultiIter iter;
const NMPObject *obj;
int IS_IPv4;
nm_assert (_NM_IS_L3_CONFIG_DATA (self, FALSE));
nm_assert (_NM_IS_L3_CONFIG_DATA (src, TRUE));
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
const NML3ConfigDatFlags has_dns_priority_flag = NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY (IS_IPv4);
nm_l3_config_data_iter_obj_for_each (iter,
src,
obj,
NMP_OBJECT_TYPE_IP_ADDRESS (IS_IPv4)) {
if ( NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_EXTERNAL)
&& !NMP_OBJECT_CAST_IP_ADDRESS (obj)->external) {
NMPlatformIPXAddress a;
if (IS_IPv4)
a.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS (obj);
else
a.a6 = *NMP_OBJECT_CAST_IP6_ADDRESS (obj);
a.ax.ifindex = self->ifindex;
a.ax.external = TRUE;
nm_l3_config_data_add_address_full (self,
addr_family,
NULL,
&a.ax,
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL);
continue;
}
nm_l3_config_data_add_address_full (self,
addr_family,
obj,
NULL,
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL);
}
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES)) {
nm_l3_config_data_iter_obj_for_each (iter,
src,
obj,
NMP_OBJECT_TYPE_IP_ROUTE (IS_IPv4)) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (NMP_OBJECT_CAST_IP_ROUTE (obj))) {
if ( NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES)
&& !NM_FLAGS_HAS (src->flags, NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
continue;
if ( default_route_penalty_x
&& default_route_penalty_x[IS_IPv4] > 0) {
NMPlatformIPXRoute r;
if (IS_IPv4)
r.r4 = *NMP_OBJECT_CAST_IP4_ROUTE (obj);
else
r.r6 = *NMP_OBJECT_CAST_IP6_ROUTE (obj);
r.rx.ifindex = self->ifindex;
r.rx.metric = nm_utils_ip_route_metric_penalize (r.rx.metric, default_route_penalty_x[IS_IPv4]);
nm_l3_config_data_add_route_full (self,
addr_family,
NULL,
&r.rx,
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL,
NULL);
continue;
}
}
nm_l3_config_data_add_route_full (self,
addr_family,
obj,
NULL,
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL,
NULL);
}
}
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
_garray_inaddr_merge (&self->nameservers_x[IS_IPv4], src->nameservers_x[IS_IPv4], addr_family);
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
_strv_ptrarray_merge (&self->domains_x[IS_IPv4], src->domains_x[IS_IPv4]);
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
_strv_ptrarray_merge (&self->searches_x[IS_IPv4], src->searches_x[IS_IPv4]);
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
_strv_ptrarray_merge (&self->dns_options_x[IS_IPv4], src->dns_options_x[IS_IPv4]);
if ( !NM_FLAGS_ANY (self->flags, has_dns_priority_flag)
&& NM_FLAGS_ANY (src->flags, has_dns_priority_flag)) {
self->dns_priority_x[IS_IPv4] = src->dns_priority_x[IS_IPv4];
self->flags |= has_dns_priority_flag;
}
}
if (!NM_FLAGS_HAS (merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS)) {
_garray_inaddr_merge (&self->wins, src->wins, AF_INET);
_garray_inaddr_merge (&self->nis_servers, src->nis_servers, AF_INET);
if ( !self->nis_domain
&& src->nis_domain)
self->nis_domain = g_strdup (src->nis_domain);
}
if (self->mdns == NM_SETTING_CONNECTION_MDNS_DEFAULT)
self->mdns = src->mdns;
if (self->llmnr == NM_SETTING_CONNECTION_LLMNR_DEFAULT)
self->llmnr = src->llmnr;
if (self->metered == NM_TERNARY_DEFAULT)
self->metered = src->metered;
if ( !NM_FLAGS_HAS (self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU)
&& NM_FLAGS_HAS (src->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_MTU)) {
self->mtu = src->mtu;
self->flags |= NM_L3_CONFIG_DAT_FLAGS_HAS_MTU;
}
}
NML3ConfigData *
nm_l3_config_data_new_clone (const NML3ConfigData *src,
int ifindex)
{
NML3ConfigData *self;
NMDedupMultiIter iter;
const NMPObject *obj;
nm_assert (_NM_IS_L3_CONFIG_DATA (src, TRUE));
@ -1333,34 +1531,30 @@ nm_l3_config_data_new_clone (const NML3ConfigData *src,
ifindex = src->ifindex;
self = nm_l3_config_data_new (src->multi_idx, ifindex);
_init_merge (self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL);
return self;
}
nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP4_ADDRESS)
nm_l3_config_data_add_address (self, AF_INET, obj, NULL);
nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP6_ADDRESS)
nm_l3_config_data_add_address (self, AF_INET6, obj, NULL);
nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP4_ROUTE)
nm_l3_config_data_add_route (self, AF_INET, obj, NULL);
nm_l3_config_data_iter_obj_for_each (iter, src, obj, NMP_OBJECT_TYPE_IP6_ROUTE)
nm_l3_config_data_add_route (self, AF_INET6, obj, NULL);
NML3ConfigData *
nm_l3_config_data_new_combined (NMDedupMultiIndex *multi_idx,
int ifindex,
const NML3ConfigDatMergeInfo *const*merge_infos,
guint merge_infos_len)
{
NML3ConfigData *self;
guint i;
nm_assert (self->best_default_route_4 == src->best_default_route_4);
nm_assert (self->best_default_route_6 == src->best_default_route_6);
nm_assert (multi_idx);
nm_assert (ifindex > 0);
self->wins = _garray_inaddr_clone (src->wins, AF_INET);
self->nameservers_4 = _garray_inaddr_clone (src->nameservers_4, AF_INET);
self->nameservers_6 = _garray_inaddr_clone (src->nameservers_6, AF_INET6);
self->domains_4 = nm_strv_ptrarray_clone (src->domains_4, TRUE);
self->domains_6 = nm_strv_ptrarray_clone (src->domains_6, TRUE);
self->searches_4 = nm_strv_ptrarray_clone (src->searches_4, TRUE);
self->searches_6 = nm_strv_ptrarray_clone (src->searches_6, TRUE);
self->dns_options_4 = nm_strv_ptrarray_clone (src->dns_options_4, TRUE);
self->dns_options_6 = nm_strv_ptrarray_clone (src->dns_options_6, TRUE);
self->dns_priority_4 = src->dns_priority_4;
self->dns_priority_6 = src->dns_priority_6;
self->mdns = src->mdns;
self->llmnr = src->llmnr;
self = nm_l3_config_data_new (multi_idx, ifindex);
/* TODO: some fields are not cloned. Will be done next. */
for (i = 0; i < merge_infos_len; i++) {
_init_merge (self,
merge_infos[i]->l3cfg,
merge_infos[i]->merge_flags,
merge_infos[i]->default_route_penalty_x);
}
return self;
}

View file

@ -43,10 +43,40 @@ typedef enum {
NM_L3_CONFIG_ADD_FLAGS_APPEND_FORCE = (1ull << 2),
} NML3ConfigAddFlags;
/**
* NML3ConfigMergeFlags:
* @NM_L3_CONFIG_MERGE_FLAGS_NONE: no flags set
* @NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES: don't merge routes
* @NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES: don't merge default routes.
* Note that if the respective NML3ConfigData has NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES
* set, this flag gets ignored during merge.
* @NM_L3_CONFIG_MERGE_FLAGS_NO_DNS: don't merge DNS information
* @NM_L3_CONFIG_MERGE_FLAGS_EXTERNAL: mark new addresses as external
*/
typedef enum {
NM_L3_CONFIG_MERGE_FLAGS_NONE = 0,
NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 0),
NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 1),
NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 2),
NM_L3_CONFIG_MERGE_FLAGS_EXTERNAL = (1LL << 3),
} NML3ConfigMergeFlags;
/*****************************************************************************/
typedef struct _NML3ConfigData NML3ConfigData;
typedef struct {
const NML3ConfigData *l3cfg;
NML3ConfigMergeFlags merge_flags;
union {
struct {
guint32 default_route_penalty_6;
guint32 default_route_penalty_4;
};
guint32 default_route_penalty_x[2];
};
} NML3ConfigDatMergeInfo;
NML3ConfigData *nm_l3_config_data_new (NMDedupMultiIndex *multi_idx,
int ifindex);
const NML3ConfigData *nm_l3_config_data_ref (const NML3ConfigData *self);
@ -76,6 +106,11 @@ NML3ConfigData *nm_l3_config_data_new_from_platform (NMDedupMultiIndex *multi_id
NMPlatform *platform,
NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941);
NML3ConfigData *nm_l3_config_data_new_combined (NMDedupMultiIndex *multi_idx,
int ifindex,
const NML3ConfigDatMergeInfo *const*merge_infos,
guint merge_infos_len);
/*****************************************************************************/
int nm_l3_config_data_get_ifindex (const NML3ConfigData *self);

View file

@ -10,6 +10,16 @@
/*****************************************************************************/
typedef struct {
NML3ConfigDatMergeInfo merge_info;
gconstpointer tag;
guint64 pseudo_timestamp;
int priority;
bool dirty:1;
} L3ConfigData;
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE (NML3Cfg,
PROP_NETNS,
PROP_IFINDEX,
@ -17,6 +27,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NML3Cfg,
typedef struct _NML3CfgPrivate {
GArray *property_emit_list;
GArray *l3_config_datas;
const NML3ConfigData *combined_l3cfg;
guint64 pseudo_timestamp_counter;
} NML3CfgPrivate;
struct _NML3CfgClass {
@ -226,6 +239,331 @@ nm_l3cfg_property_emit_unregister (NML3Cfg *self,
/*****************************************************************************/
static GArray *
_l3_config_datas_ensure (GArray **p_arr)
{
if (!*p_arr)
*p_arr = g_array_new (FALSE, FALSE, sizeof (L3ConfigData));
return *p_arr;
}
#define _l3_config_datas_at(l3_config_datas, idx) \
(&g_array_index ((l3_config_datas), L3ConfigData, (idx)))
static gssize
_l3_config_datas_find_next (GArray *l3_config_datas,
guint start_idx,
gconstpointer needle_tag,
const NML3ConfigData *needle_l3cfg)
{
guint i;
nm_assert (l3_config_datas);
nm_assert (start_idx <= l3_config_datas->len);
for (i = start_idx; i < l3_config_datas->len; i++) {
const L3ConfigData *l3_config_data = _l3_config_datas_at (l3_config_datas, i);
if ( NM_IN_SET (needle_tag, NULL, l3_config_data->tag)
&& NM_IN_SET (needle_l3cfg, NULL, l3_config_data->merge_info.l3cfg))
return i;
}
return -1;
}
static void
_l3_config_datas_remove_index_fast (GArray *arr,
guint idx)
{
L3ConfigData *l3_config_data;
nm_assert (arr);
nm_assert (idx < arr->len);
l3_config_data = _l3_config_datas_at (arr, idx);
nm_l3_config_data_unref (l3_config_data->merge_info.l3cfg);
g_array_remove_index_fast (arr, idx);
}
void
nm_l3cfg_mark_config_dirty (NML3Cfg *self,
gconstpointer tag,
gboolean dirty)
{
GArray *l3_config_datas;
gssize idx;
nm_assert (NM_IS_L3CFG (self));
nm_assert (tag);
l3_config_datas = self->priv.p->l3_config_datas;
if (!l3_config_datas)
return;
idx = 0;
while (TRUE) {
idx = _l3_config_datas_find_next (l3_config_datas,
idx,
tag,
NULL);
if (idx < 0)
return;
_l3_config_datas_at (l3_config_datas, idx)->dirty = dirty;
idx++;
}
}
void
nm_l3cfg_add_config (NML3Cfg *self,
gconstpointer tag,
gboolean replace_same_tag,
const NML3ConfigData *l3cfg,
int priority,
guint32 default_route_penalty_4,
guint32 default_route_penalty_6,
NML3ConfigMergeFlags merge_flags)
{
GArray *l3_config_datas;
L3ConfigData *l3_config_data;
gssize idx;
gboolean changed = FALSE;
nm_assert (NM_IS_L3CFG (self));
nm_assert (tag);
nm_assert (l3cfg);
nm_assert (nm_l3_config_data_get_ifindex (l3cfg) == self->priv.ifindex);
l3_config_datas = _l3_config_datas_ensure (&self->priv.p->l3_config_datas);
idx = _l3_config_datas_find_next (l3_config_datas,
0,
tag,
replace_same_tag ? NULL : l3cfg);
if (replace_same_tag) {
gssize idx2;
idx2 = idx;
idx = -1;
while (TRUE) {
l3_config_data = _l3_config_datas_at (l3_config_datas, idx2);
if (l3_config_data->merge_info.l3cfg == l3cfg) {
nm_assert (idx == -1);
idx = idx2;
continue;
}
changed = TRUE;
_l3_config_datas_remove_index_fast (l3_config_datas, idx2);
idx2 = _l3_config_datas_find_next (l3_config_datas, idx2, tag, NULL);
if (idx2 < 0)
break;
}
}
if (idx < 0) {
l3_config_data = nm_g_array_append_new (l3_config_datas, L3ConfigData);
*l3_config_data = (L3ConfigData) {
.tag = tag,
.merge_info.l3cfg = nm_l3_config_data_ref_and_seal (l3cfg),
.merge_info.merge_flags = merge_flags,
.merge_info.default_route_penalty_4 = default_route_penalty_4,
.merge_info.default_route_penalty_6 = default_route_penalty_6,
.priority = priority,
.pseudo_timestamp = ++self->priv.p->pseudo_timestamp_counter,
.dirty = FALSE,
};
changed = TRUE;
} else {
l3_config_data = _l3_config_datas_at (l3_config_datas, idx);
l3_config_data->dirty = FALSE;
nm_assert (l3_config_data->tag == tag);
nm_assert (l3_config_data->merge_info.l3cfg == l3cfg);
if (l3_config_data->priority != priority) {
l3_config_data->priority = priority;
changed = TRUE;
}
if (l3_config_data->merge_info.merge_flags != merge_flags) {
l3_config_data->merge_info.merge_flags = merge_flags;
changed = TRUE;
}
if (l3_config_data->merge_info.default_route_penalty_4 != default_route_penalty_4) {
l3_config_data->merge_info.default_route_penalty_4 = default_route_penalty_4;
changed = TRUE;
}
if (l3_config_data->merge_info.default_route_penalty_6 != default_route_penalty_6) {
l3_config_data->merge_info.default_route_penalty_6 = default_route_penalty_6;
changed = TRUE;
}
}
if (changed)
self->priv.changed_configs = TRUE;
}
static void
_l3cfg_remove_config (NML3Cfg *self,
gconstpointer tag,
gboolean only_dirty,
const NML3ConfigData *l3cfg)
{
GArray *l3_config_datas;
gssize idx;
nm_assert (NM_IS_L3CFG (self));
nm_assert (tag);
l3_config_datas = self->priv.p->l3_config_datas;
if (!l3_config_datas)
return;
idx = 0;
while (TRUE) {
idx = _l3_config_datas_find_next (l3_config_datas,
idx,
tag,
l3cfg);
if (idx < 0)
return;
if ( only_dirty
&& !_l3_config_datas_at (l3_config_datas, idx)->dirty) {
idx++;
continue;
}
self->priv.changed_configs = TRUE;
_l3_config_datas_remove_index_fast (l3_config_datas, idx);
if (!l3cfg)
return;
}
}
void
nm_l3cfg_remove_config (NML3Cfg *self,
gconstpointer tag,
const NML3ConfigData *ifcfg)
{
nm_assert (ifcfg);
_l3cfg_remove_config (self, tag, FALSE, ifcfg);
}
void
nm_l3cfg_remove_config_all (NML3Cfg *self,
gconstpointer tag,
gboolean only_dirty)
{
_l3cfg_remove_config (self, tag, only_dirty, NULL);
}
/*****************************************************************************/
static int
_l3_config_combine_sort_fcn (gconstpointer p_a,
gconstpointer p_b,
gpointer user_data)
{
const L3ConfigData *a = *((L3ConfigData **) p_a);
const L3ConfigData *b = *((L3ConfigData **) p_b);
nm_assert (a);
nm_assert (b);
nm_assert (nm_l3_config_data_get_ifindex (a->merge_info.l3cfg) == nm_l3_config_data_get_ifindex (b->merge_info.l3cfg));
/* we sort the entries with higher priority (more important, lower numerical value)
* first. */
NM_CMP_FIELD (a, b, priority);
/* if the priority is not unique, we sort them in the order they were added,
* with the oldest first (lower numerical value). */
NM_CMP_FIELD (a, b, pseudo_timestamp);
return nm_assert_unreachable_val (0);
}
static const NML3ConfigData *
_l3cfg_combine_config (GArray *l3_config_datas,
NMDedupMultiIndex *multi_idx,
int ifindex)
{
gs_free L3ConfigData **infos_heap = NULL;
NML3ConfigData *l3cfg;
L3ConfigData **infos;
guint i;
if ( !l3_config_datas
|| l3_config_datas->len == 0)
return NULL;
if (l3_config_datas->len == 1)
return nm_l3_config_data_ref (_l3_config_datas_at (l3_config_datas, 0)->merge_info.l3cfg);
if (l3_config_datas->len < 300 / sizeof (infos[0]))
infos = g_alloca (l3_config_datas->len * sizeof (infos[0]));
else {
infos_heap = g_new (L3ConfigData *, l3_config_datas->len);
infos = infos_heap;
}
for (i = 0; i < l3_config_datas->len; i++)
infos[i] = _l3_config_datas_at (l3_config_datas, i);
g_qsort_with_data (infos,
l3_config_datas->len,
sizeof (infos[0]),
_l3_config_combine_sort_fcn,
NULL);
nm_assert (&infos[0]->merge_info == (NML3ConfigDatMergeInfo *) infos[0]);
l3cfg = nm_l3_config_data_new_combined (multi_idx,
ifindex,
(const NML3ConfigDatMergeInfo *const*) infos,
l3_config_datas->len);
nm_assert (l3cfg);
nm_assert (nm_l3_config_data_get_ifindex (l3cfg) == ifindex);
return nm_l3_config_data_seal (l3cfg);
}
_nm_unused
static gboolean
_l3cfg_update_combined_config (NML3Cfg *self,
const NML3ConfigData **out_old /* transfer reference */)
{
nm_auto_unref_l3cfg const NML3ConfigData *l3cfg_old = NULL;
nm_auto_unref_l3cfg const NML3ConfigData *l3cfg = NULL;
nm_assert (NM_IS_L3CFG (self));
nm_assert (!out_old || !*out_old);
if (!self->priv.changed_configs)
return FALSE;
self->priv.changed_configs = FALSE;
l3cfg = _l3cfg_combine_config (self->priv.p->l3_config_datas,
nm_platform_get_multi_idx (self->priv.platform),
self->priv.ifindex);
if (nm_l3_config_data_equal (l3cfg, self->priv.p->combined_l3cfg))
return FALSE;
l3cfg_old = g_steal_pointer (&self->priv.p->combined_l3cfg);
self->priv.p->combined_l3cfg = nm_l3_config_data_seal (g_steal_pointer (&l3cfg));
NM_SET_OUT (out_old, nm_l3_config_data_ref (self->priv.p->combined_l3cfg));
return TRUE;
}
/*****************************************************************************/
static void
set_property (GObject *object,
guint prop_id,
@ -304,6 +642,8 @@ finalize (GObject *object)
g_clear_object (&self->priv.netns);
g_clear_object (&self->priv.platform);
nm_clear_pointer (&self->priv.p->combined_l3cfg, nm_l3_config_data_unref);
nm_clear_pointer (&self->priv.pllink, nmp_object_unref);
_LOGT ("finalized");

View file

@ -4,6 +4,7 @@
#define __NM_L3CFG_H__
#include "platform/nmp-object.h"
#include "nm-l3-config-data.h"
#define NM_TYPE_L3CFG (nm_l3cfg_get_type ())
#define NM_L3CFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_L3CFG, NML3Cfg))
@ -20,11 +21,12 @@ struct _NML3CfgPrivate;
struct _NML3Cfg {
GObject parent;
struct {
struct _NML3CfgPrivate *p;
NMNetns *netns;
NMPlatform *platform;
int ifindex;
const NMPObject *pllink;
struct _NML3CfgPrivate *p;
int ifindex;
bool changed_configs:1;
} priv;
};
@ -89,4 +91,27 @@ void nm_l3cfg_property_emit_unregister (NML3Cfg *self,
GObject *target_obj,
const GParamSpec *target_property);
/*****************************************************************************/
void nm_l3cfg_mark_config_dirty (NML3Cfg *self,
gconstpointer tag,
gboolean dirty);
void nm_l3cfg_add_config (NML3Cfg *self,
gconstpointer tag,
gboolean replace_same_tag,
const NML3ConfigData *l3cfg,
int priority,
guint32 default_route_penalty_4,
guint32 default_route_penalty_6,
NML3ConfigMergeFlags merge_flags);
void nm_l3cfg_remove_config (NML3Cfg *self,
gconstpointer tag,
const NML3ConfigData *ifcfg);
void nm_l3cfg_remove_config_all (NML3Cfg *self,
gconstpointer tag,
gboolean only_dirty);
#endif /* __NM_L3CFG_H__ */