diff options
| author | Iain Lane <iain@orangesquash.org.uk> | 2018-09-24 09:29:55 +0100 |
|---|---|---|
| committer | Iain Lane <iain@orangesquash.org.uk> | 2018-09-24 09:29:55 +0100 |
| commit | e152ec7bf4ba252ff9d3eb13eabd417b931dac9a (patch) | |
| tree | c323cf856ee0bb8e44590670dd54c19653a55748 /src/ndisc | |
| parent | ee9c73a923909e23a649407be77e25235d769e25 (diff) | |
Import Upstream version 1.12.2
Diffstat (limited to 'src/ndisc')
| -rw-r--r-- | src/ndisc/nm-lndp-ndisc.c | 52 | ||||
| -rw-r--r-- | src/ndisc/nm-ndisc.c | 71 | ||||
| -rw-r--r-- | src/ndisc/nm-ndisc.h | 38 | ||||
| -rw-r--r-- | src/ndisc/tests/meson.build | 23 |
4 files changed, 139 insertions, 45 deletions
diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c index 70200ed3..c0a0cd40 100644 --- a/src/ndisc/nm-lndp-ndisc.c +++ b/src/ndisc/nm-lndp-ndisc.c @@ -173,10 +173,10 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) */ { const NMNDiscGateway gateway = { - .address = gateway_addr, - .timestamp = now, - .lifetime = ndp_msgra_router_lifetime (msgra), - .preference = _route_preference_coerce (ndp_msgra_route_preference (msgra)), + .address = gateway_addr, + .timestamp = now, + .lifetime = ndp_msgra_router_lifetime (msgra), + .preference = _route_preference_coerce (ndp_msgra_route_preference (msgra)), }; if (nm_ndisc_add_gateway (ndisc, &gateway)) @@ -195,12 +195,16 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) continue; nm_utils_ip6_address_clear_host_address (&r_network, ndp_msg_opt_prefix (msg, offset), r_plen); + if ( IN6_IS_ADDR_UNSPECIFIED (&r_network) + || IN6_IS_ADDR_LINKLOCAL (&r_network)) + continue; + if (ndp_msg_opt_prefix_flag_on_link (msg, offset)) { - NMNDiscRoute route = { - .network = r_network, - .plen = r_plen, - .timestamp = now, - .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset), + const NMNDiscRoute route = { + .network = r_network, + .plen = r_plen, + .timestamp = now, + .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset), }; if (nm_ndisc_add_route (ndisc, &route)) @@ -211,10 +215,10 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) if ( r_plen == 64 && ndp_msg_opt_prefix_flag_auto_addr_conf (msg, offset)) { NMNDiscAddress address = { - .address = r_network, - .timestamp = now, - .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset), - .preferred = ndp_msg_opt_prefix_preferred_time (msg, offset), + .address = r_network, + .timestamp = now, + .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset), + .preferred = ndp_msg_opt_prefix_preferred_time (msg, offset), }; if (address.preferred > address.lifetime) @@ -225,11 +229,11 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) } ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_ROUTE) { NMNDiscRoute route = { - .gateway = gateway_addr, - .plen = ndp_msg_opt_route_prefix_len (msg, offset), - .timestamp = now, - .lifetime = ndp_msg_opt_route_lifetime (msg, offset), - .preference = _route_preference_coerce (ndp_msg_opt_route_preference (msg, offset)), + .gateway = gateway_addr, + .plen = ndp_msg_opt_route_prefix_len (msg, offset), + .timestamp = now, + .lifetime = ndp_msg_opt_route_lifetime (msg, offset), + .preference = _route_preference_coerce (ndp_msg_opt_route_preference (msg, offset)), }; if (route.plen == 0 || route.plen > 128) @@ -248,9 +252,9 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) { NMNDiscDNSServer dns_server = { - .address = *addr, - .timestamp = now, - .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset), + .address = *addr, + .timestamp = now, + .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset), }; /* Pad the lifetime somewhat to give a bit of slack in cases @@ -270,9 +274,9 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) { NMNDiscDNSDomain dns_domain = { - .domain = domain, - .timestamp = now, - .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset), + .domain = domain, + .timestamp = now, + .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset), }; /* Pad the lifetime somewhat to give a bit of slack in cases diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index 6b44a96c..04f86312 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -89,7 +89,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( ); enum { - CONFIG_CHANGED, + CONFIG_RECEIVED, RA_TIMEOUT, LAST_SIGNAL }; @@ -231,11 +231,11 @@ _data_complete (NMNDiscDataInternal *data) return &data->public; } -static void -_emit_config_change (NMNDisc *self, NMNDiscConfigMap changed) +void +nm_ndisc_emit_config_change (NMNDisc *self, NMNDiscConfigMap changed) { _config_changed_log (self, changed); - g_signal_emit (self, signals[CONFIG_CHANGED], 0, + g_signal_emit (self, signals[CONFIG_RECEIVED], 0, _data_complete (&NM_NDISC_GET_PRIVATE (self)->rdata), (guint) changed); } @@ -349,6 +349,11 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new) NMNDiscDataInternal *rdata = &priv->rdata; guint i; + nm_assert (new); + nm_assert (new->timestamp > 0 && new->timestamp < G_MAXINT32); + nm_assert (!IN6_IS_ADDR_UNSPECIFIED (&new->address)); + nm_assert (!IN6_IS_ADDR_LINKLOCAL (&new->address)); + for (i = 0; i < rdata->addresses->len; i++) { NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i); @@ -738,7 +743,7 @@ nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid) if (rdata->addresses->len) { _LOGD ("IPv6 interface identifier changed, flushing addresses"); g_array_remove_range (rdata->addresses, 0, rdata->addresses->len); - _emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES); + nm_ndisc_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES); solicit_routers (ndisc); } return TRUE; @@ -791,8 +796,8 @@ nm_ndisc_start (NMNDisc *ndisc) } } -void -nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address) +NMNDiscConfigMap +nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal) { NMNDiscDataInternal *rdata; guint i; @@ -814,8 +819,10 @@ nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address) i++; } - if (changed) - _emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES); + if (emit_changed_signal && changed) + nm_ndisc_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES); + + return changed ? NM_NDISC_CONFIG_ADDRESSES : NM_NDISC_CONFIG_NONE; } #define CONFIG_MAP_MAX_STR 7 @@ -887,6 +894,23 @@ get_expiry_time (guint32 timestamp, guint32 lifetime) : (_item->lifetime) / 2); \ }) +static const char * +_get_exp (char *buf, gsize buf_size, gint64 now_ns, gint32 expiry_time) +{ + int l; + + if (expiry_time == G_MAXINT32) + return "permanent"; + l = g_snprintf (buf, buf_size, + "%.4f", + ((double) ((expiry_time * NM_UTILS_NS_PER_SECOND) - now_ns)) / ((double) NM_UTILS_NS_PER_SECOND)); + nm_assert (l < buf_size); + return buf; +} + +#define get_exp(buf, now_ns, item) \ + _get_exp ((buf), G_N_ELEMENTS (buf), (now_ns), (get_expiry (item))) + static void _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed) { @@ -896,10 +920,14 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed) char changedstr[CONFIG_MAP_MAX_STR]; char addrstr[INET6_ADDRSTRLEN]; char str_pref[35]; + char str_exp[100]; + gint64 now_ns; if (!_LOGD_ENABLED ()) return; + now_ns = nm_utils_get_monotonic_timestamp_ns (); + priv = NM_NDISC_GET_PRIVATE (ndisc); rdata = &priv->rdata; @@ -910,35 +938,38 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed) NMNDiscGateway *gateway = &g_array_index (rdata->gateways, NMNDiscGateway, i); inet_ntop (AF_INET6, &gateway->address, addrstr, sizeof (addrstr)); - _LOGD (" gateway %s pref %s exp %d", addrstr, + _LOGD (" gateway %s pref %s exp %s", addrstr, nm_icmpv6_router_pref_to_string (gateway->preference, str_pref, sizeof (str_pref)), - get_expiry (gateway)); + get_exp (str_exp, now_ns, gateway)); } for (i = 0; i < rdata->addresses->len; i++) { - NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i); + const NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i); inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr)); - _LOGD (" address %s exp %d", addrstr, get_expiry (address)); + _LOGD (" address %s exp %s", addrstr, + get_exp (str_exp, now_ns, address)); } for (i = 0; i < rdata->routes->len; i++) { NMNDiscRoute *route = &g_array_index (rdata->routes, NMNDiscRoute, i); inet_ntop (AF_INET6, &route->network, addrstr, sizeof (addrstr)); - _LOGD (" route %s/%u via %s pref %s exp %d", addrstr, (guint) route->plen, + _LOGD (" route %s/%u via %s pref %s exp %s", addrstr, (guint) route->plen, nm_utils_inet6_ntop (&route->gateway, NULL), nm_icmpv6_router_pref_to_string (route->preference, str_pref, sizeof (str_pref)), - get_expiry (route)); + get_exp (str_exp, now_ns, route)); } for (i = 0; i < rdata->dns_servers->len; i++) { NMNDiscDNSServer *dns_server = &g_array_index (rdata->dns_servers, NMNDiscDNSServer, i); inet_ntop (AF_INET6, &dns_server->address, addrstr, sizeof (addrstr)); - _LOGD (" dns_server %s exp %d", addrstr, get_expiry (dns_server)); + _LOGD (" dns_server %s exp %s", addrstr, + get_exp (str_exp, now_ns, dns_server)); } for (i = 0; i < rdata->dns_domains->len; i++) { NMNDiscDNSDomain *dns_domain = &g_array_index (rdata->dns_domains, NMNDiscDNSDomain, i); - _LOGD (" dns_domain %s exp %d", dns_domain->domain, get_expiry (dns_domain)); + _LOGD (" dns_domain %s exp %s", dns_domain->domain, + get_exp (str_exp, now_ns, dns_domain)); } } @@ -979,7 +1010,7 @@ clean_addresses (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 * rdata = &NM_NDISC_GET_PRIVATE (ndisc)->rdata; for (i = 0; i < rdata->addresses->len; ) { - NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i); + const NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i); if (item->lifetime != NM_NDISC_INFINITY) { gint32 expiry = get_expiry (item); @@ -1102,7 +1133,7 @@ check_timestamps (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed) clean_dns_domains (ndisc, now, &changed, &nextevent); if (changed) - _emit_config_change (ndisc, changed); + nm_ndisc_emit_config_change (ndisc, changed); if (nextevent != G_MAXINT32) { if (nextevent <= now) @@ -1354,7 +1385,7 @@ nm_ndisc_class_init (NMNDiscClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - signals[CONFIG_CHANGED] = + signals[CONFIG_RECEIVED] = g_signal_new (NM_NDISC_CONFIG_RECEIVED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h index b66c2289..fdc5615f 100644 --- a/src/ndisc/nm-ndisc.h +++ b/src/ndisc/nm-ndisc.h @@ -27,6 +27,9 @@ #include "nm-setting-ip6-config.h" #include "NetworkManagerUtils.h" +#include "platform/nm-platform.h" +#include "platform/nmp-object.h" + #define NM_TYPE_NDISC (nm_ndisc_get_type ()) #define NM_NDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NDISC, NMNDisc)) #define NM_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NDISC, NMNDiscClass)) @@ -97,6 +100,7 @@ typedef struct { } NMNDiscDNSDomain; typedef enum { + NM_NDISC_CONFIG_NONE = 0, NM_NDISC_CONFIG_DHCP_LEVEL = 1 << 0, NM_NDISC_CONFIG_GATEWAYS = 1 << 1, NM_NDISC_CONFIG_ADDRESSES = 1 << 2, @@ -168,13 +172,17 @@ 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); NMNDiscNodeType nm_ndisc_get_node_type (NMNDisc *self); gboolean nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid); void nm_ndisc_start (NMNDisc *ndisc); -void nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address); +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, @@ -184,4 +192,32 @@ NMPlatform *nm_ndisc_get_platform (NMNDisc *self); NMPNetns *nm_ndisc_netns_get (NMNDisc *self); gboolean nm_ndisc_netns_push (NMNDisc *self, NMPNetns **netns); +static inline gboolean +nm_ndisc_dad_addr_is_fail_candidate_event (NMPlatformSignalChangeType change_type, + const NMPlatformIP6Address *addr) +{ + return !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TEMPORARY) + && ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED) + || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE)); +} + +static inline gboolean +nm_ndisc_dad_addr_is_fail_candidate (NMPlatform *platform, + const NMPObject *obj) +{ + const NMPlatformIP6Address *addr; + + addr = NMP_OBJECT_CAST_IP6_ADDRESS (nm_platform_lookup_obj (platform, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + obj)); + if ( addr + && ( NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TEMPORARY) + || !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_DADFAILED))) { + /* the address still/again exists and is not in DADFAILED state. Skip it. */ + return FALSE; + } + + return TRUE; +} + #endif /* __NETWORKMANAGER_NDISC_H__ */ diff --git a/src/ndisc/tests/meson.build b/src/ndisc/tests/meson.build new file mode 100644 index 00000000..2f479c2d --- /dev/null +++ b/src/ndisc/tests/meson.build @@ -0,0 +1,23 @@ +test_unit = 'test-ndisc-fake' + +exe = executable( + test_unit, + test_unit + '.c', + dependencies: test_nm_dep, + c_args: test_cflags_platform +) + +test( + 'ndisc/' + test_unit, + test_script, + args: test_args + [exe.full_path()] +) + +test = 'test-ndisc-linux' + +exe = executable( + test, + test + '.c', + dependencies: test_nm_dep, + c_args: test_cflags_platform +) |