diff options
Diffstat (limited to 'src/platform/nm-platform.c')
| -rw-r--r-- | src/platform/nm-platform.c | 644 |
1 files changed, 149 insertions, 495 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 84d862d2..c7ed90e3 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -353,45 +353,6 @@ nm_platform_process_events (NMPlatform *self) klass->process_events (self); } -const NMPlatformLink * -nm_platform_process_events_ensure_link (NMPlatform *self, - int ifindex, - const char *ifname) -{ - const NMPObject *obj; - gboolean refreshed = FALSE; - - g_return_val_if_fail (NM_IS_PLATFORM (self), NULL); - - if (ifindex <= 0 && !ifname) - return NULL; - - /* we look into the cache, whether a link for given ifindex/ifname - * exits. If not, we poll the netlink socket, maybe the event - * with the link is waiting. - * - * Then we try again to find the object. - * - * If the link is already cached the first time, we avoid polling - * the netlink socket. */ -again: - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self), - ifindex, - ifname, - FALSE, /* also invisible. We don't care here whether udev is ready */ - NM_LINK_TYPE_NONE, - NULL, NULL); - if (obj) - return NMP_OBJECT_CAST_LINK (obj); - if (!refreshed) { - refreshed = TRUE; - nm_platform_process_events (self); - goto again; - } - - return NULL; -} - /*****************************************************************************/ /** @@ -636,11 +597,11 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name) * further by moving children/slaves to the end. */ g_ptr_array_sort_with_data (links, _link_get_all_presort, GINT_TO_POINTER (sort_by_name)); - unseen = g_hash_table_new (nm_direct_hash, NULL); + unseen = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < links->len; i++) { item = NMP_OBJECT_CAST_LINK (links->pdata[i]); nm_assert (item->ifindex > 0); - if (!g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL)) + if (!nm_g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL)) nm_assert_not_reached (); } @@ -1157,21 +1118,6 @@ nm_platform_link_supports_slaves (NMPlatform *self, int ifindex) } /** - * nm_platform_refresh_all: - * @self: platform instance - * @obj_type: The object type to request. - * - * Resync and re-request all objects from kernel of a certain @obj_type. - */ -void -nm_platform_refresh_all (NMPlatform *self, NMPObjectType obj_type) -{ - _CHECK_SELF_VOID (self, klass); - - klass->refresh_all (self, obj_type); -} - -/** * nm_platform_link_refresh: * @self: platform instance * @ifindex: Interface index @@ -1379,26 +1325,30 @@ gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length) { const NMPlatformLink *pllink; + gconstpointer a = NULL; + guint8 l = 0; _CHECK_SELF (self, klass, NULL); + if (length) + *length = 0; + g_return_val_if_fail (ifindex > 0, NULL); pllink = nm_platform_link_get (self, ifindex); - - if ( !pllink - || pllink->addr.len <= 0) { - NM_SET_OUT (length, 0); - return NULL; - } - - if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX) { - NM_SET_OUT (length, 0); - g_return_val_if_reached (NULL); + if (pllink && pllink->addr.len > 0) { + if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX) { + if (length) + *length = 0; + g_return_val_if_reached (NULL); + } + a = pllink->addr.data; + l = pllink->addr.len; } - NM_SET_OUT (length, pllink->addr.len); - return pllink->addr.data; + if (length) + *length = l; + return a; } /** @@ -1894,12 +1844,6 @@ nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLin return _link_get_lnk (self, ifindex, NM_LINK_TYPE_SIT, out_link); } -const NMPlatformLnkTun * -nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_TUN, out_link); -} - const NMPlatformLnkVlan * nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -2046,43 +1990,33 @@ nm_platform_link_vxlan_add (NMPlatform *self, * @vnet_hdr: whether to set the IFF_VNET_HDR flag * @multi_queue: whether to set the IFF_MULTI_QUEUE flag * @out_link: on success, the link object - * @out_fd: (allow-none): if give, return the file descriptor for the - * created device. Note that when creating a non-persistent device, - * this argument is mandatory, otherwise it makes no sense - * to create such an interface. - * The caller is responsible for closing this file descriptor. * * Create a TUN or TAP interface. */ NMPlatformError nm_platform_link_tun_add (NMPlatform *self, const char *name, - const NMPlatformLnkTun *props, - const NMPlatformLink **out_link, - int *out_fd) + gboolean tap, + gint64 owner, + gint64 group, + gboolean pi, + gboolean vnet_hdr, + gboolean multi_queue, + const NMPlatformLink **out_link) { - char b[255]; NMPlatformError plerr; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (NM_IN_SET (props->type, IFF_TUN, IFF_TAP), NM_PLATFORM_ERROR_BUG); - - /* creating a non-persistant device requires that the caller handles - * the file descriptor. */ - g_return_val_if_fail (props->persist || out_fd, NM_PLATFORM_ERROR_BUG); - NM_SET_OUT (out_fd, -1); - - plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_TUN, out_link); + plerr = _link_add_check_existing (self, name, tap ? NM_LINK_TYPE_TAP : NM_LINK_TYPE_TUN, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("link: adding tun '%s' %s", - name, nm_platform_lnk_tun_to_string (props, b, sizeof (b))); - if (!klass->link_tun_add (self, name, props, out_link, out_fd)) + _LOGD ("link: adding %s '%s' owner %" G_GINT64_FORMAT " group %" G_GINT64_FORMAT, + tap ? "tap" : "tun", name, owner, group); + if (!klass->tun_add (self, name, tap, owner, group, pi, vnet_hdr, multi_queue, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; } @@ -2686,100 +2620,44 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe return TRUE; } -/** - * nm_platform_link_tun_get_properties: - * @self: the #NMPlatform instance - * @ifindex: the ifindex to look up - * @out_properties: (out): (allow-none): return the read properties - * - * Only recent versions of kernel export tun properties via netlink. - * So, if that's the case, then we have the NMPlatformLnkTun instance - * in the platform cache ready to return. Otherwise, this function - * falls back reading sysctl to obtain the tun properties. That - * is racy, because querying sysctl means that the object might - * be already removed from cache (while NM didn't yet process the - * netlink message). - * - * Hence, to lookup the tun properties, you always need to use this - * function, and use it with care knowing that it might obtain its - * data by reading sysctl. Note that we don't want to add this workaround - * to the platform cache itself, because the cache should (mainly) - * contain data from netlink. To access the sysctl side channel, the - * user needs to do explicitly. - * - * Returns: #TRUE, if the properties could be read. */ gboolean -nm_platform_link_tun_get_properties (NMPlatform *self, - int ifindex, - NMPlatformLnkTun *out_properties) +nm_platform_link_tun_get_properties (NMPlatform *self, int ifindex, NMPlatformTunProperties *props) { - const NMPObject *plobj; - const NMPObject *pllnk; + nm_auto_close int dirfd = -1; char ifname[IFNAMSIZ]; - gint64 owner; - gint64 group; gint64 flags; - + gboolean success = TRUE; _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (props, FALSE); - /* we consider also invisible links (those that are not yet in udev). */ - plobj = nm_platform_link_get_obj (self, ifindex, FALSE); - if (!plobj) - return FALSE; - if (NMP_OBJECT_CAST_LINK (plobj)->type != NM_LINK_TYPE_TUN) - return FALSE; - - pllnk = plobj->_link.netlink.lnk; - if (pllnk) { - nm_assert (NMP_OBJECT_GET_TYPE (pllnk) == NMP_OBJECT_TYPE_LNK_TUN); - nm_assert (NMP_OBJECT_GET_CLASS (pllnk)->lnk_link_type == NM_LINK_TYPE_TUN); + memset (props, 0, sizeof (*props)); + props->owner = -1; + props->group = -1; - /* recent kernels expose tun properties via netlink and thus we have them - * in the platform cache. */ - NM_SET_OUT (out_properties, pllnk->lnk_tun); - return TRUE; - } - - /* fallback to reading sysctl. */ - { - nm_auto_close int dirfd = -1; + dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname); + if (dirfd < 0) + return FALSE; - dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname); - if (dirfd < 0) - return FALSE; + props->owner = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "owner"), 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; - owner = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "owner"), 10, -1, G_MAXUINT32, -2); - if (owner == -2) - return FALSE; + props->group = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "group"), 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; - group = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "group"), 10, -1, G_MAXUINT32, -2); - if (group == -2) - return FALSE; - - flags = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "tun_flags"), 16, 0, G_MAXINT64, -1); - if (flags == -1) - return FALSE; - } + flags = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "tun_flags"), 16, 0, G_MAXINT64, -1); + if (flags >= 0) { + props->mode = ((flags & (IFF_TUN | IFF_TAP)) == IFF_TUN) ? "tun" : "tap"; + props->no_pi = !!(flags & IFF_NO_PI); + props->vnet_hdr = !!(flags & IFF_VNET_HDR); + props->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE); + } else + success = FALSE; - if (out_properties) { - memset (out_properties, 0, sizeof (*out_properties)); - if (owner != -1) { - out_properties->owner_valid = TRUE; - out_properties->owner = owner; - } - if (group != -1) { - out_properties->group_valid = TRUE; - out_properties->group = group; - } - out_properties->type = (flags & TUN_TYPE_MASK); - out_properties->pi = !(flags & IFF_NO_PI); - out_properties->vnet_hdr = !!(flags & IFF_VNET_HDR); - out_properties->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE); - out_properties->persist = !!(flags & IFF_PERSIST); - } - return TRUE; + return success; } gboolean @@ -3054,7 +2932,7 @@ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *ob * @user_data: user data for @predicate * * Returns the result of lookup in a GPtrArray. The result array contains - * references objects from the cache, its destroy function will unref them. + * references objects from the cache, it's destroy function will unref them. * * The user must unref the GPtrArray, which will also unref the NMPObject * elements. @@ -3233,68 +3111,24 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr } static gboolean -_addr_array_clean_expired (int addr_family, int ifindex, GPtrArray *array, guint32 now, GHashTable **idx) +array_contains_ip6_address (const GPtrArray *addresses, const NMPlatformIP6Address *address, gint32 now) { + guint len = addresses ? addresses->len : 0; guint i; - gboolean any_addrs = FALSE; - - nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); - nm_assert (now > 0); - if (!array) - return FALSE; - - /* remove all addresses that are already expired. */ - for (i = 0; i < array->len; i++) { - const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS (array->pdata[i]); - -#if NM_MORE_ASSERTS > 10 - nm_assert (a); - nm_assert (a->ifindex == ifindex); - { - const NMPObject *o = NMP_OBJECT_UP_CAST (a); - guint j; - - nm_assert (NMP_OBJECT_GET_CLASS (o)->addr_family == addr_family); - for (j = i + 1; j < array->len; j++) { - const NMPObject *o2 = array->pdata[j]; - - nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_GET_TYPE (o2)); - nm_assert (!nmp_object_id_equal (o, o2)); - } - } -#endif - - if ( addr_family == AF_INET6 - && NM_FLAGS_HAS (a->n_ifa_flags, IFA_F_TEMPORARY)) { - /* temporary addresses are never added explicitly by NetworkManager but - * kernel adds them via mngtempaddr flag. - * - * We drop them from this list. */ - goto clear_and_next; - } + for (i = 0; i < len; i++) { + NMPlatformIP6Address *candidate = NMP_OBJECT_CAST_IP6_ADDRESS (addresses->pdata[i]); - if (!nm_utils_lifetime_get (a->timestamp, a->lifetime, a->preferred, - now, NULL)) - goto clear_and_next; + if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) { + guint32 lifetime, preferred; - if (idx) { - if (G_UNLIKELY (!*idx)) { - *idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - } - if (!g_hash_table_add (*idx, (gpointer) NMP_OBJECT_UP_CAST (a))) - nm_assert_not_reached (); + if (nm_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, + now, &lifetime, &preferred)) + return TRUE; } - any_addrs = TRUE; - continue; - -clear_and_next: - nmp_object_unref (g_steal_pointer (&array->pdata[i])); } - return any_addrs; + return FALSE; } static gboolean @@ -3345,7 +3179,7 @@ ip4_addr_subnets_build_index (const GPtrArray *addresses, nm_assert (addresses && addresses->len); - subnets = g_hash_table_new (nm_direct_hash, NULL); + subnets = g_hash_table_new (NULL, NULL); /* Build a hash table of all addresses per subnet */ for (i = 0; i < addresses->len; i++) { @@ -3478,8 +3312,39 @@ nm_platform_ip4_address_sync (NMPlatform *self, _CHECK_SELF (self, klass, FALSE); - if (!_addr_array_clean_expired (AF_INET, ifindex, known_addresses, now, &known_addresses_idx)) - known_addresses = NULL; + if (known_addresses) { + /* remove all addresses that are already expired. */ + for (i = 0; i < known_addresses->len; i++) { + const NMPObject *o; + + o = known_addresses->pdata[i]; + nm_assert (o); + + known_address = NMP_OBJECT_CAST_IP4_ADDRESS (known_addresses->pdata[i]); + + if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, + now, &lifetime, &preferred)) + goto delete_and_next; + + if (G_UNLIKELY (!known_addresses_idx)) { + known_addresses_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, + (GEqualFunc) nmp_object_id_equal); + } + if (!nm_g_hash_table_insert (known_addresses_idx, (gpointer) o, (gpointer) o)) { + /* duplicate? Keep only the first instance. */ + goto delete_and_next; + } + + continue; +delete_and_next: + nmp_object_unref (o); + known_addresses->pdata[i] = NULL; + } + + if ( !known_addresses_idx + || g_hash_table_size (known_addresses_idx) == 0) + known_addresses = NULL; + } plat_addresses = nm_platform_lookup_clone (self, nmp_lookup_init_object (&lookup, @@ -3576,9 +3441,8 @@ nm_platform_ip4_address_sync (NMPlatform *self, known_address = NMP_OBJECT_CAST_IP4_ADDRESS (o); - lifetime = nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, &preferred); - if (!lifetime) + if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, + now, &lifetime, &preferred)) goto delete_and_next2; if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, @@ -3600,15 +3464,9 @@ delete_and_next2: * nm_platform_ip6_address_sync: * @self: platform instance * @ifindex: Interface index - * @known_addresses: List of addresses. The list will be modified and only - * addresses that were successfully added will be kept in the list. - * That means, expired addresses and addresses that could not be added - * will be dropped. - * Hence, the input argument @known_addresses is also an output argument - * telling which addresses were succesfully added. - * Addresses are removed by unrefing the instance via nmp_object_unref() - * and leaving a NULL tombstone. - * @full_sync: Also remove link-local and temporary addresses. + * @known_addresses: List of IPv6 addresses, as NMPObject. The list + * is not modified. + * @keep_link_local: Don't remove link-local address * * A convenience function to synchronize addresses for a specific interface * with the least possible disturbance. It simply removes addresses that are @@ -3619,117 +3477,32 @@ delete_and_next2: gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, - GPtrArray *known_addresses, - gboolean full_sync) + const GPtrArray *known_addresses, + gboolean keep_link_local) { gs_unref_ptrarray GPtrArray *plat_addresses = NULL; + NMPlatformIP6Address *address; gint32 now = nm_utils_get_monotonic_timestamp_s (); - guint i_plat, i_know; - gs_unref_hashtable GHashTable *known_addresses_idx = NULL; + guint i; NMPLookup lookup; guint32 ifa_flags; - if (!_addr_array_clean_expired (AF_INET6, ifindex, known_addresses, now, &known_addresses_idx)) - known_addresses = NULL; - - /* @plat_addresses is in decreasing priority order (highest priority addresses first), contrary to - * @known_addresses which is in increasing priority order (lowest priority addresses first). */ + /* Delete unknown addresses */ plat_addresses = nm_platform_lookup_clone (self, nmp_lookup_init_object (&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex), NULL, NULL); - if (plat_addresses) { - guint known_addresses_len; - - known_addresses_len = known_addresses ? known_addresses->len : 0; - - /* First, compare every address whether it is still a "known address", that is, whether - * to keep it or to delete it. - * - * If we don't find a matching valid address in @known_addresses, we will delete - * plat_addr. - * - * Certain addresses, like temporary addresses, are ignored by this function - * if not run with full_sync. These addresses are usually not managed by NetworkManager - * directly, or at least, they are not managed via nm_platform_ip6_address_sync(). - * Only in full_sync mode, we really want to get rid of them (usually, when we take - * the interface down). - * - * Note that we mark handled addresses by setting it to %NULL in @plat_addresses array. */ - for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) { - const NMPObject *plat_obj = plat_addresses->pdata[i_plat]; - const NMPObject *know_obj; - const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS (plat_obj); - - if (NM_FLAGS_HAS (plat_addr->n_ifa_flags, IFA_F_TEMPORARY)) { - if (!full_sync) { - /* just mark as handled, without actually deleting the address. */ - goto clear_and_next; - } - } else if (known_addresses_idx) { - know_obj = g_hash_table_lookup (known_addresses_idx, plat_obj); - if ( know_obj - && plat_addr->plen == NMP_OBJECT_CAST_IP6_ADDRESS (know_obj)->plen) { - /* technically, plen is not part of the ID for IPv6 addresses and thus - * @plat_addr is essentially the same address as @know_addr (regrading - * its identity, not its other attributes). - * However, we cannot modify an existing addresses' plen without - * removing and readding it. Thus, only keep plat_addr, if the plen - * matches. - * - * keep this one, and continue */ - continue; - } - } - - nm_platform_ip6_address_delete (self, ifindex, plat_addr->address, plat_addr->plen); -clear_and_next: - nmp_object_unref (g_steal_pointer (&plat_addresses->pdata[i_plat])); - } + for (i = 0; i < plat_addresses->len; i++) { + address = NMP_OBJECT_CAST_IP6_ADDRESS (plat_addresses->pdata[i]); - /* Next, we must preserve the priority of the routes. That is, source address - * selection will choose addresses in the order as they are reported by kernel. - * Note that the order in @plat_addresses of the remaining matches is highest - * priority first. - * We need to compare this to the order in @known_addresses (which has lowest - * priority first). - * - * If we find a first discrepancy, we need to delete all remaining addresses - * from that point on, because below we must re-add all the addresses in the - * right order to get their priority right. */ - i_plat = plat_addresses->len; - i_know = 0; - while (i_plat > 0) { - const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS (plat_addresses->pdata[--i_plat]); - - if (!plat_addr) + /* Leave link local address management to the kernel */ + if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address)) continue; - for (; i_know < known_addresses_len; i_know++) { - const NMPlatformIP6Address *know_addr = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); - - if (!know_addr) - continue; - - if (IN6_ARE_ADDR_EQUAL (&plat_addr->address, &know_addr->address)) { - /* we have a match. Mark address as handled. */ - i_know++; - goto next_plat; - } - - /* all remainging addresses need to be removed as well, so that we can - * re-add them in the correct order. Signal that, by setting @i_know - * so that the next @i_plat iteration, we won't enter the loop and - * delete the address right away */ - i_know = known_addresses_len; - break; - } - - nm_platform_ip6_address_delete (self, ifindex, plat_addr->address, plat_addr->plen); -next_plat: - ; + if (!array_contains_ip6_address (known_addresses, address, now)) + nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen); } } @@ -3740,18 +3513,19 @@ next_plat: ? IFA_F_NOPREFIXROUTE : 0; - /* Add missing addresses. New addresses are added by kernel with top - * priority. - */ - for (i_know = 0; i_know < known_addresses->len; i_know++) { - const NMPlatformIP6Address *known_address = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); + /* Add missing addresses */ + for (i = 0; i < known_addresses->len; i++) { + const NMPlatformIP6Address *known_address = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i]); guint32 lifetime, preferred; - if (!known_address) + if (NM_FLAGS_HAS (known_address->n_ifa_flags, IFA_F_TEMPORARY)) { + /* Kernel manages these */ continue; + } - lifetime = nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, &preferred); + if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, + now, &lifetime, &preferred)) + continue; if (!nm_platform_ip6_address_add (self, ifindex, known_address->address, known_address->plen, known_address->peer_address, @@ -3779,7 +3553,7 @@ nm_platform_ip_address_flush (NMPlatform *self, if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) success &= nm_platform_ip4_address_sync (self, ifindex, NULL); if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) - success &= nm_platform_ip6_address_sync (self, ifindex, NULL, TRUE); + success &= nm_platform_ip6_address_sync (self, ifindex, NULL, FALSE); return success; } @@ -3918,8 +3692,7 @@ nm_platform_ip_route_sync (NMPlatform *self, for (i_type = 0; routes && i_type < 2; i_type++) { for (i = 0; i < routes->len; i++) { - NMPlatformError plerr, plerr2; - gboolean gateway_route_added = FALSE; + NMPlatformError plerr; conf_o = routes->pdata[i]; @@ -3939,7 +3712,7 @@ nm_platform_ip_route_sync (NMPlatform *self, routes_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); } - if (!g_hash_table_insert (routes_idx, (gpointer) conf_o, (gpointer) conf_o)) { + if (!nm_g_hash_table_insert (routes_idx, (gpointer) conf_o, (gpointer) conf_o)) { _LOGD ("route-sync: skip adding duplicate route %s", nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1))); continue; @@ -3965,7 +3738,6 @@ nm_platform_ip_route_sync (NMPlatform *self, } } -sync_route_add: plerr = nm_platform_ip_route_add (self, NMP_NLM_FLAG_APPEND | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, @@ -3990,11 +3762,6 @@ sync_route_add: nmp_object_to_string (plat_entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf2, sizeof (sbuf2))); } } - } else if (NMP_OBJECT_CAST_IP_ROUTE (conf_o)->rt_source < NM_IP_CONFIG_SOURCE_USER) { - _LOGD ("route-sync: ignore failure to add IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); } else if ( -((int) plerr) == EINVAL && out_temporary_not_available && _err_inval_due_to_ipv6_tentative_pref_src (self, conf_o)) { @@ -4004,66 +3771,25 @@ sync_route_add: if (!*out_temporary_not_available) *out_temporary_not_available = g_ptr_array_new_full (0, (GDestroyNotify) nmp_object_unref); g_ptr_array_add (*out_temporary_not_available, (gpointer) nmp_object_ref (conf_o)); - } else if ( !gateway_route_added - && ( ( -((int) plerr) == ENETUNREACH - && vt->is_ip4 - && !!NMP_OBJECT_CAST_IP4_ROUTE (conf_o)->gateway) - || ( -((int) plerr) == EHOSTUNREACH - && !vt->is_ip4 - && !IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->gateway)))) { - NMPObject oo; - - if (vt->is_ip4) { - const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (conf_o); - - nmp_object_stackinit (&oo, - NMP_OBJECT_TYPE_IP4_ROUTE, - &((NMPlatformIP4Route) { - .network = r->gateway, - .plen = 32, - .metric = r->metric, - .rt_source = r->rt_source, - .table_coerced = r->table_coerced, - })); - } else { - const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (conf_o); - - nmp_object_stackinit (&oo, - NMP_OBJECT_TYPE_IP6_ROUTE, - &((NMPlatformIP6Route) { - .network = r->gateway, - .plen = 128, - .metric = r->metric, - .rt_source = r->rt_source, - .table_coerced = r->table_coerced, - })); - } - - _LOGD ("route-sync: failure to add IPv%c route: %s: %s; try adding direct route to gateway %s", + } else if (NMP_OBJECT_CAST_IP_ROUTE (conf_o)->rt_source < NM_IP_CONFIG_SOURCE_USER) { + _LOGD ("route-sync: ignore failure to add IPv%c route: %s: %s", vt->is_ip4 ? '4' : '6', nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err)), - nmp_object_to_string (&oo, NMP_OBJECT_TO_STRING_PUBLIC, sbuf2, sizeof (sbuf2))); - - plerr2 = nm_platform_ip_route_add (self, - NMP_NLM_FLAG_APPEND - | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, - &oo); - - if (plerr2 != NM_PLATFORM_ERROR_SUCCESS) { - _LOGD ("route-sync: failure to add gateway IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); - } - - gateway_route_added = TRUE; - goto sync_route_add; + nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); } else { - _LOGW ("route-sync: failure to add IPv%c route: %s: %s", + const char *reason = ""; + + if ( -((int) plerr) == ENETUNREACH + && ( vt->is_ip4 + ? !!NMP_OBJECT_CAST_IP4_ROUTE (conf_o)->gateway + : !IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->gateway))) + reason = "; is the gateway directly reachable?"; + + _LOGW ("route-sync: failure to add IPv%c route: %s: %s%s", vt->is_ip4 ? '4' : '6', nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err))); + nm_platform_error_to_string (plerr, sbuf_err, sizeof (sbuf_err)), + reason); success = FALSE; } } @@ -4987,7 +4713,6 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi "%s" /* encap limit */ "%s" /* flow label */ "%s" /* proto */ - " flags 0x%x" "", nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet6_ntop (&lnk->remote, str_remote1)), nm_sprintf_buf (str_local, " local %s", nm_utils_inet6_ntop (&lnk->local, str_local1)), @@ -4996,8 +4721,7 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass), nm_sprintf_buf (str_encap, " encap-limit %u", lnk->encap_limit), nm_sprintf_buf (str_flow, " flow-label 0x05%x", lnk->flow_label), - nm_sprintf_buf (str_proto, " proto %u", lnk->proto), - (guint) lnk->flags); + nm_sprintf_buf (str_proto, " proto %u", lnk->proto)); return buf; } @@ -5118,43 +4842,6 @@ nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len } const char * -nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len) -{ - char str_owner[50]; - char str_group[50]; - char str_type[50]; - const char *type; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - if (lnk->type == IFF_TUN) - type = "tun"; - else if (lnk->type == IFF_TAP) - type = "tap"; - else - type = nm_sprintf_buf (str_type, "tun type %u", (guint) lnk->type); - - g_snprintf (buf, len, - "%s" /* type */ - "%s" /* pi */ - "%s" /* vnet_hdr */ - "%s" /* multi_queue */ - "%s" /* persist */ - "%s" /* owner */ - "%s" /* group */ - "", - type, - lnk->pi ? " pi" : "", - lnk->vnet_hdr ? " vnet_hdr" : "", - lnk->multi_queue ? " multi_queue" : "", - lnk->persist ? " persist" : "", - lnk->owner_valid ? nm_sprintf_buf (str_owner, " owner %u", (guint) lnk->owner) : "", - lnk->group_valid ? nm_sprintf_buf (str_group, " group %u", (guint) lnk->group) : ""); - return buf; -} - -const char * nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len) { char *b; @@ -5356,10 +5043,10 @@ NM_UTILS_FLAGS2STR_DEFINE (nm_platform_addr_flags2str, unsigned, NM_UTILS_FLAGS2STR (IFA_F_OPTIMISTIC, "optimistic"), NM_UTILS_FLAGS2STR (IFA_F_HOMEADDRESS, "homeaddress"), NM_UTILS_FLAGS2STR (IFA_F_DEPRECATED, "deprecated"), + NM_UTILS_FLAGS2STR (IFA_F_TENTATIVE, "tentative"), NM_UTILS_FLAGS2STR (IFA_F_PERMANENT, "permanent"), NM_UTILS_FLAGS2STR (IFA_F_MANAGETEMPADDR, "mngtmpaddr"), NM_UTILS_FLAGS2STR (IFA_F_NOPREFIXROUTE, "noprefixroute"), - NM_UTILS_FLAGS2STR (IFA_F_TENTATIVE, "tentative"), ); NM_UTILS_ENUM2STR_DEFINE (nm_platform_route_scope2str, int, @@ -5850,8 +5537,7 @@ nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState obj->tclass, obj->encap_limit, obj->proto, - obj->flow_label, - obj->flags); + obj->flow_label); } int @@ -5866,7 +5552,6 @@ nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6 NM_CMP_FIELD (a, b, encap_limit); NM_CMP_FIELD (a, b, flow_label); NM_CMP_FIELD (a, b, proto); - NM_CMP_FIELD (a, b, flags); return 0; } @@ -5985,38 +5670,6 @@ nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) } void -nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->type, - obj->owner, - obj->group, - NM_HASH_COMBINE_BOOLS (guint8, - obj->owner_valid, - obj->group_valid, - obj->pi, - obj->vnet_hdr, - obj->multi_queue, - obj->persist)); -} - -int -nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, type); - NM_CMP_FIELD (a, b, owner); - NM_CMP_FIELD (a, b, group); - NM_CMP_FIELD_BOOL (a, b, owner_valid); - NM_CMP_FIELD_BOOL (a, b, group_valid); - NM_CMP_FIELD_BOOL (a, b, pi); - NM_CMP_FIELD_BOOL (a, b, vnet_hdr); - NM_CMP_FIELD_BOOL (a, b, multi_queue); - NM_CMP_FIELD_BOOL (a, b, persist); - return 0; -} - -void nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h) { nm_hash_update_vals (h, @@ -6607,13 +6260,14 @@ nm_platform_cache_update_emit_signal (NMPlatform *self, const NMPObject *o; const NMPClass *klass; - nm_assert (NM_IN_SET ((NMPlatformSignalChangeType) cache_op, NM_PLATFORM_SIGNAL_NONE, - NM_PLATFORM_SIGNAL_ADDED, - NM_PLATFORM_SIGNAL_CHANGED, - NM_PLATFORM_SIGNAL_REMOVED)); + nm_assert (NM_IN_SET ((NMPlatformSignalChangeType) cache_op, (NMPlatformSignalChangeType) NMP_CACHE_OPS_UNCHANGED, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_SIGNAL_REMOVED)); ASSERT_nmp_cache_ops (nm_platform_get_cache (self), cache_op, obj_old, obj_new); + nm_assert (NM_IN_SET (nm_platform_netns_get (self), + NULL, + nmp_netns_get_current ())); + NMTST_ASSERT_PLATFORM_NETNS_CURRENT (self); switch (cache_op) { |