diff options
Diffstat (limited to 'src/core/ndisc')
| -rw-r--r-- | src/core/ndisc/nm-fake-ndisc.c | 90 | ||||
| -rw-r--r-- | src/core/ndisc/nm-fake-ndisc.h | 18 | ||||
| -rw-r--r-- | src/core/ndisc/nm-lndp-ndisc.c | 112 | ||||
| -rw-r--r-- | src/core/ndisc/nm-lndp-ndisc.h | 13 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc-private.h | 2 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc.c | 587 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc.h | 66 | ||||
| -rw-r--r-- | src/core/ndisc/tests/test-ndisc-fake.c | 138 | ||||
| -rw-r--r-- | src/core/ndisc/tests/test-ndisc-linux.c | 55 |
9 files changed, 516 insertions, 565 deletions
diff --git a/src/core/ndisc/nm-fake-ndisc.c b/src/core/ndisc/nm-fake-ndisc.c index ffe07ab6..5aea273e 100644 --- a/src/core/ndisc/nm-fake-ndisc.c +++ b/src/core/ndisc/nm-fake-ndisc.c @@ -10,6 +10,7 @@ #include <arpa/inet.h> #include "nm-ndisc-private.h" +#include "nm-l3cfg.h" #define _NMLOG_PREFIX_NAME "ndisc-fake" @@ -20,10 +21,10 @@ typedef struct { guint when; NMNDiscDHCPLevel dhcp_level; - GArray * gateways; - GArray * prefixes; - GArray * dns_servers; - GArray * dns_domains; + GArray *gateways; + GArray *prefixes; + GArray *dns_servers; + GArray *dns_domains; int hop_limit; guint32 mtu; } FakeRa; @@ -97,7 +98,7 @@ find_ra(GSList *ras, guint id) } guint -nm_fake_ndisc_add_ra(NMFakeNDisc * self, +nm_fake_ndisc_add_ra(NMFakeNDisc *self, guint seconds_after_previous, NMNDiscDHCPLevel dhcp_level, int hop_limit, @@ -105,7 +106,7 @@ nm_fake_ndisc_add_ra(NMFakeNDisc * self, { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); static guint counter = 1; - FakeRa * ra; + FakeRa *ra; ra = g_malloc0(sizeof(*ra)); ra->id = counter++; @@ -124,15 +125,15 @@ nm_fake_ndisc_add_ra(NMFakeNDisc * self, } void -nm_fake_ndisc_add_gateway(NMFakeNDisc * self, +nm_fake_ndisc_add_gateway(NMFakeNDisc *self, guint ra_id, - const char * addr, + const char *addr, gint64 expiry_msec, NMIcmpv6RouterPref preference) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); - FakeRa * ra = find_ra(priv->ras, ra_id); - NMNDiscGateway * gw; + FakeRa *ra = find_ra(priv->ras, ra_id); + NMNDiscGateway *gw; g_assert(ra); @@ -144,18 +145,18 @@ nm_fake_ndisc_add_gateway(NMFakeNDisc * self, } void -nm_fake_ndisc_add_prefix(NMFakeNDisc * self, +nm_fake_ndisc_add_prefix(NMFakeNDisc *self, guint ra_id, - const char * network, + const char *network, guint plen, - const char * gateway, + const char *gateway, gint64 expiry_msec, gint64 expiry_preferred_msec, NMIcmpv6RouterPref preference) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); - FakeRa * ra = find_ra(priv->ras, ra_id); - FakePrefix * prefix; + FakeRa *ra = find_ra(priv->ras, ra_id); + FakePrefix *prefix; g_assert(ra); @@ -175,12 +176,12 @@ nm_fake_ndisc_add_prefix(NMFakeNDisc * self, void nm_fake_ndisc_add_dns_server(NMFakeNDisc *self, guint ra_id, - const char * address, + const char *address, gint64 expiry_msec) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); - FakeRa * ra = find_ra(priv->ras, ra_id); - NMNDiscDNSServer * dns; + FakeRa *ra = find_ra(priv->ras, ra_id); + NMNDiscDNSServer *dns; g_assert(ra); @@ -195,8 +196,8 @@ void nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, guint ra_id, const char *domain, gint64 expiry_msec) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); - FakeRa * ra = find_ra(priv->ras, ra_id); - NMNDiscDNSDomain * dns; + FakeRa *ra = find_ra(priv->ras, ra_id); + NMNDiscDNSDomain *dns; g_assert(ra); @@ -225,11 +226,11 @@ send_rs(NMNDisc *ndisc, GError **error) static gboolean receive_ra(gpointer user_data) { - NMFakeNDisc * self = user_data; - NMFakeNDiscPrivate * priv = NM_FAKE_NDISC_GET_PRIVATE(self); - NMNDisc * ndisc = NM_NDISC(self); + NMFakeNDisc *self = user_data; + NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); + NMNDisc *ndisc = NM_NDISC(self); NMNDiscDataInternal *rdata = ndisc->rdata; - FakeRa * ra = priv->ras->data; + FakeRa *ra = priv->ras->data; NMNDiscConfigMap changed = 0; const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); guint i; @@ -253,7 +254,7 @@ receive_ra(gpointer user_data) } for (i = 0; i < ra->prefixes->len; i++) { - FakePrefix * item = &g_array_index(ra->prefixes, FakePrefix, i); + FakePrefix *item = &g_array_index(ra->prefixes, FakePrefix, i); const NMNDiscRoute route = { .network = item->network, .plen = item->plen, @@ -322,7 +323,7 @@ static void start(NMNDisc *ndisc) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(ndisc); - FakeRa * ra; + FakeRa *ra; /* Queue up the first fake RA */ g_assert(priv->ras); @@ -354,28 +355,23 @@ nm_fake_ndisc_init(NMFakeNDisc *fake_ndisc) {} NMNDisc * -nm_fake_ndisc_new(int ifindex, const char *ifname) +nm_fake_ndisc_new(NML3Cfg *l3cfg) { - return g_object_new(NM_TYPE_FAKE_NDISC, - NM_NDISC_IFINDEX, - ifindex, - NM_NDISC_IFNAME, - ifname, - NM_NDISC_NODE_TYPE, - (int) NM_NDISC_NODE_TYPE_HOST, - NM_NDISC_STABLE_TYPE, - (int) NM_UTILS_STABLE_TYPE_UUID, - NM_NDISC_NETWORK_ID, - "fake", - NM_NDISC_MAX_ADDRESSES, - NM_NDISC_MAX_ADDRESSES_DEFAULT, - NM_NDISC_ROUTER_SOLICITATIONS, - NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT, - NM_NDISC_ROUTER_SOLICITATION_INTERVAL, - NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL, - NM_NDISC_RA_TIMEOUT, - 30u, - NULL); + const NMNDiscConfig config = { + .l3cfg = g_object_ref(NM_L3CFG(l3cfg)), + .ifname = nm_l3cfg_get_ifname(l3cfg, TRUE), + .node_type = NM_NDISC_NODE_TYPE_HOST, + .stable_type = NM_UTILS_STABLE_TYPE_UUID, + .network_id = "fake", + .max_addresses = NM_NDISC_MAX_ADDRESSES_DEFAULT, + .router_solicitations = NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT, + .router_solicitation_interval = NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL, + .ra_timeout = 30u, + .addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + }; + + return g_object_new(NM_TYPE_FAKE_NDISC, NM_NDISC_CONFIG, &config, NULL); } static void diff --git a/src/core/ndisc/nm-fake-ndisc.h b/src/core/ndisc/nm-fake-ndisc.h index 677f15fc..91c2c21c 100644 --- a/src/core/ndisc/nm-fake-ndisc.h +++ b/src/core/ndisc/nm-fake-ndisc.h @@ -24,37 +24,37 @@ typedef struct _NMFakeRNDiscClass NMFakeNDiscClass; GType nm_fake_ndisc_get_type(void); -NMNDisc *nm_fake_ndisc_new(int ifindex, const char *ifname); +NMNDisc *nm_fake_ndisc_new(NML3Cfg *l3cfg); -guint nm_fake_ndisc_add_ra(NMFakeNDisc * self, +guint nm_fake_ndisc_add_ra(NMFakeNDisc *self, guint seconds, NMNDiscDHCPLevel dhcp_level, int hop_limit, guint32 mtu); -void nm_fake_ndisc_add_gateway(NMFakeNDisc * self, +void nm_fake_ndisc_add_gateway(NMFakeNDisc *self, guint ra_id, - const char * addr, + const char *addr, gint64 expiry_msec, NMIcmpv6RouterPref preference); -void nm_fake_ndisc_add_prefix(NMFakeNDisc * self, +void nm_fake_ndisc_add_prefix(NMFakeNDisc *self, guint ra_id, - const char * network, + const char *network, guint plen, - const char * gateway, + const char *gateway, gint64 expiry_msec, gint64 expiry_preferred_msec, NMIcmpv6RouterPref preference); void nm_fake_ndisc_add_dns_server(NMFakeNDisc *self, guint ra_id, - const char * address, + const char *address, gint64 expiry_msec); void nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, guint ra_id, - const char * domain, + const char *domain, gint64 expiry_msec); void nm_fake_ndisc_emit_new_ras(NMFakeNDisc *self); diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index 552b0e4b..313756a6 100644 --- a/src/core/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -9,16 +9,16 @@ #include <arpa/inet.h> #include <netinet/icmp6.h> -/* stdarg.h included because of a bug in ndp.h */ #include <stdarg.h> #include <ndp.h> -#include "libnm-glib-aux/nm-str-buf.h" -#include "libnm-systemd-shared/nm-sd-utils-shared.h" -#include "nm-ndisc-private.h" #include "NetworkManagerUtils.h" +#include "libnm-glib-aux/nm-str-buf.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-netns.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" +#include "nm-l3cfg.h" +#include "nm-ndisc-private.h" #define _NMLOG_PREFIX_NAME "ndisc-lndp" @@ -26,7 +26,7 @@ typedef struct { struct ndp *ndp; - GSource * event_source; + GSource *event_source; } NMLndpNDiscPrivate; /*****************************************************************************/ @@ -53,7 +53,7 @@ static gboolean send_rs(NMNDisc *ndisc, GError **error) { NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); - struct ndp_msg * msg; + struct ndp_msg *msg; int errsv; errsv = ndp_msg_new(&msg, NDP_MSG_RS); @@ -112,10 +112,10 @@ _route_preference_coerce(enum ndp_route_preference pref) static int receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) { - NMNDisc * ndisc = (NMNDisc *) user_data; + NMNDisc *ndisc = (NMNDisc *) user_data; NMNDiscDataInternal *rdata = ndisc->rdata; NMNDiscConfigMap changed = 0; - struct ndp_msgra * msgra = ndp_msgra(msg); + struct ndp_msgra *msgra = ndp_msgra(msg); struct in6_addr gateway_addr; const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); int offset; @@ -386,11 +386,11 @@ G_STATIC_ASSERT(sizeof(NMLndpDnsslOption) == 8u); static gboolean send_ra(NMNDisc *ndisc, GError **error) { - NMLndpNDiscPrivate * priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); - NMNDiscDataInternal * rdata = ndisc->rdata; + NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); + NMNDiscDataInternal *rdata = ndisc->rdata; int errsv; - struct in6_addr * addr; - struct ndp_msg * msg; + struct in6_addr *addr; + struct ndp_msg *msg; guint i; nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE); @@ -417,7 +417,7 @@ send_ra(NMNDisc *ndisc, GError **error) /* The device let us know about all addresses that the device got * whose prefixes are suitable for delegating. Let's announce them. */ for (i = 0; i < rdata->addresses->len; i++) { - const NMNDiscAddress * address = &g_array_index(rdata->addresses, NMNDiscAddress, i); + const NMNDiscAddress *address = &g_array_index(rdata->addresses, NMNDiscAddress, i); struct nd_opt_prefix_info *prefix; prefix = _ndp_msg_add_option(msg, sizeof(*prefix)); @@ -573,9 +573,9 @@ receive_rs(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) static gboolean event_ready(int fd, GIOCondition condition, gpointer user_data) { - gs_unref_object NMNDisc *ndisc = g_object_ref(NM_NDISC(user_data)); + gs_unref_object NMNDisc *ndisc = g_object_ref(NM_NDISC(user_data)); nm_auto_pop_netns NMPNetns *netns = NULL; - NMLndpNDiscPrivate * priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); + NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); _LOGD("processing libndp events"); @@ -669,72 +669,39 @@ nm_lndp_ndisc_init(NMLndpNDisc *lndp_ndisc) {} NMNDisc * -nm_lndp_ndisc_new(NMPlatform * platform, - int ifindex, - const char * ifname, - NMUtilsStableType stable_type, - const char * network_id, - NMSettingIP6ConfigAddrGenMode addr_gen_mode, - NMNDiscNodeType node_type, - int max_addresses, - int router_solicitations, - int router_solicitation_interval, - guint32 ra_timeout, - GError ** error) +nm_lndp_ndisc_new(const NMNDiscConfig *config) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDisc * ndisc; - NMLndpNDiscPrivate * priv; + gs_unref_object NMNDisc *ndisc = NULL; + NMLndpNDiscPrivate *priv; int errsv; - g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL); - g_return_val_if_fail(!error || !*error, NULL); - g_return_val_if_fail(network_id, NULL); + g_return_val_if_fail(config, NULL); + g_return_val_if_fail(NM_IS_L3CFG(config->l3cfg), NULL); + g_return_val_if_fail(config->network_id, NULL); - if (!nm_platform_netns_push(platform, &netns)) - return NULL; + if (!nm_platform_netns_push(nm_l3cfg_get_platform(config->l3cfg), &netns)) { + /* The inability to change the name space is also considered + * a fatal error. We have a FD open to the file descriptor, and + * it's unclear how to handle (or recover from) a failure to setns(). */ + g_return_val_if_reached(NULL); + } - ndisc = g_object_new(NM_TYPE_LNDP_NDISC, - NM_NDISC_PLATFORM, - platform, - NM_NDISC_STABLE_TYPE, - (int) stable_type, - NM_NDISC_IFINDEX, - ifindex, - NM_NDISC_IFNAME, - ifname, - NM_NDISC_NETWORK_ID, - network_id, - NM_NDISC_ADDR_GEN_MODE, - (int) addr_gen_mode, - NM_NDISC_NODE_TYPE, - (int) node_type, - NM_NDISC_MAX_ADDRESSES, - max_addresses, - NM_NDISC_ROUTER_SOLICITATIONS, - router_solicitations, - NM_NDISC_ROUTER_SOLICITATION_INTERVAL, - router_solicitation_interval, - NM_NDISC_RA_TIMEOUT, - (guint) ra_timeout, - NULL); + ndisc = g_object_new(NM_TYPE_LNDP_NDISC, NM_NDISC_CONFIG, config, NULL); priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); errsv = ndp_open(&priv->ndp); if (errsv != 0) { - errsv = nm_errno_native(errsv); - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "failure creating libndp socket: %s (%d)", - nm_strerror_native(errsv), - errsv); - g_object_unref(ndisc); - return NULL; + /* This is serious. It might be ENOMEM or the inability to open (or modify) + * a file descriptor. In all cases there is not much reason trying to recover + * from that. File descriptors are a basic resource, that we just require (just + * like memory). */ + g_return_val_if_reached(NULL); } - return ndisc; + + return g_steal_pointer(&ndisc); } static void @@ -754,8 +721,9 @@ nm_lndp_ndisc_class_init(NMLndpNDiscClass *klass) NMNDiscClass *ndisc_class = NM_NDISC_CLASS(klass); object_class->dispose = dispose; - ndisc_class->start = start; - ndisc_class->stop = stop; - ndisc_class->send_rs = send_rs; - ndisc_class->send_ra = send_ra; + + ndisc_class->start = start; + ndisc_class->stop = stop; + ndisc_class->send_rs = send_rs; + ndisc_class->send_ra = send_ra; } diff --git a/src/core/ndisc/nm-lndp-ndisc.h b/src/core/ndisc/nm-lndp-ndisc.h index 151f4bf7..711a95e1 100644 --- a/src/core/ndisc/nm-lndp-ndisc.h +++ b/src/core/ndisc/nm-lndp-ndisc.h @@ -23,17 +23,6 @@ typedef struct _NMLndpNDiscClass NMLndpNDiscClass; GType nm_lndp_ndisc_get_type(void); -NMNDisc *nm_lndp_ndisc_new(NMPlatform * platform, - int ifindex, - const char * ifname, - NMUtilsStableType stable_type, - const char * network_id, - NMSettingIP6ConfigAddrGenMode addr_gen_mode, - NMNDiscNodeType node_type, - int max_addresses, - int router_solicitations, - int router_solicitation_interval, - guint32 ra_timeout, - GError ** error); +NMNDisc *nm_lndp_ndisc_new(const NMNDiscConfig *config); #endif /* __NETWORKMANAGER_LNDP_NDISC_H__ */ diff --git a/src/core/ndisc/nm-ndisc-private.h b/src/core/ndisc/nm-ndisc-private.h index 04739124..1479e566 100644 --- a/src/core/ndisc/nm-ndisc-private.h +++ b/src/core/ndisc/nm-ndisc-private.h @@ -45,7 +45,7 @@ gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_ite if (nm_logging_enabled(__level, __domain)) { \ NMNDisc *const __self = (self); \ char __prefix[64]; \ - const char * __ifname = __self ? nm_ndisc_get_ifname(__self) : NULL; \ + const char *__ifname = __self ? nm_ndisc_get_ifname(__self) : NULL; \ \ _nm_log(__level, \ __domain, \ diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index d7b1a2e1..969eacfa 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -7,16 +7,17 @@ #include "nm-ndisc.h" -#include <stdlib.h> #include <arpa/inet.h> +#include <stdlib.h> -#include "nm-setting-ip6-config.h" - -#include "nm-ndisc-private.h" -#include "nm-utils.h" +#include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-netns.h" #include "nm-l3-config-data.h" +#include "nm-l3cfg.h" +#include "nm-ndisc-private.h" +#include "nm-setting-ip6-config.h" +#include "nm-utils.h" #define _NMLOG_PREFIX_NAME "ndisc" @@ -38,6 +39,8 @@ struct _NMNDiscPrivate { /* this *must* be the first field. */ NMNDiscDataInternal rdata; + const NML3ConfigData *l3cd; + char *last_error; GSource *ra_timeout_source; @@ -54,38 +57,27 @@ struct _NMNDiscPrivate { GSource *timeout_expire_source; NMUtilsIPv6IfaceId iid; + gboolean iid_is_token; - /* immutable values: */ - int ifindex; - char * ifname; - char * network_id; - guint max_addresses; - NMSettingIP6ConfigAddrGenMode addr_gen_mode; - NMUtilsStableType stable_type; - guint32 ra_timeout; - gint32 router_solicitations; - gint32 router_solicitation_interval; - NMNDiscNodeType node_type; - - NMPlatform *platform; - NMPNetns * netns; + /* immutable values from here on: */ + + union { + const NMNDiscConfig config; + NMNDiscConfig config_; + }; + + NMPNetns *netns; }; typedef struct _NMNDiscPrivate NMNDiscPrivate; -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PLATFORM, - PROP_IFINDEX, - PROP_IFNAME, - PROP_STABLE_TYPE, - PROP_NETWORK_ID, - PROP_ADDR_GEN_MODE, - PROP_MAX_ADDRESSES, - PROP_RA_TIMEOUT, - PROP_ROUTER_SOLICITATIONS, - PROP_ROUTER_SOLICITATION_INTERVAL, - PROP_NODE_TYPE, ); +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CONFIG, ); -enum { CONFIG_RECEIVED, RA_TIMEOUT_SIGNAL, LAST_SIGNAL }; +enum { + CONFIG_RECEIVED, + RA_TIMEOUT_SIGNAL, + LAST_SIGNAL, +}; static guint signals[LAST_SIGNAL] = {0}; @@ -111,18 +103,14 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_ndisc_dhcp_level_to_string, /*****************************************************************************/ NML3ConfigData * -nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, +nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx, int ifindex, - const NMNDiscData * rdata, + const NMNDiscData *rdata, NMSettingIP6ConfigPrivacy ip6_privacy, - guint32 route_table, - guint32 route_metric, - gboolean kernel_support_rta_pref, - gboolean kernel_support_extended_ifa_flags) + NMUtilsIPv6IfaceId *token) { nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; guint32 ifa_flags; - guint8 plen; guint i; const gint32 now_sec = nm_utils_get_monotonic_timestamp_sec(); @@ -130,20 +118,11 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, nm_l3_config_data_set_ip6_privacy(l3cd, ip6_privacy); - /* Check, whether kernel is recent enough to help user space handling RA. - * If it's not supported, we have no ipv6-privacy and must add autoconf - * addresses as /128. The reason for the /128 is to prevent the kernel - * from adding a prefix route for this address. */ - ifa_flags = 0; - if (kernel_support_extended_ifa_flags) { - ifa_flags |= IFA_F_NOPREFIXROUTE; - if (NM_IN_SET(ip6_privacy, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) - ifa_flags |= IFA_F_MANAGETEMPADDR; - plen = 64; - } else - plen = 128; + ifa_flags = IFA_F_NOPREFIXROUTE; + if (NM_IN_SET(ip6_privacy, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) + ifa_flags |= IFA_F_MANAGETEMPADDR; for (i = 0; i < rdata->addresses_n; i++) { const NMNDiscAddress *ndisc_addr = &rdata->addresses[i]; @@ -152,7 +131,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, a = (NMPlatformIP6Address){ .ifindex = ifindex, .address = ndisc_addr->address, - .plen = plen, + .plen = 64, .timestamp = now_sec, .lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) now_sec) * 1000, ndisc_addr->expiry_msec, @@ -178,8 +157,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, .plen = ndisc_route->plen, .gateway = ndisc_route->gateway, .rt_source = NM_IP_CONFIG_SOURCE_NDISC, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, .rt_pref = ndisc_route->preference, }; nm_assert((NMIcmpv6RouterPref) r.rt_pref == ndisc_route->preference); @@ -188,12 +169,13 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, } if (rdata->gateways_n > 0) { - const NMIcmpv6RouterPref first_pref = rdata->gateways[0].preference; - NMPlatformIP6Route r = { + NMPlatformIP6Route r = { .rt_source = NM_IP_CONFIG_SOURCE_NDISC, .ifindex = ifindex, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, }; for (i = 0; i < rdata->gateways_n; i++) { @@ -201,13 +183,6 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, r.rt_pref = rdata->gateways[i].preference; nm_assert((NMIcmpv6RouterPref) r.rt_pref == rdata->gateways[i].preference); nm_l3_config_data_add_route_6(l3cd, &r); - - if (first_pref != rdata->gateways[i].preference && !kernel_support_rta_pref) { - /* We are unable to configure a router preference. Hence, we skip all gateways - * with a different preference from the first gateway. Note, that the gateways - * are sorted in order of highest to lowest preference. */ - break; - } } } @@ -222,6 +197,8 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, nm_l3_config_data_set_ndisc_retrans_timer_msec(l3cd, rdata->retrans_timer_ms); nm_l3_config_data_set_ip6_mtu(l3cd, rdata->mtu); + if (token) + nm_l3_config_data_set_ip6_token(l3cd, *token); return g_steal_pointer(&l3cd); } @@ -315,7 +292,7 @@ nm_ndisc_get_ifindex(NMNDisc *self) { g_return_val_if_fail(NM_IS_NDISC(self), 0); - return NM_NDISC_GET_PRIVATE(self)->ifindex; + return nm_l3cfg_get_ifindex(NM_NDISC_GET_PRIVATE(self)->config.l3cfg); } const char * @@ -323,7 +300,7 @@ nm_ndisc_get_ifname(NMNDisc *self) { g_return_val_if_fail(NM_IS_NDISC(self), NULL); - return NM_NDISC_GET_PRIVATE(self)->ifname; + return NM_NDISC_GET_PRIVATE(self)->config.ifname; } NMNDiscNodeType @@ -331,7 +308,7 @@ nm_ndisc_get_node_type(NMNDisc *self) { g_return_val_if_fail(NM_IS_NDISC(self), NM_NDISC_NODE_TYPE_INVALID); - return NM_NDISC_GET_PRIVATE(self)->node_type; + return NM_NDISC_GET_PRIVATE(self)->config.node_type; } /*****************************************************************************/ @@ -391,15 +368,28 @@ _data_complete(NMNDiscDataInternal *data) return &data->public; } -void +static void nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed) { + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(self); + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + const NMNDiscData *rdata; + _config_changed_log(self, changed); - g_signal_emit(self, - signals[CONFIG_RECEIVED], - 0, - _data_complete(&NM_NDISC_GET_PRIVATE(self)->rdata), - (guint) changed); + + rdata = _data_complete(&NM_NDISC_GET_PRIVATE(self)->rdata), + + l3cd = nm_ndisc_data_to_l3cd(nm_l3cfg_get_multi_idx(priv->config.l3cfg), + nm_l3cfg_get_ifindex(priv->config.l3cfg), + rdata, + priv->config.ip6_privacy, + priv->iid_is_token ? &priv->iid : NULL); + l3cd = nm_l3_config_data_seal(l3cd); + + if (!nm_l3_config_data_equal(priv->l3cd, l3cd)) + NM_SWAP(&priv->l3cd, &l3cd); + + g_signal_emit(self, signals[CONFIG_RECEIVED], 0, rdata, (guint) changed, priv->l3cd); } /*****************************************************************************/ @@ -474,16 +464,16 @@ static gboolean complete_address(NMNDisc *ndisc, NMNDiscAddress *addr) { NMNDiscPrivate *priv; - GError * error = NULL; + GError *error = NULL; g_return_val_if_fail(NM_IS_NDISC(ndisc), FALSE); priv = NM_NDISC_GET_PRIVATE(ndisc); - if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { - if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(priv->stable_type, + if (priv->config.addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { + if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(priv->config.stable_type, &addr->address, - priv->ifname, - priv->network_id, + priv->config.ifname, + priv->config.network_id, addr->dad_counter++, &error)) { _LOGW("complete-address: failed to generate an stable-privacy address: %s", @@ -511,15 +501,15 @@ complete_address(NMNDisc *ndisc, NMNDiscAddress *addr) } static gboolean -nm_ndisc_add_address(NMNDisc * ndisc, +nm_ndisc_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec, gboolean from_ra) { - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); NMNDiscDataInternal *rdata = &priv->rdata; - NMNDiscAddress * new2; - NMNDiscAddress * existing = NULL; + NMNDiscAddress *new2; + NMNDiscAddress *existing = NULL; guint i; nm_assert(new_item); @@ -608,7 +598,7 @@ nm_ndisc_add_address(NMNDisc * ndisc, * what the kernel does, because it considers *all* addresses (including * static and other temporary addresses). **/ - if (rdata->addresses->len >= priv->max_addresses) + if (rdata->addresses->len >= priv->config.max_addresses) return FALSE; if (new_item->expiry_msec <= now_msec) @@ -640,7 +630,7 @@ nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; guint i; guint insert_idx = G_MAXUINT; @@ -709,7 +699,7 @@ nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; guint i; @@ -747,9 +737,9 @@ nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; - NMNDiscDNSDomain * item; + NMNDiscDNSDomain *item; guint i; priv = NM_NDISC_GET_PRIVATE(ndisc); @@ -824,13 +814,13 @@ solicit_retransmit_time_jitter(gint32 solicit_retransmit_time_msec) static gboolean solicit_timer_cb(gpointer user_data) { - const gint32 TIMEOUT_APPROX_THRESHOLD_SEC = 10000; - nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDisc * ndisc = user_data; - NMNDiscClass * klass = NM_NDISC_GET_CLASS(ndisc); - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); - gs_free_error GError *error = NULL; - gint32 timeout_msec; + const gint32 TIMEOUT_APPROX_THRESHOLD_SEC = 10000; + nm_auto_pop_netns NMPNetns *netns = NULL; + NMNDisc *ndisc = user_data; + NMNDiscClass *klass = NM_NDISC_GET_CLASS(ndisc); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); + gs_free_error GError *error = NULL; + gint32 timeout_msec; if (!nm_ndisc_netns_push(ndisc, &netns)) { nm_utils_error_set(&error, @@ -899,7 +889,7 @@ solicit_timer_start(NMNDisc *ndisc) g_random_int() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); _LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds", - priv->router_solicitations, + priv->config.router_solicitations, ((double) delay_msec) / 1000); priv->solicit_retransmit_time_msec = 0; @@ -913,9 +903,9 @@ static gboolean announce_router(NMNDisc *ndisc) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDiscClass * klass = NM_NDISC_GET_CLASS(ndisc); - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); - GError * error = NULL; + NMNDiscClass *klass = NM_NDISC_GET_CLASS(ndisc); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); + GError *error = NULL; if (!nm_ndisc_netns_push(ndisc, &netns)) return G_SOURCE_REMOVE; @@ -997,30 +987,82 @@ announce_router_solicited(NMNDisc *ndisc) /*****************************************************************************/ void -nm_ndisc_set_config(NMNDisc * ndisc, - const GArray *addresses, - const GArray *dns_servers, - const GArray *dns_domains) +nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd) { - gboolean changed = FALSE; - guint i; + gboolean changed = FALSE; + const struct in6_addr *in6arr; + const char *const *strvarr; + NMDedupMultiIter iter; + const NMPObject *obj; + guint len; + guint i; + + nm_assert(NM_IS_NDISC(ndisc)); + nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER); + + nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP6_ADDRESS) { + const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj); + guint32 preferred; + guint32 lifetime; + NMNDiscAddress a; + + if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address)) + continue; + + if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED) + continue; + + if (addr->plen != 64) + continue; - for (i = 0; i < addresses->len; i++) { - if (nm_ndisc_add_address(ndisc, &g_array_index(addresses, NMNDiscAddress, i), 0, FALSE)) + lifetime = nmp_utils_lifetime_get(addr->timestamp, + addr->lifetime, + addr->preferred, + NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000, + &preferred); + if (!lifetime) + continue; + + a = (NMNDiscAddress){ + .address = addr->address, + .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime), + .expiry_preferred_msec = + _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred), + }; + + if (nm_ndisc_add_address(ndisc, &a, 0, FALSE)) changed = TRUE; } - for (i = 0; i < dns_servers->len; i++) { - if (nm_ndisc_add_dns_server(ndisc, - &g_array_index(dns_servers, NMNDiscDNSServer, i), - G_MININT64)) + in6arr = NULL; + len = 0; + if (l3cd) + in6arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET6, &len); + for (i = 0; i < len; i++) { + NMNDiscDNSServer n; + + n = (NMNDiscDNSServer){ + .address = in6arr[i], + .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, + NM_NDISC_ROUTER_LIFETIME), + }; + if (nm_ndisc_add_dns_server(ndisc, &n, G_MININT64)) changed = TRUE; } - for (i = 0; i < dns_domains->len; i++) { - if (nm_ndisc_add_dns_domain(ndisc, - &g_array_index(dns_domains, NMNDiscDNSDomain, i), - G_MININT64)) + strvarr = NULL; + len = 0; + if (l3cd) + strvarr = nm_l3_config_data_get_searches(l3cd, AF_INET6, &len); + for (i = 0; i < len; i++) { + NMNDiscDNSDomain n; + + n = (NMNDiscDNSDomain){ + .domain = (char *) strvarr[i], + .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, + NM_NDISC_ROUTER_LIFETIME), + }; + if (nm_ndisc_add_dns_domain(ndisc, &n, G_MININT64)) changed = TRUE; } @@ -1048,20 +1090,21 @@ nm_ndisc_set_config(NMNDisc * ndisc, * Returns: %TRUE if addresses need to be regenerated, %FALSE otherwise. **/ gboolean -nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid) +nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid, gboolean is_token) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; g_return_val_if_fail(NM_IS_NDISC(ndisc), FALSE); - priv = NM_NDISC_GET_PRIVATE(ndisc); - rdata = &priv->rdata; + priv = NM_NDISC_GET_PRIVATE(ndisc); + priv->iid_is_token = is_token; + rdata = &priv->rdata; if (priv->iid.id != iid.id) { priv->iid = iid; - if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) + if (priv->config.addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) return FALSE; if (rdata->addresses->len) { @@ -1090,7 +1133,7 @@ void nm_ndisc_start(NMNDisc *ndisc) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; g_return_if_fail(NM_IS_NDISC(ndisc)); @@ -1100,26 +1143,26 @@ nm_ndisc_start(NMNDisc *ndisc) nm_assert(!priv->ra_timeout_source); _LOGD("starting neighbor discovery for ifindex %d%s", - priv->ifindex, - priv->node_type == NM_NDISC_NODE_TYPE_HOST ? " (solicit)" : " (announce)"); + nm_l3cfg_get_ifindex(priv->config.l3cfg), + priv->config.node_type == NM_NDISC_NODE_TYPE_HOST ? " (solicit)" : " (announce)"); if (!nm_ndisc_netns_push(ndisc, &netns)) return; NM_NDISC_GET_CLASS(ndisc)->start(ndisc); - if (priv->node_type == NM_NDISC_NODE_TYPE_HOST) { + if (priv->config.node_type == NM_NDISC_NODE_TYPE_HOST) { G_STATIC_ASSERT_EXPR(NM_RA_TIMEOUT_DEFAULT == 0); G_STATIC_ASSERT_EXPR(NM_RA_TIMEOUT_INFINITY == G_MAXINT32); - nm_assert(priv->ra_timeout > 0u); - nm_assert(priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY); + nm_assert(priv->config.ra_timeout > 0u); + nm_assert(priv->config.ra_timeout <= NM_RA_TIMEOUT_INFINITY); - if (priv->ra_timeout < NM_RA_TIMEOUT_INFINITY) { + if (priv->config.ra_timeout < NM_RA_TIMEOUT_INFINITY) { guint timeout_msec; - _LOGD("scheduling RA timeout in %u seconds", priv->ra_timeout); - if (priv->ra_timeout < G_MAXUINT / 1000u) - timeout_msec = priv->ra_timeout * 1000u; + _LOGD("scheduling RA timeout in %u seconds", priv->config.ra_timeout); + if (priv->config.ra_timeout < G_MAXUINT / 1000u) + timeout_msec = priv->config.ra_timeout * 1000u; else timeout_msec = G_MAXUINT; priv->ra_timeout_source = nm_g_timeout_add_source(timeout_msec, ra_timeout_cb, ndisc); @@ -1129,8 +1172,8 @@ nm_ndisc_start(NMNDisc *ndisc) return; } - nm_assert(priv->ra_timeout == 0u); - nm_assert(priv->node_type == NM_NDISC_NODE_TYPE_ROUTER); + nm_assert(priv->config.ra_timeout == 0u); + nm_assert(priv->config.node_type == NM_NDISC_NODE_TYPE_ROUTER); announce_router_initial(ndisc); } @@ -1138,8 +1181,8 @@ void nm_ndisc_stop(NMNDisc *ndisc) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDiscDataInternal * rdata; - NMNDiscPrivate * priv; + NMNDiscDataInternal *rdata; + NMNDiscPrivate *priv; g_return_if_fail(NM_IS_NDISC(ndisc)); @@ -1147,7 +1190,7 @@ nm_ndisc_stop(NMNDisc *ndisc) nm_assert(NM_NDISC_GET_CLASS(ndisc)->stop); - _LOGD("stopping neighbor discovery for ifindex %d", priv->ifindex); + _LOGD("stopping neighbor discovery for ifindex %d", nm_l3cfg_get_ifindex(priv->config.l3cfg)); if (!nm_ndisc_netns_push(ndisc, &netns)) return; @@ -1230,7 +1273,7 @@ config_map_to_string(NMNDiscConfigMap map, char *p) static void _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; guint i; char changedstr[CONFIG_MAP_MAX_STR]; @@ -1319,7 +1362,7 @@ static void clean_gateways(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; - NMNDiscGateway * arr; + NMNDiscGateway *arr; guint i; guint j; @@ -1350,9 +1393,9 @@ clean_gateways(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint6 static void clean_addresses(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; - NMNDiscAddress * arr; + NMNDiscAddress *arr; guint i; guint j; @@ -1374,7 +1417,7 @@ clean_addresses(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint g_array_set_size(rdata->addresses, j); } - if (_array_set_size_max(rdata->gateways, priv->max_addresses)) + if (_array_set_size_max(rdata->gateways, priv->config.max_addresses)) *changed |= NM_NDISC_CONFIG_ADDRESSES; } @@ -1382,7 +1425,7 @@ static void clean_routes(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; - NMNDiscRoute * arr; + NMNDiscRoute *arr; guint i; guint j; @@ -1412,7 +1455,7 @@ static void clean_dns_servers(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; - NMNDiscDNSServer * arr; + NMNDiscDNSServer *arr; guint i; guint j; @@ -1442,7 +1485,7 @@ static void clean_dns_domains(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; - NMNDiscDNSDomain * arr; + NMNDiscDNSDomain *arr; guint i; guint j; @@ -1549,7 +1592,7 @@ _calc_pre_expiry_rs_msec_worker(gint64 *earliest_expiry_msec, static gint64 calc_pre_expiry_rs_msec(NMNDisc *ndisc) { - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); NMNDiscDataInternal *rdata = &priv->rdata; gint64 expiry_msec = NM_NDISC_EXPIRY_INFINITY; guint i; @@ -1657,10 +1700,10 @@ ipv6_sysctl_get(NMPlatform *platform, void nm_ndisc_get_sysctl(NMPlatform *platform, const char *ifname, - int * out_max_addresses, - int * out_router_solicitations, - int * out_router_solicitation_interval, - guint32 * out_default_ra_timeout) + int *out_max_addresses, + int *out_router_solicitations, + int *out_router_solicitation_interval, + guint32 *out_default_ra_timeout) { int router_solicitation_interval = 0; int router_solicitations = 0; @@ -1700,85 +1743,87 @@ nm_ndisc_get_sysctl(NMPlatform *platform, /*****************************************************************************/ static void +_config_clear(NMNDiscConfig *config) +{ + g_clear_object(&config->l3cfg); + nm_clear_g_free((gpointer *) &config->ifname); + nm_clear_g_free((gpointer *) &config->network_id); +} + +static void +_config_init(NMNDiscConfig *config, const NMNDiscConfig *src) +{ + nm_assert(config); + g_return_if_fail(src); + + /* we only allow to set @config if it was cleared (or is not yet initialized). */ + nm_assert(!config->l3cfg); + nm_assert(!config->ifname); + nm_assert(!config->network_id); + + g_return_if_fail(NM_IS_L3CFG(src->l3cfg)); + + *config = *src; + + g_object_ref(config->l3cfg); + config->ifname = g_strdup(config->ifname); + config->network_id = g_strdup(config->network_id); + + if (config->max_addresses <= 0) + config->max_addresses = _SIZE_MAX_ADDRESSES; + else if (config->max_addresses > 3u * _SIZE_MAX_ADDRESSES) + config->max_addresses = 3u * _SIZE_MAX_ADDRESSES; + + /* This setter is only used in specific circumstances, and in this case, + * we expect that @src only contains valid settings. We thus assert that to + * be the case.*/ + g_return_if_fail(config->ifname && config->ifname[0]); + g_return_if_fail(config->network_id); + g_return_if_fail(config->stable_type >= NM_UTILS_STABLE_TYPE_UUID + && config->stable_type <= NM_UTILS_STABLE_TYPE_RANDOM); + g_return_if_fail(config->addr_gen_mode >= NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 + && config->addr_gen_mode + <= NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY); + nm_assert(config->max_addresses >= 0 && config->max_addresses <= G_MAXINT32); + G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_RA_TIMEOUT_INFINITY); + g_return_if_fail(config->ra_timeout <= NM_RA_TIMEOUT_INFINITY); + g_return_if_fail(config->router_solicitations > 0 + && config->router_solicitations <= G_MAXINT32); + g_return_if_fail(config->router_solicitation_interval > 0 + && config->router_solicitation_interval <= G_MAXINT32); + g_return_if_fail( + NM_IN_SET(config->node_type, NM_NDISC_NODE_TYPE_HOST, NM_NDISC_NODE_TYPE_ROUTER)); + g_return_if_fail(NM_IN_SET(config->ip6_privacy, + NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); +} + +/*****************************************************************************/ + +static void dns_domain_free(gpointer data) { g_free(((NMNDiscDNSDomain *) (data))->domain); } +/*****************************************************************************/ + static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMNDisc * self = NM_NDISC(object); + NMNDisc *self = NM_NDISC(object); NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(self); - int i; switch (prop_id) { - case PROP_PLATFORM: + case PROP_CONFIG: /* construct-only */ - priv->platform = g_value_get_object(value) ?: NM_PLATFORM_GET; - if (!priv->platform) - g_return_if_reached(); - - g_object_ref(priv->platform); - - priv->netns = nm_platform_netns_get(priv->platform); - if (priv->netns) - g_object_ref(priv->netns); + _config_init(&priv->config_, g_value_get_pointer(value)); + priv->netns = + nm_g_object_ref(nm_platform_netns_get(nm_l3cfg_get_platform(priv->config.l3cfg))); g_return_if_fail(!priv->netns || priv->netns == nmp_netns_get_current()); break; - case PROP_IFINDEX: - /* construct-only */ - priv->ifindex = g_value_get_int(value); - g_return_if_fail(priv->ifindex > 0); - break; - case PROP_IFNAME: - /* construct-only */ - priv->ifname = g_value_dup_string(value); - g_return_if_fail(priv->ifname && priv->ifname[0]); - break; - case PROP_STABLE_TYPE: - /* construct-only */ - priv->stable_type = g_value_get_int(value); - break; - case PROP_NETWORK_ID: - /* construct-only */ - priv->network_id = g_value_dup_string(value); - g_return_if_fail(priv->network_id); - break; - case PROP_ADDR_GEN_MODE: - /* construct-only */ - priv->addr_gen_mode = g_value_get_int(value); - break; - case PROP_MAX_ADDRESSES: - /* construct-only */ - i = g_value_get_int(value); - nm_assert(i >= 0); - priv->max_addresses = i; - - if (priv->max_addresses <= 0) - priv->max_addresses = _SIZE_MAX_ADDRESSES; - else if (priv->max_addresses > 3u * _SIZE_MAX_ADDRESSES) - priv->max_addresses = 3u * _SIZE_MAX_ADDRESSES; - break; - case PROP_RA_TIMEOUT: - /* construct-only */ - priv->ra_timeout = g_value_get_uint(value); - nm_assert(priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY); - break; - case PROP_ROUTER_SOLICITATIONS: - /* construct-only */ - priv->router_solicitations = g_value_get_int(value); - break; - case PROP_ROUTER_SOLICITATION_INTERVAL: - /* construct-only */ - priv->router_solicitation_interval = g_value_get_int(value); - break; - case PROP_NODE_TYPE: - /* construct-only */ - priv->node_type = g_value_get_int(value); - nm_assert(NM_IN_SET(priv->node_type, NM_NDISC_NODE_TYPE_HOST, NM_NDISC_NODE_TYPE_ROUTER)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -1788,7 +1833,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps static void nm_ndisc_init(NMNDisc *ndisc) { - NMNDiscPrivate * priv; + NMNDiscPrivate *priv; NMNDiscDataInternal *rdata; priv = G_TYPE_INSTANCE_GET_PRIVATE(ndisc, NM_TYPE_NDISC, NMNDiscPrivate); @@ -1808,7 +1853,7 @@ nm_ndisc_init(NMNDisc *ndisc) static void dispose(GObject *object) { - NMNDisc * ndisc = NM_NDISC(object); + NMNDisc *ndisc = NM_NDISC(object); NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); nm_clear_g_source_inst(&priv->ra_timeout_source); @@ -1824,13 +1869,10 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMNDisc * ndisc = NM_NDISC(object); - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDisc *ndisc = NM_NDISC(object); + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); NMNDiscDataInternal *rdata = &priv->rdata; - g_free(priv->ifname); - g_free(priv->network_id); - g_array_unref(rdata->gateways); g_array_unref(rdata->addresses); g_array_unref(rdata->routes); @@ -1838,7 +1880,10 @@ finalize(GObject *object) g_array_unref(rdata->dns_domains); g_clear_object(&priv->netns); - g_clear_object(&priv->platform); + + _config_clear(&priv->config_); + + nm_clear_l3cd(&priv->l3cd); G_OBJECT_CLASS(nm_ndisc_parent_class)->finalize(object); } @@ -1854,89 +1899,12 @@ nm_ndisc_class_init(NMNDiscClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - obj_properties[PROP_PLATFORM] = - g_param_spec_object(NM_NDISC_PLATFORM, - "", - "", - NM_TYPE_PLATFORM, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IFINDEX] = - g_param_spec_int(NM_NDISC_IFINDEX, - "", - "", - 0, - G_MAXINT, - 0, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IFNAME] = - g_param_spec_string(NM_NDISC_IFNAME, - "", - "", - NULL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_STABLE_TYPE] = - g_param_spec_int(NM_NDISC_STABLE_TYPE, - "", - "", - NM_UTILS_STABLE_TYPE_UUID, - NM_UTILS_STABLE_TYPE_RANDOM, - NM_UTILS_STABLE_TYPE_UUID, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_NETWORK_ID] = - g_param_spec_string(NM_NDISC_NETWORK_ID, - "", - "", - NULL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ADDR_GEN_MODE] = - g_param_spec_int(NM_NDISC_ADDR_GEN_MODE, - "", - "", - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_MAX_ADDRESSES] = - g_param_spec_int(NM_NDISC_MAX_ADDRESSES, - "", - "", - 0, - G_MAXINT32, - NM_NDISC_MAX_ADDRESSES_DEFAULT, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_RA_TIMEOUT_INFINITY); - obj_properties[PROP_RA_TIMEOUT] = - g_param_spec_uint(NM_NDISC_RA_TIMEOUT, - "", - "", - 0, - G_MAXINT32, - 0, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ROUTER_SOLICITATIONS] = - g_param_spec_int(NM_NDISC_ROUTER_SOLICITATIONS, - "", - "", - 1, - G_MAXINT32, - NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ROUTER_SOLICITATION_INTERVAL] = - g_param_spec_int(NM_NDISC_ROUTER_SOLICITATION_INTERVAL, - "", - "", - 1, - G_MAXINT32, - NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_NODE_TYPE] = - g_param_spec_int(NM_NDISC_NODE_TYPE, - "", - "", - NM_NDISC_NODE_TYPE_INVALID, - NM_NDISC_NODE_TYPE_ROUTER, - NM_NDISC_NODE_TYPE_INVALID, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CONFIG] = + g_param_spec_pointer(NM_NDISC_CONFIG, + "", + "", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[CONFIG_RECEIVED] = g_signal_new(NM_NDISC_CONFIG_RECEIVED, @@ -1947,9 +1915,14 @@ nm_ndisc_class_init(NMNDiscClass *klass) NULL, NULL, G_TYPE_NONE, - 2, - G_TYPE_POINTER, - G_TYPE_UINT); + 3, + G_TYPE_POINTER + /* (const NMNDiscData *)rdata */, + G_TYPE_UINT + /* (guint) changed_i */, + G_TYPE_POINTER + /* (const NML3ConfigData *) l3cd */ + ); signals[RA_TIMEOUT_SIGNAL] = g_signal_new(NM_NDISC_RA_TIMEOUT_SIGNAL, G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h index 5b827528..079ec037 100644 --- a/src/core/ndisc/nm-ndisc.h +++ b/src/core/ndisc/nm-ndisc.h @@ -26,17 +26,7 @@ #define NM_IS_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_NDISC)) #define NM_NDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NDISC, NMNDiscClass)) -#define NM_NDISC_PLATFORM "platform" -#define NM_NDISC_IFINDEX "ifindex" -#define NM_NDISC_IFNAME "ifname" -#define NM_NDISC_NETWORK_ID "network-id" -#define NM_NDISC_ADDR_GEN_MODE "addr-gen-mode" -#define NM_NDISC_STABLE_TYPE "stable-type" -#define NM_NDISC_NODE_TYPE "node-type" -#define NM_NDISC_MAX_ADDRESSES "max-addresses" -#define NM_NDISC_RA_TIMEOUT "ra-timeout" -#define NM_NDISC_ROUTER_SOLICITATIONS "router-solicitations" -#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL "router-solicitation-interval" +#define NM_NDISC_CONFIG "config" #define NM_NDISC_CONFIG_RECEIVED "config-received" #define NM_NDISC_RA_TIMEOUT_SIGNAL "ra-timeout-signal" @@ -133,7 +123,7 @@ typedef struct { } NMNDiscDNSServer; typedef struct { - char * domain; + char *domain; gint64 expiry_msec; } NMNDiscDNSDomain; @@ -169,6 +159,20 @@ typedef enum { #define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861, MaxRtrAdvInterval default */ #define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */ +typedef struct { + NML3Cfg *l3cfg; + const char *ifname; + const char *network_id; + int max_addresses; + int router_solicitations; + int router_solicitation_interval; + guint32 ra_timeout; + NMUtilsStableType stable_type; + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + NMNDiscNodeType node_type; + NMSettingIP6ConfigPrivacy ip6_privacy; +} NMNDiscConfig; + struct _NMNDiscPrivate; struct _NMNDiscDataInternal; @@ -185,9 +189,9 @@ typedef struct { guint dns_servers_n; guint dns_domains_n; - const NMNDiscGateway * gateways; - const NMNDiscAddress * addresses; - const NMNDiscRoute * routes; + const NMNDiscGateway *gateways; + const NMNDiscAddress *addresses; + const NMNDiscRoute *routes; const NMNDiscDNSServer *dns_servers; const NMNDiscDNSDomain *dns_domains; } NMNDiscData; @@ -201,7 +205,7 @@ typedef struct { typedef struct { GObject parent; union { - struct _NMNDiscPrivate * _priv; + struct _NMNDiscPrivate *_priv; struct _NMNDiscDataInternal *rdata; }; } NMNDisc; @@ -217,24 +221,19 @@ typedef struct { GType nm_ndisc_get_type(void); -void nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed); - int nm_ndisc_get_ifindex(NMNDisc *self); -const char * nm_ndisc_get_ifname(NMNDisc *self); +const char *nm_ndisc_get_ifname(NMNDisc *self); NMNDiscNodeType nm_ndisc_get_node_type(NMNDisc *self); -gboolean nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid); +gboolean nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid, gboolean is_token); void nm_ndisc_start(NMNDisc *ndisc); void nm_ndisc_stop(NMNDisc *ndisc); NMNDiscConfigMap nm_ndisc_dad_failed(NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal); -void nm_ndisc_set_config(NMNDisc * ndisc, - const GArray *addresses, - const GArray *dns_servers, - const GArray *dns_domains); +void nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd); NMPlatform *nm_ndisc_get_platform(NMNDisc *self); -NMPNetns * nm_ndisc_netns_get(NMNDisc *self); +NMPNetns *nm_ndisc_netns_get(NMNDisc *self); gboolean nm_ndisc_netns_push(NMNDisc *self, NMPNetns **netns); static inline gboolean @@ -268,22 +267,19 @@ nm_ndisc_dad_addr_is_fail_candidate(NMPlatform *platform, const NMPObject *obj) void nm_ndisc_get_sysctl(NMPlatform *platform, const char *ifname, - int * out_max_addresses, - int * out_router_solicitations, - int * out_router_solicitation_interval, - guint32 * out_default_ra_timeout); + int *out_max_addresses, + int *out_router_solicitations, + int *out_router_solicitation_interval, + guint32 *out_default_ra_timeout); /*****************************************************************************/ struct _NML3ConfigData; -struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, +struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx, int ifindex, - const NMNDiscData * rdata, + const NMNDiscData *rdata, NMSettingIP6ConfigPrivacy ip6_privacy, - guint32 route_table, - guint32 route_metric, - gboolean kernel_support_rta_pref, - gboolean kernel_support_extended_ifa_flags); + NMUtilsIPv6IfaceId *token); #endif /* __NETWORKMANAGER_NDISC_H__ */ diff --git a/src/core/ndisc/tests/test-ndisc-fake.c b/src/core/ndisc/tests/test-ndisc-fake.c index f201bc56..0763b64e 100644 --- a/src/core/ndisc/tests/test-ndisc-fake.c +++ b/src/core/ndisc/tests/test-ndisc-fake.c @@ -11,24 +11,29 @@ #include "ndisc/nm-fake-ndisc.h" #include "platform/nm-fake-platform.h" +#include "nm-netns.h" -#include "nm-test-utils-core.h" +#include "platform/tests/test-common.h" /*****************************************************************************/ static NMFakeNDisc * ndisc_new(void) { - NMNDisc * ndisc; - const int ifindex = 1; - const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex); - NMUtilsIPv6IfaceId iid = {}; + gs_unref_object NML3Cfg *l3cfg = NULL; + NMNDisc *ndisc; + const int ifindex = 1; + NMUtilsIPv6IfaceId iid; - ndisc = nm_fake_ndisc_new(ifindex, ifname); - iid.id_u8[7] = 1; - nm_ndisc_set_iid(ndisc, iid); + l3cfg = nm_netns_l3cfg_acquire(NM_NETNS_GET, ifindex); + + ndisc = nm_fake_ndisc_new(l3cfg); g_assert(ndisc); + memset(&iid, 0, sizeof(iid)); + iid.id_u8[7] = 1; + nm_ndisc_set_iid(ndisc, iid, FALSE); + return NM_FAKE_NDISC(ndisc); } @@ -37,7 +42,7 @@ ndisc_new(void) static void match_gateway(const NMNDiscData *rdata, guint idx, - const char * addr, + const char *addr, gint64 expiry_msec, NMIcmpv6RouterPref pref) { @@ -57,7 +62,7 @@ match_gateway(const NMNDiscData *rdata, #define match_address(rdata, idx, addr, _expiry_msec, _expiry_preferred_msec) \ G_STMT_START \ { \ - const NMNDiscData * _rdata = (rdata); \ + const NMNDiscData *_rdata = (rdata); \ guint _idx = (idx); \ const NMNDiscAddress *_a; \ \ @@ -76,7 +81,7 @@ match_gateway(const NMNDiscData *rdata, #define match_route(rdata, idx, nw, pl, gw, _expiry_msec, pref) \ G_STMT_START \ { \ - const NMNDiscData * _rdata = (rdata); \ + const NMNDiscData *_rdata = (rdata); \ guint _idx = (idx); \ const NMNDiscRoute *_r; \ int _plen = (pl); \ @@ -140,9 +145,15 @@ typedef struct { /*****************************************************************************/ static void -test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) +test_simple_changed(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + TestData *data) { - NMNDiscConfigMap changed = changed_int; + NMNDiscConfigMap changed = changed_i; + + _LOGT("test_simple: callback (counter=%u)", data->counter); switch (data->counter++) { case 0: @@ -180,12 +191,12 @@ test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, static void test_simple(void) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); - gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); - const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); - TestData data = { - .loop = loop, - .timestamp_msec_1 = now_msec, + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, }; guint id; @@ -206,9 +217,11 @@ test_simple(void) g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data); + _LOGT("test_simple: start"); nm_ndisc_start(NM_NDISC(ndisc)); nmtst_main_loop_run_assert(data.loop, 15000); g_assert_cmpint(data.counter, ==, 2); + _LOGT("test_simple: done"); } /*****************************************************************************/ @@ -221,9 +234,13 @@ test_everything_rs_sent(NMNDisc *ndisc, TestData *data) } static void -test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) +test_everything_changed(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + TestData *data) { - NMNDiscConfigMap changed = changed_int; + NMNDiscConfigMap changed = changed_i; if (data->counter == 0) { g_assert_cmpint(data->rs_counter, ==, 1); @@ -288,12 +305,12 @@ test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_ static void test_everything(void) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); - gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); - const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); - TestData data = { - .loop = loop, - .timestamp_msec_1 = now_msec, + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, }; guint id; @@ -342,12 +359,13 @@ test_everything(void) } static void -test_preference_order_cb(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) +test_preference_order_cb(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + TestData *data) { - NMNDiscConfigMap changed = changed_int; + NMNDiscConfigMap changed = changed_i; if (data->counter == 1) { g_assert_cmpint(changed, @@ -391,12 +409,12 @@ test_preference_order_cb(NMNDisc * ndisc, static void test_preference_order(void) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); - gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); - const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); - TestData data = { - .loop = loop, - .timestamp_msec_1 = now_msec, + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, }; guint id; @@ -434,12 +452,13 @@ test_preference_order(void) } static void -test_preference_changed_cb(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) +test_preference_changed_cb(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + TestData *data) { - NMNDiscConfigMap changed = changed_int; + NMNDiscConfigMap changed = changed_i; if (data->counter == 1) { g_assert_cmpint(changed, @@ -513,12 +532,12 @@ test_preference_changed_cb(NMNDisc * ndisc, static void test_preference_changed(void) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); - gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); - const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); - TestData data = { - .loop = loop, - .timestamp_msec_1 = now_msec, + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, }; guint id; @@ -576,10 +595,11 @@ test_preference_changed(void) /*****************************************************************************/ static void -_test_dns_solicit_loop_changed(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) +_test_dns_solicit_loop_changed(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + TestData *data) { data->counter++; } @@ -593,12 +613,12 @@ _test_dns_solicit_loop_rs_sent(NMFakeNDisc *ndisc, TestData *data) static void test_dns_solicit_loop(void) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); - gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); - const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); - TestData data = { - .loop = loop, - .timestamp_msec_1 = now_msec, + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, }; guint id; diff --git a/src/core/ndisc/tests/test-ndisc-linux.c b/src/core/ndisc/tests/test-ndisc-linux.c index 57021606..66c7e157 100644 --- a/src/core/ndisc/tests/test-ndisc-linux.c +++ b/src/core/ndisc/tests/test-ndisc-linux.c @@ -11,6 +11,8 @@ #include "ndisc/nm-lndp-ndisc.h" #include "libnm-platform/nm-linux-platform.h" +#include "nm-netns.h" +#include "nm-l3cfg.h" #include "nm-test-utils-core.h" @@ -19,16 +21,18 @@ NMTST_DEFINE(); int main(int argc, char **argv) { - GMainLoop * loop; - NMNDisc * ndisc; - int ifindex = 1; - const char * ifname; - NMUtilsIPv6IfaceId iid = {}; - GError * error = NULL; - int max_addresses; - int router_solicitations; - int router_solicitation_interval; - guint32 ra_timeout; + gs_unref_object NML3Cfg *l3cfg = NULL; + NMNDiscConfig config; + GMainLoop *loop; + NMNDisc *ndisc; + int ifindex = 1; + const char *ifname; + NMUtilsIPv6IfaceId iid = {}; + GError *error = NULL; + int max_addresses; + int router_solicitations; + int router_solicitation_interval; + guint32 ra_timeout; nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT"); @@ -56,18 +60,23 @@ main(int argc, char **argv) &router_solicitation_interval, &ra_timeout); - ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET, - ifindex, - ifname, - NM_UTILS_STABLE_TYPE_UUID, - "8ce666e8-d34d-4fb1-b858-f15a7al28086", - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NM_NDISC_NODE_TYPE_HOST, - max_addresses, - router_solicitations, - router_solicitation_interval, - ra_timeout, - &error); + l3cfg = nm_netns_l3cfg_acquire(NM_NETNS_GET, ifindex); + + config = (NMNDiscConfig){ + .l3cfg = l3cfg, + .ifname = nm_l3cfg_get_ifname(l3cfg, TRUE), + .stable_type = NM_UTILS_STABLE_TYPE_UUID, + .network_id = "8ce666e8-d34d-4fb1-b858-f15a7al28086", + .addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + .node_type = NM_NDISC_NODE_TYPE_HOST, + .max_addresses = max_addresses, + .router_solicitations = router_solicitations, + .router_solicitation_interval = router_solicitation_interval, + .ra_timeout = ra_timeout, + .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + }; + + ndisc = nm_lndp_ndisc_new(&config); if (!ndisc) { g_print("Failed to create NMNDisc instance: %s\n", error->message); g_error_free(error); @@ -75,7 +84,7 @@ main(int argc, char **argv) } iid.id_u8[7] = 1; - nm_ndisc_set_iid(ndisc, iid); + nm_ndisc_set_iid(ndisc, iid, FALSE); nm_ndisc_start(ndisc); g_main_loop_run(loop); |