diff options
Diffstat (limited to 'src/libnm-platform/nm-linux-platform.c')
| -rw-r--r-- | src/libnm-platform/nm-linux-platform.c | 895 |
1 files changed, 496 insertions, 399 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 78df53e7..93935b98 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -402,11 +402,11 @@ typedef struct { guint32 seq_number; WaitForNlResponseResult seq_result; DelayedActionWaitForNlResponseType response_type; - gint64 timeout_abs_ns; - WaitForNlResponseResult * out_seq_result; - char ** out_errmsg; + gint64 timeout_abs_nsec; + WaitForNlResponseResult *out_seq_result; + char **out_errmsg; union { - int * out_refresh_all_in_progress; + int *out_refresh_all_in_progress; NMPObject **out_route_get; gpointer out_data; } response; @@ -446,11 +446,22 @@ typedef struct { GPtrArray *list_master_connected; GPtrArray *list_refresh_link; - GArray * list_wait_for_nl_response; + GArray *list_wait_for_nl_response; int is_handling; } delayed_action; + /* This is the receive buffer for netlink messages. This buffer should be large + * enough for any rtnetlink message. When too small, nl_recv() would notice the + * truncation and lose the message. In that case, we reallocate a larger buffer. + * + * We keep the receive buffer around for the entire lifetime of the platform instance. + * Usually we only have one platform instance per netns, so we don't waste too much. */ + struct { + unsigned char *buf; + gsize len; + } netlink_recv_buf; + } NMLinuxPlatformPrivate; struct _NMLinuxPlatform { @@ -493,7 +504,7 @@ NM_LINUX_PLATFORM_FROM_PRIVATE(NMLinuxPlatformPrivate *priv) G_STMT_START \ { \ char __prefix[32]; \ - const char * __p_prefix = _NMLOG_PREFIX_NAME; \ + const char *__p_prefix = _NMLOG_PREFIX_NAME; \ NMPlatform *const __self = (self); \ \ if (__self && nm_platform_get_log_with_ptr(__self)) { \ @@ -554,7 +565,7 @@ delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpo static gboolean delayed_action_handle_all(NMPlatform *platform, gboolean read_netlink); static void do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name); static void do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action_type); -static void cache_on_change(NMPlatform * platform, +static void cache_on_change(NMPlatform *platform, NMPCacheOpsType cache_op, const NMPObject *obj_old, const NMPObject *obj_new); @@ -576,8 +587,8 @@ wait_for_nl_response_to_nmerr(WaitForNlResponseResult seq_result) static const char * wait_for_nl_response_to_string(WaitForNlResponseResult seq_result, - const char * errmsg, - char * buf, + const char *errmsg, + char *buf, gsize buf_size) { char *buf0 = buf; @@ -993,9 +1004,9 @@ _addrtime_get_lifetimes(guint32 timestamp, /*****************************************************************************/ static const NMPObject * -_lookup_cached_link(const NMPCache * cache, +_lookup_cached_link(const NMPCache *cache, int ifindex, - gboolean * completed_from_cache, + gboolean *completed_from_cache, const NMPObject **link_cached) { const NMPObject *obj; @@ -1019,7 +1030,7 @@ static char * _linktype_read_devtype(int dirfd) { gs_free char *contents = NULL; - char * cont, *end; + char *cont, *end; nm_assert(dirfd >= 0); @@ -1046,16 +1057,16 @@ _linktype_read_devtype(int dirfd) } static NMLinkType -_linktype_get_type(NMPlatform * platform, - const NMPCache * cache, - const char * kind, +_linktype_get_type(NMPlatform *platform, + const NMPCache *cache, + const char *kind, int ifindex, - const char * ifname, + const char *ifname, unsigned flags, unsigned arptype, - gboolean * completed_from_cache, + gboolean *completed_from_cache, const NMPObject **link_cached, - const char ** out_kind) + const char **out_kind) { NMLinkType link_type; @@ -1138,7 +1149,7 @@ _linktype_get_type(NMPlatform * platform, { nm_auto_close int dirfd = -1; - gs_free char * devtype = NULL; + gs_free char *devtype = NULL; char ifname_verified[IFNAMSIZ]; dirfd = nmp_utils_sysctl_open_netdir(ifindex, ifname, ifname_verified); @@ -1242,12 +1253,12 @@ _nl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int al /* Copied and heavily modified from libnl3's inet6_parse_protinfo(). */ static gboolean -_parse_af_inet6(NMPlatform * platform, - struct nlattr * attr, +_parse_af_inet6(NMPlatform *platform, + struct nlattr *attr, NMUtilsIPv6IfaceId *out_token, - gboolean * out_token_valid, - guint8 * out_addr_gen_mode_inv, - gboolean * out_addr_gen_mode_valid) + gboolean *out_token_valid, + guint8 *out_addr_gen_mode_inv, + gboolean *out_addr_gen_mode_valid) { static const struct nla_policy policy[] = { [IFLA_INET6_FLAGS] = {.type = NLA_U32}, @@ -1258,7 +1269,7 @@ _parse_af_inet6(NMPlatform * platform, [IFLA_INET6_TOKEN] = {.minlen = sizeof(struct in6_addr)}, [IFLA_INET6_ADDR_GEN_MODE] = {.type = NLA_U8}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; struct in6_addr i6_token; gboolean token_valid = FALSE; gboolean addr_gen_mode_valid = FALSE; @@ -1331,8 +1342,8 @@ _parse_lnk_bridge(const char *kind, struct nlattr *info_data) [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = {.type = NLA_U64}, }; NMPlatformLnkBridge *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; if (!info_data || !nm_streq0(kind, "bridge")) return NULL; @@ -1420,8 +1431,8 @@ _parse_lnk_gre(const char *kind, struct nlattr *info_data) [IFLA_GRE_TOS] = {.type = NLA_U8}, [IFLA_GRE_PMTUDISC] = {.type = NLA_U8}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkGre *props; gboolean is_tap; @@ -1480,10 +1491,10 @@ _parse_lnk_infiniband(const char *kind, struct nlattr *info_data) [IFLA_IPOIB_MODE] = {.type = NLA_U16}, [IFLA_IPOIB_UMCAST] = {.type = NLA_U16}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; NMPlatformLnkInfiniband *info; - NMPObject * obj; - const char * mode; + NMPObject *obj; + const char *mode; if (!info_data || !nm_streq0(kind, "ipoib")) return NULL; @@ -1529,8 +1540,8 @@ _parse_lnk_ip6tnl(const char *kind, struct nlattr *info_data) [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, [IFLA_IPTUN_FLAGS] = {.type = NLA_U32}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkIp6Tnl *props; guint32 flowinfo; @@ -1582,8 +1593,8 @@ _parse_lnk_ip6gre(const char *kind, struct nlattr *info_data) [IFLA_GRE_FLOWINFO] = {.type = NLA_U32}, [IFLA_GRE_FLAGS] = {.type = NLA_U32}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkIp6Tnl *props; guint32 flowinfo; gboolean is_tap; @@ -1648,8 +1659,8 @@ _parse_lnk_ipip(const char *kind, struct nlattr *info_data) [IFLA_IPTUN_TOS] = {.type = NLA_U8}, [IFLA_IPTUN_PMTUDISC] = {.type = NLA_U8}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkIpIp *props; if (!info_data || !nm_streq0(kind, "ipip")) @@ -1681,8 +1692,8 @@ _parse_lnk_macvlan(const char *kind, struct nlattr *info_data) [IFLA_MACVLAN_FLAGS] = {.type = NLA_U16}, }; NMPlatformLnkMacvlan *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; gboolean tap; if (!info_data || !kind) @@ -1732,8 +1743,8 @@ _parse_lnk_macsec(const char *kind, struct nlattr *info_data) [IFLA_MACSEC_REPLAY_PROTECT] = {.type = NLA_U8}, [IFLA_MACSEC_VALIDATION] = {.type = NLA_U8}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkMacsec *props; if (!info_data || !nm_streq0(kind, "macsec")) @@ -1800,8 +1811,8 @@ _parse_lnk_sit(const char *kind, struct nlattr *info_data) [IFLA_IPTUN_FLAGS] = {.type = NLA_U16}, [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkSit *props; if (!info_data || !nm_streq0(kind, "sit")) @@ -1841,8 +1852,8 @@ _parse_lnk_tun(const char *kind, struct nlattr *info_data) [IFLA_TUN_NUM_QUEUES] = {.type = NLA_U32}, [IFLA_TUN_NUM_DISABLED_QUEUES] = {.type = NLA_U32}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; NMPlatformLnkTun *props; if (!info_data || !nm_streq0(kind, "tun")) @@ -1878,12 +1889,12 @@ _parse_lnk_tun(const char *kind, struct nlattr *info_data) /*****************************************************************************/ static gboolean -_vlan_qos_mapping_from_nla(struct nlattr * nlattr, +_vlan_qos_mapping_from_nla(struct nlattr *nlattr, const NMVlanQosMapping **out_map, - guint * out_n_map) + guint *out_n_map) { - struct nlattr * nla; - int remaining; + struct nlattr *nla; + int remaining; gs_unref_ptrarray GPtrArray *array = NULL; G_STATIC_ASSERT(sizeof(NMVlanQosMapping) == sizeof(struct ifla_vlan_qos_mapping)); @@ -1950,9 +1961,9 @@ _parse_lnk_vlan(const char *kind, struct nlattr *info_data) [IFLA_VLAN_EGRESS_QOS] = {.type = NLA_NESTED}, [IFLA_VLAN_PROTOCOL] = {.type = NLA_U16}, }; - struct nlattr *tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; nm_auto_nmpobj NMPObject *obj = NULL; - NMPObject * obj_result; + NMPObject *obj_result; if (!info_data || !nm_streq0(kind, "vlan")) return NULL; @@ -2050,8 +2061,8 @@ _parse_lnk_vxlan(const char *kind, struct nlattr *info_data) [IFLA_VXLAN_PORT] = {.type = NLA_U16}, }; NMPlatformLnkVxlan *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; if (!info_data || !nm_streq0(kind, "vxlan")) return NULL; @@ -2117,8 +2128,8 @@ _parse_lnk_vrf(const char *kind, struct nlattr *info_data) [IFLA_VRF_TABLE] = {.type = NLA_U32}, }; NMPlatformLnkVrf *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; if (!info_data || !nm_streq0(kind, "vrf")) return NULL; @@ -2199,7 +2210,7 @@ _wireguard_update_from_peers_nla(CList *peers, GArray **p_allowed_ips, struct nl [WGPEER_A_TX_BYTES] = {.type = NLA_U64}, [WGPEER_A_ALLOWEDIPS] = {.type = NLA_NESTED}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; WireGuardPeerConstruct *peer_c; if (nla_parse_nested_arr(tb, peer_attr, policy) < 0) @@ -2259,7 +2270,7 @@ _wireguard_update_from_peers_nla(CList *peers, GArray **p_allowed_ips, struct nl if (tb[WGPEER_A_ALLOWEDIPS]) { struct nlattr *attr; int rem; - GArray * allowed_ips = *p_allowed_ips; + GArray *allowed_ips = *p_allowed_ips; nla_for_each_nested (attr, tb[WGPEER_A_ALLOWEDIPS], rem) { if (!allowed_ips) { @@ -2290,7 +2301,7 @@ typedef struct { const int ifindex; NMPObject *obj; CList peers; - GArray * allowed_ips; + GArray *allowed_ips; } WireGuardParseData; static int @@ -2306,7 +2317,7 @@ _wireguard_get_device_cb(struct nl_msg *msg, void *arg) [WGDEVICE_A_FWMARK] = {.type = NLA_U32}, [WGDEVICE_A_PEERS] = {.type = NLA_NESTED}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; WireGuardParseData *parse_data = arg; if (genlmsg_parse_arr(nlmsg_hdr(msg), 0, tb, policy) < 0) @@ -2327,7 +2338,7 @@ _wireguard_get_device_cb(struct nl_msg *msg, void *arg) /* we already have an object instance. This means the netlink message * is a continuation, only providing more WGDEVICE_A_PEERS data below. */ } else { - NMPObject * obj; + NMPObject *obj; NMPlatformLnkWireGuard *props; obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL); @@ -2370,18 +2381,18 @@ _wireguard_get_device_cb(struct nl_msg *msg, void *arg) } static const NMPObject * -_wireguard_read_info(NMPlatform * platform /* used only as logging context */, +_wireguard_read_info(NMPlatform *platform /* used only as logging context */, struct nl_sock *genl, int wireguard_family_id, int ifindex) { nm_auto_nlmsg struct nl_msg *msg = NULL; - NMPObject * obj = NULL; - WireGuardPeerConstruct * peer_c; - WireGuardPeerConstruct * peer_c_safe; - gs_unref_array GArray *allowed_ips = NULL; - WireGuardParseData parse_data = { - .ifindex = ifindex, + NMPObject *obj = NULL; + WireGuardPeerConstruct *peer_c; + WireGuardPeerConstruct *peer_c_safe; + gs_unref_array GArray *allowed_ips = NULL; + WireGuardParseData parse_data = { + .ifindex = ifindex, }; guint i; @@ -2522,13 +2533,13 @@ _wireguard_get_family_id(NMPlatform *platform, int ifindex_try) static const NMPObject * _wireguard_refresh_link(NMPlatform *platform, int wireguard_family_id, int ifindex) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); nm_auto_nmpobj const NMPObject *obj_old = NULL; nm_auto_nmpobj const NMPObject *obj_new = NULL; nm_auto_nmpobj const NMPObject *lnk_new = NULL; NMPCacheOpsType cache_op; - const NMPObject * plink = NULL; - nm_auto_nmpobj NMPObject *obj = NULL; + const NMPObject *plink = NULL; + nm_auto_nmpobj NMPObject *obj = NULL; nm_assert(wireguard_family_id >= 0); nm_assert(ifindex > 0); @@ -2587,25 +2598,25 @@ _wireguard_refresh_link(NMPlatform *platform, int wireguard_family_id, int ifind } static int -_wireguard_create_change_nlmsgs(NMPlatform * platform, +_wireguard_create_change_nlmsgs(NMPlatform *platform, int ifindex, int wireguard_family_id, - const NMPlatformLnkWireGuard * lnk_wireguard, - const NMPWireGuardPeer * peers, + const NMPlatformLnkWireGuard *lnk_wireguard, + const NMPWireGuardPeer *peers, const NMPlatformWireGuardChangePeerFlags *peer_flags, guint peers_len, NMPlatformWireGuardChangeFlags change_flags, - GPtrArray ** out_msgs) + GPtrArray **out_msgs) { - gs_unref_ptrarray GPtrArray * msgs = NULL; - nm_auto_nlmsg struct nl_msg * msg = NULL; + gs_unref_ptrarray GPtrArray *msgs = NULL; + nm_auto_nlmsg struct nl_msg *msg = NULL; const guint IDX_NIL = G_MAXUINT; guint idx_peer_curr; guint idx_allowed_ips_curr; - struct nlattr * nest_peers; - struct nlattr * nest_curr_peer; - struct nlattr * nest_allowed_ips; - struct nlattr * nest_curr_allowed_ip; + struct nlattr *nest_peers; + struct nlattr *nest_curr_peer; + struct nlattr *nest_allowed_ips; + struct nlattr *nest_curr_allowed_ip; NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT; #define _nla_nest_end(msg, nest_start) \ @@ -2821,15 +2832,15 @@ nla_put_failure: } static int -link_wireguard_change(NMPlatform * platform, +link_wireguard_change(NMPlatform *platform, int ifindex, - const NMPlatformLnkWireGuard * lnk_wireguard, - const NMPWireGuardPeer * peers, + const NMPlatformLnkWireGuard *lnk_wireguard, + const NMPWireGuardPeer *peers, const NMPlatformWireGuardChangePeerFlags *peer_flags, guint peers_len, NMPlatformWireGuardChangeFlags change_flags) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); gs_unref_ptrarray GPtrArray *msgs = NULL; int wireguard_family_id; guint i; @@ -2897,8 +2908,8 @@ _nmp_link_address_set(NMPLinkAddress *dst, const struct nlattr *nla) /* Copied and heavily modified from libnl3's link_msg_parser(). */ static NMPObject * -_new_from_nl_link(NMPlatform * platform, - const NMPCache * cache, +_new_from_nl_link(NMPlatform *platform, + const NMPCache *cache, struct nlmsghdr *nlh, gboolean id_only) { @@ -2930,15 +2941,15 @@ _new_from_nl_link(NMPlatform * platform, [IFLA_LINK_NETNSID] = {}, [IFLA_PERM_ADDRESS] = {.type = NLA_UNSPEC}, }; - const struct ifinfomsg *ifi; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - struct nlattr * nl_info_data = NULL; - const char * nl_info_kind = NULL; + const struct ifinfomsg *ifi; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + struct nlattr *nl_info_data = NULL; + const char *nl_info_kind = NULL; nm_auto_nmpobj NMPObject *obj = NULL; gboolean completed_from_cache_val = FALSE; - gboolean * completed_from_cache = cache ? &completed_from_cache_val : NULL; - const NMPObject * link_cached = NULL; - const NMPObject * lnk_data = NULL; + gboolean *completed_from_cache = cache ? &completed_from_cache_val : NULL; + const NMPObject *link_cached = NULL; + const NMPObject *lnk_data = NULL; gboolean address_complete_from_cache = TRUE; gboolean perm_address_complete_from_cache = TRUE; gboolean broadcast_complete_from_cache = TRUE; @@ -3210,7 +3221,7 @@ _new_from_nl_link(NMPlatform * platform, if (obj->link.type == NM_LINK_TYPE_WIREGUARD) { const NMPObject *lnk_data_new = NULL; - struct nl_sock * genl = NM_LINUX_PLATFORM_GET_PRIVATE(platform)->genl; + struct nl_sock *genl = NM_LINUX_PLATFORM_GET_PRIVATE(platform)->genl; /* The WireGuard kernel module does not yet send link update * notifications, so we don't actually update the cache. For @@ -3255,9 +3266,9 @@ _new_from_nl_addr(struct nlmsghdr *nlh, gboolean id_only) [IFA_CACHEINFO] = {.minlen = nm_offsetofend(struct ifa_cacheinfo, tstamp)}, [IFA_FLAGS] = {}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - const struct ifaddrmsg *ifa; - gboolean is_v4; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + const struct ifaddrmsg *ifa; + gboolean IS_IPv4; nm_auto_nmpobj NMPObject *obj = NULL; int addr_len; guint32 lifetime, preferred, timestamp; @@ -3267,29 +3278,31 @@ _new_from_nl_addr(struct nlmsghdr *nlh, gboolean id_only) ifa = nlmsg_data(nlh); - if (!NM_IN_SET(ifa->ifa_family, AF_INET, AF_INET6)) + if (ifa->ifa_family == AF_INET) + IS_IPv4 = TRUE; + else if (ifa->ifa_family == AF_INET6) + IS_IPv4 = FALSE; + else return NULL; - is_v4 = ifa->ifa_family == AF_INET; - if (nlmsg_parse_arr(nlh, sizeof(*ifa), tb, policy) < 0) return NULL; - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + addr_len = IS_IPv4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); - if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128)) + if (ifa->ifa_prefixlen > (IS_IPv4 ? 32 : 128)) return NULL; /*****************************************************************/ - obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL); + obj = nmp_object_new(IS_IPv4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL); obj->ip_address.ifindex = ifa->ifa_index; obj->ip_address.plen = ifa->ifa_prefixlen; _check_addr_or_return_null(tb, IFA_ADDRESS, addr_len); _check_addr_or_return_null(tb, IFA_LOCAL, addr_len); - if (is_v4) { + if (IS_IPv4) { /* For IPv4, kernel omits IFA_LOCAL/IFA_ADDRESS if (and only if) they * are effectively 0.0.0.0 (all-zero). */ if (tb[IFA_LOCAL]) @@ -3325,7 +3338,7 @@ _new_from_nl_addr(struct nlmsghdr *nlh, gboolean id_only) obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifa->ifa_flags; - if (is_v4) { + if (IS_IPv4) { if (tb[IFA_LABEL]) { char label[IFNAMSIZ]; @@ -3374,9 +3387,9 @@ _new_from_nl_route(struct nlmsghdr *nlh, gboolean id_only) [RTA_METRICS] = {.type = NLA_NESTED}, [RTA_MULTIPATH] = {.type = NLA_NESTED}, }; - const struct rtmsg *rtm; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - gboolean is_v4; + const struct rtmsg *rtm; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + gboolean IS_IPv4; nm_auto_nmpobj NMPObject *obj = NULL; int addr_len; struct { @@ -3403,10 +3416,19 @@ _new_from_nl_route(struct nlmsghdr *nlh, gboolean id_only) * only handle ~supported~ routes. *****************************************************************/ - if (!NM_IN_SET(rtm->rtm_family, AF_INET, AF_INET6)) + if (rtm->rtm_family == AF_INET) + IS_IPv4 = TRUE; + else if (rtm->rtm_family == AF_INET6) + IS_IPv4 = FALSE; + else return NULL; - if (!NM_IN_SET(rtm->rtm_type, RTN_UNICAST, RTN_LOCAL)) + if (!NM_IN_SET(rtm->rtm_type, + RTN_UNICAST, + RTN_LOCAL, + RTN_BLACKHOLE, + RTN_UNREACHABLE, + RTN_PROHIBIT)) return NULL; if (nlmsg_parse_arr(nlh, sizeof(struct rtmsg), tb, policy) < 0) @@ -3414,10 +3436,9 @@ _new_from_nl_route(struct nlmsghdr *nlh, gboolean id_only) /*****************************************************************/ - is_v4 = rtm->rtm_family == AF_INET; - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + addr_len = IS_IPv4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); - if (rtm->rtm_dst_len > (is_v4 ? 32 : 128)) + if (rtm->rtm_dst_len > (IS_IPv4 ? 32 : 128)) return NULL; /***************************************************************** @@ -3481,16 +3502,45 @@ rta_multipath_done:; /* If no nexthops have been provided via RTA_MULTIPATH * we add it as regular nexthop to maintain backwards * compatibility */ - nh.ifindex = ifindex; - nh.gateway = gateway; + nh.ifindex = ifindex; + nh.gateway = gateway; + nh.is_present = TRUE; } else { /* Kernel supports new style nexthop configuration, * verify that it is a duplicate and ignore old-style nexthop. */ if (nh.ifindex != ifindex || memcmp(&nh.gateway, &gateway, addr_len) != 0) return NULL; } - } else if (!nh.is_present) - return NULL; + } + + if (nm_platform_route_type_is_nodev(rtm->rtm_type)) { + /* These routes are special. They don't have an device/ifindex. + * + * Well, actually, for IPv6 kernel will always say that the device is + * 1 (lo). Of course it does!! */ + if (nh.is_present) { + if (IS_IPv4) { + if (nh.ifindex != 0 || nh.gateway.addr4 != 0) { + /* we only accept kernel to notify about the ifindex/gateway, if it + * is zero. This is only to be a bit forgiving, but we really don't + * know how to handle such routes that have an ifindex. */ + return NULL; + } + } else { + if (!NM_IN_SET(nh.ifindex, 0, 1) || !IN6_IS_ADDR_UNSPECIFIED(&nh.gateway.addr6)) { + /* We allow an ifindex of 1 (will be normalized to zero). Otherwise, + * we don't expect a device/next hop. */ + return NULL; + } + nh.ifindex = 0; + } + } + } else { + if (!nh.is_present) { + /* a "normal" route needs a device. This is not the route we are looking for. */ + return NULL; + } + } /*****************************************************************/ @@ -3528,9 +3578,8 @@ rta_multipath_done:; /*****************************************************************/ - obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL); + obj = nmp_object_new(IS_IPv4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - obj->ip_route.is_external = TRUE; obj->ip_route.type_coerced = nm_platform_route_type_coerce(rtm->rtm_type); obj->ip_route.table_coerced = nm_platform_route_table_coerce( tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : (guint32) rtm->rtm_table); @@ -3545,22 +3594,22 @@ rta_multipath_done:; if (tb[RTA_PRIORITY]) obj->ip_route.metric = nla_get_u32(tb[RTA_PRIORITY]); - if (is_v4) + if (IS_IPv4) obj->ip4_route.gateway = nh.gateway.addr4; else obj->ip6_route.gateway = nh.gateway.addr6; - if (is_v4) + if (IS_IPv4) obj->ip4_route.scope_inv = nm_platform_route_scope_inv(rtm->rtm_scope); if (_check_addr_or_return_null(tb, RTA_PREFSRC, addr_len)) { - if (is_v4) + if (IS_IPv4) memcpy(&obj->ip4_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); else memcpy(&obj->ip6_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); } - if (is_v4) + if (IS_IPv4) obj->ip4_route.tos = rtm->rtm_tos; else { if (tb[RTA_SRC]) { @@ -3582,7 +3631,7 @@ rta_multipath_done:; obj->ip_route.lock_initrwnd = NM_FLAGS_HAS(lock, 1 << RTAX_INITRWND); obj->ip_route.lock_mtu = NM_FLAGS_HAS(lock, 1 << RTAX_MTU); - if (!is_v4) { + if (!IS_IPv4) { if (tb[RTA_PREF]) obj->ip6_route.rt_pref = nla_get_u8(tb[RTA_PREF]); } @@ -3682,12 +3731,12 @@ _new_from_nl_routing_rule(struct nlmsghdr *nlh, gboolean id_only) .maxlen = sizeof(NMFibRulePortRange), }, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr *tb[G_N_ELEMENTS(policy)]; const struct fib_rule_hdr *frh; - NMPlatformRoutingRule * props; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_family; - guint8 addr_size; + NMPlatformRoutingRule *props; + nm_auto_nmpobj NMPObject *obj = NULL; + int addr_family; + guint8 addr_size; if (nlmsg_parse_arr(nlh, sizeof(*frh), tb, policy) < 0) return NULL; @@ -3876,8 +3925,8 @@ _new_from_nl_qdisc(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_only) [TCA_KIND] = {.type = NLA_STRING}, [TCA_OPTIONS] = {.type = NLA_NESTED}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - const struct tcmsg *tcm; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + const struct tcmsg *tcm; nm_auto_nmpobj NMPObject *obj = NULL; if (!nm_platform_get_cache_tc(platform)) @@ -3926,7 +3975,7 @@ _new_from_nl_qdisc(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_only) [TCA_TBF_PARMS] = {.minlen = sizeof(struct tc_tbf_qopt)}, [TCA_TBF_RATE64] = {.type = NLA_U64}, }; - struct nlattr * tbf_tb[G_N_ELEMENTS(tbf_policy)]; + struct nlattr *tbf_tb[G_N_ELEMENTS(tbf_policy)]; struct tc_tbf_qopt opt; if (nla_parse_nested_arr(tbf_tb, tb[TCA_OPTIONS], tbf_policy) < 0) @@ -3988,8 +4037,8 @@ _new_from_nl_tfilter(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_onl static const struct nla_policy policy[] = { [TCA_KIND] = {.type = NLA_STRING}, }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj = NULL; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj = NULL; const struct tcmsg *tcm; if (!nm_platform_get_cache_tc(platform)) @@ -4028,9 +4077,9 @@ _new_from_nl_tfilter(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_onl * Returns: %NULL or a newly created NMPObject instance. **/ static NMPObject * -nmp_object_new_from_nl(NMPlatform * platform, +nmp_object_new_from_nl(NMPlatform *platform, const NMPCache *cache, - struct nl_msg * msg, + struct nl_msg *msg, gboolean id_only) { struct nlmsghdr *msghdr; @@ -4113,7 +4162,7 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo { struct nlattr *info; struct nlattr *data = NULL; - const char * kind; + const char *kind; nm_assert(msg); @@ -4242,9 +4291,9 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo } case NM_LINK_TYPE_VETH: { - const char * veth_peer = extra_data; + const char *veth_peer = extra_data; const struct ifinfomsg ifi = {}; - struct nlattr * info_peer; + struct nlattr *info_peer; nm_assert(veth_peer); @@ -4438,7 +4487,7 @@ nla_put_failure: } static gboolean -_nl_msg_new_link_set_linkinfo_vlan(struct nl_msg * msg, +_nl_msg_new_link_set_linkinfo_vlan(struct nl_msg *msg, int vlan_id, guint32 flags_mask, guint32 flags_set, @@ -4559,10 +4608,10 @@ _nl_msg_new_link_full(int nlmsg_type, { nm_auto_nlmsg struct nl_msg *msg = NULL; const struct ifinfomsg ifi = { - .ifi_family = family, - .ifi_change = flags_mask, - .ifi_flags = flags_set, - .ifi_index = ifindex, + .ifi_family = family, + .ifi_change = flags_mask, + .ifi_flags = flags_set, + .ifi_index = ifindex, }; nm_assert(NM_IN_SET(nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK)); @@ -4601,14 +4650,14 @@ _nl_msg_new_address(int nlmsg_type, guint32 lifetime, guint32 preferred, in_addr_t ip4_broadcast_address, - const char * label) + const char *label) { nm_auto_nlmsg struct nl_msg *msg = NULL; struct ifaddrmsg am = { - .ifa_family = family, - .ifa_index = ifindex, - .ifa_prefixlen = plen, - .ifa_flags = flags, + .ifa_family = family, + .ifa_index = ifindex, + .ifa_prefixlen = plen, + .ifa_flags = flags, }; gsize addr_len; @@ -4680,27 +4729,48 @@ ip_route_get_lock_flag(const NMPlatformIPRoute *route) | (((guint32) route->lock_mtu) << RTAX_MTU); } +static gboolean +ip_route_ignored_protocol(const NMPlatformIPRoute *route) +{ + guint8 prot; + + nm_assert(route); + nm_assert(route->rt_source >= NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC + && route->rt_source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST); + + prot = route->rt_source - 1; + + nm_assert(nmp_utils_ip_config_source_from_rtprot(prot) == route->rt_source); + + /* We ignore all routes outside a certain subest of rtm_protocol. NetworkManager + * itself wouldn't configure those, so they are always configured by somebody + * external. We thus ignore them to avoid the overhead that processing them brings. + * For example, the BGP daemon "bird" might configure a huge number of RTPROT_BIRD routes. */ + + return prot > RTPROT_STATIC && !NM_IN_SET(prot, RTPROT_DHCP, RTPROT_RA); +} + /* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */ static struct nl_msg * _nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - const NMPClass * klass = NMP_OBJECT_GET_CLASS(obj); - gboolean is_v4 = klass->addr_family == AF_INET; - const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj)); + nm_auto_nlmsg struct nl_msg *msg = NULL; + const NMPClass *klass = NMP_OBJECT_GET_CLASS(obj); + const gboolean IS_IPv4 = NM_IS_IPv4(klass->addr_family); + const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj)); const guint32 table = nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE); const struct rtmsg rtmsg = { .rtm_family = klass->addr_family, - .rtm_tos = is_v4 ? obj->ip4_route.tos : 0, + .rtm_tos = IS_IPv4 ? obj->ip4_route.tos : 0, .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC, .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot(obj->ip_route.rt_source), .rtm_scope = - is_v4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, + IS_IPv4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, .rtm_type = nm_platform_route_type_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced), .rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)), .rtm_dst_len = obj->ip_route.plen, - .rtm_src_len = is_v4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen, + .rtm_src_len = IS_IPv4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen, }; gsize addr_len; @@ -4714,28 +4784,28 @@ _nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) if (nlmsg_append_struct(msg, &rtmsg) < 0) goto nla_put_failure; - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + addr_len = IS_IPv4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); NLA_PUT(msg, RTA_DST, addr_len, - is_v4 ? (gconstpointer) &obj->ip4_route.network - : (gconstpointer) &obj->ip6_route.network); + IS_IPv4 ? (gconstpointer) &obj->ip4_route.network + : (gconstpointer) &obj->ip6_route.network); - if (!is_v4) { + if (!IS_IPv4) { if (!IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(obj)->src)) NLA_PUT(msg, RTA_SRC, addr_len, &obj->ip6_route.src); } NLA_PUT_U32(msg, RTA_PRIORITY, - is_v4 ? nm_platform_ip4_route_get_effective_metric(&obj->ip4_route) - : nm_platform_ip6_route_get_effective_metric(&obj->ip6_route)); + IS_IPv4 ? nm_platform_ip4_route_get_effective_metric(&obj->ip4_route) + : nm_platform_ip6_route_get_effective_metric(&obj->ip6_route)); if (table > 0xFF) NLA_PUT_U32(msg, RTA_TABLE, table); - if (is_v4) { + if (IS_IPv4) { if (NMP_OBJECT_CAST_IP4_ROUTE(obj)->pref_src) NLA_PUT(msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src); } else { @@ -4770,7 +4840,7 @@ _nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) } /* We currently don't have need for multi-hop routes... */ - if (is_v4) { + if (IS_IPv4) { NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); } else { if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway)) @@ -4778,7 +4848,7 @@ _nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) } NLA_PUT_U32(msg, RTA_OIF, obj->ip_route.ifindex); - if (!is_v4 && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM) + if (!IS_IPv4 && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM) NLA_PUT_U8(msg, RTA_PREF, obj->ip6_route.rt_pref); return g_steal_pointer(&msg); @@ -4904,13 +4974,13 @@ static struct nl_msg * _nl_msg_new_qdisc(int nlmsg_type, int nlmsg_flags, const NMPlatformQdisc *qdisc) { nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr * tc_options; + struct nlattr *tc_options; const struct tcmsg tcm = { - .tcm_family = qdisc->addr_family, - .tcm_ifindex = qdisc->ifindex, - .tcm_handle = qdisc->handle, - .tcm_parent = qdisc->parent, - .tcm_info = qdisc->info, + .tcm_family = qdisc->addr_family, + .tcm_ifindex = qdisc->ifindex, + .tcm_handle = qdisc->handle, + .tcm_parent = qdisc->parent, + .tcm_info = qdisc->info, }; msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); @@ -4991,14 +5061,14 @@ static struct nl_msg * _nl_msg_new_tfilter(int nlmsg_type, int nlmsg_flags, const NMPlatformTfilter *tfilter) { nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr * tc_options; - struct nlattr * act_tab; + struct nlattr *tc_options; + struct nlattr *act_tab; const struct tcmsg tcm = { - .tcm_family = tfilter->addr_family, - .tcm_ifindex = tfilter->ifindex, - .tcm_handle = tfilter->handle, - .tcm_parent = tfilter->parent, - .tcm_info = tfilter->info, + .tcm_family = tfilter->addr_family, + .tcm_ifindex = tfilter->ifindex, + .tcm_handle = tfilter->handle, + .tcm_parent = tfilter->parent, + .tcm_info = tfilter->info, }; msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); @@ -5016,8 +5086,8 @@ _nl_msg_new_tfilter(int nlmsg_type, int nlmsg_flags, const NMPlatformTfilter *tf if (tfilter->action.kind) { const NMPlatformAction *action = &tfilter->action; - struct nlattr * prio; - struct nlattr * act_options; + struct nlattr *prio; + struct nlattr *act_options; if (!(prio = nla_nest_start(msg, 1 /* priority */))) goto nla_put_failure; @@ -5121,7 +5191,7 @@ _log_dbg_sysctl_set_impl(NMPlatform *platform, const char *path, const char *value) { - GError * error = NULL; + GError *error = NULL; gs_free char *contents = NULL; gs_free char *value_escaped = g_strescape(value, NULL); @@ -5175,7 +5245,7 @@ sysctl_set_internal(NMPlatform *platform, int fd, tries; gssize nwrote; gssize len; - char * actual; + char *actual; gs_free char *actual_free = NULL; int errsv; @@ -5314,12 +5384,12 @@ sysctl_set(NMPlatform *platform, const char *pathid, int dirfd, const char *path } typedef struct { - NMPlatform * platform; - char * pathid; + NMPlatform *platform; + char *pathid; int dirfd; - char * path; - char ** values; - GCancellable * cancellable; + char *path; + char **values; + GCancellable *cancellable; NMPlatformAsyncCallback callback; gpointer callback_data; } SysctlAsyncInfo; @@ -5340,11 +5410,11 @@ sysctl_async_info_free(SysctlAsyncInfo *info) static void sysctl_async_cb(GObject *object, GAsyncResult *res, gpointer user_data) { - NMPlatform * platform; - GTask * task = G_TASK(res); - SysctlAsyncInfo *info; + NMPlatform *platform; + GTask *task = G_TASK(res); + SysctlAsyncInfo *info; gs_free_error GError *error = NULL; - gs_free char * values_str = NULL; + gs_free char *values_str = NULL; info = g_task_get_task_data(task); @@ -5360,15 +5430,15 @@ sysctl_async_cb(GObject *object, GAsyncResult *res, gpointer user_data) } static void -sysctl_async_thread_fn(GTask * task, +sysctl_async_thread_fn(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { nm_auto_pop_netns NMPNetns *netns = NULL; - SysctlAsyncInfo * info = task_data; - GError * error = NULL; - char ** value; + SysctlAsyncInfo *info = task_data; + GError *error = NULL; + char **value; if (g_task_return_error_if_cancelled(task)) return; @@ -5403,11 +5473,11 @@ sysctl_async_thread_fn(GTask * task, static void sysctl_set_async_return_idle(gpointer user_data, GCancellable *cancellable) { - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError * error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; + gs_unref_object NMPlatform *platform = NULL; + gs_free_error GError *cancelled_error = NULL; + gs_free_error GError *error = NULL; + NMPlatformAsyncCallback callback; + gpointer callback_data; nm_utils_user_data_unpack(user_data, &platform, &callback, &callback_data, &error); g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); @@ -5415,20 +5485,20 @@ sysctl_set_async_return_idle(gpointer user_data, GCancellable *cancellable) } static void -sysctl_set_async(NMPlatform * platform, - const char * pathid, +sysctl_set_async(NMPlatform *platform, + const char *pathid, int dirfd, - const char * path, - const char *const * values, + const char *path, + const char *const *values, NMPlatformAsyncCallback callback, gpointer data, - GCancellable * cancellable) + GCancellable *cancellable) { SysctlAsyncInfo *info; - GTask * task; + GTask *task; int dirfd_dup, errsv; gpointer packed; - GError * error = NULL; + GError *error = NULL; g_return_if_fail(platform); g_return_if_fail(path); @@ -5501,7 +5571,7 @@ _nm_logging_clear_platform_logging_cache(void) typedef struct { const char *path; CList lst; - char * value; + char *value; char path_data[]; } SysctlCacheEntry; @@ -5539,7 +5609,7 @@ _log_dbg_sysctl_get_impl(NMPlatform *platform, const char *pathid, const char *c **/ NM_G_MUTEX_LOCKED(&sysctl_clear_cache_lock); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - SysctlCacheEntry * entry = NULL; + SysctlCacheEntry *entry = NULL; if (!priv->sysctl_get_prev_values) { c_list_link_tail(&sysctl_clear_cache_lst_head, &priv->sysctl_clear_cache_lst); @@ -5567,7 +5637,7 @@ _log_dbg_sysctl_get_impl(NMPlatform *platform, const char *pathid, const char *c nm_c_list_move_front(&priv->sysctl_list, &entry->lst); } else { - gs_free char * contents_escaped = g_strescape(contents, NULL); + gs_free char *contents_escaped = g_strescape(contents, NULL); SysctlCacheEntry *old; size_t len; @@ -5602,8 +5672,8 @@ static char * sysctl_get(NMPlatform *platform, const char *pathid, int dirfd, const char *path) { nm_auto_pop_netns NMPNetns *netns = NULL; - GError * error = NULL; - gs_free char * contents = NULL; + GError *error = NULL; + gs_free char *contents = NULL; ASSERT_SYSCTL_ARGS(pathid, dirfd, path); @@ -5813,10 +5883,10 @@ static NM_UTILS_LOOKUP_STR_DEFINE( static const char * delayed_action_to_string_full(DelayedActionType action_type, gpointer user_data, - char * buf, + char *buf, gsize buf_size) { - char * buf0 = buf; + char *buf0 = buf; const DelayedActionWaitForNlResponseData *data; nm_strbuf_append_str(&buf, &buf_size, delayed_action_to_string(action_type)); @@ -5831,7 +5901,7 @@ delayed_action_to_string_full(DelayedActionType action_type, data = user_data; if (data) { - gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_nsec(); + gint64 timeout = data->timeout_abs_nsec - nm_utils_get_monotonic_timestamp_nsec(); char b[255]; nm_strbuf_append( @@ -5889,11 +5959,11 @@ delayed_action_refresh_all_in_progress(NMPlatform *platform, DelayedActionType a } static void -delayed_action_wait_for_nl_response_complete(NMPlatform * platform, +delayed_action_wait_for_nl_response_complete(NMPlatform *platform, guint idx, WaitForNlResponseResult seq_result) { - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); DelayedActionWaitForNlResponseData *data; nm_assert(NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); @@ -5932,17 +6002,17 @@ delayed_action_wait_for_nl_response_complete(NMPlatform * platform, } static void -delayed_action_wait_for_nl_response_complete_check(NMPlatform * platform, +delayed_action_wait_for_nl_response_complete_check(NMPlatform *platform, WaitForNlResponseResult force_result, - guint32 * out_next_seq_number, - gint64 * out_next_timeout_abs_ns, - gint64 * p_now_ns) + guint32 *out_next_seq_number, + gint64 *out_next_timeout_abs_ns, + gint64 *p_now_nsec) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); guint i; guint32 next_seq_number = 0; gint64 next_timeout_abs_ns = 0; - gint64 now_ns = 0; + gint64 now_nsec = 0; for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len;) { const DelayedActionWaitForNlResponseData *data = @@ -5952,10 +6022,10 @@ delayed_action_wait_for_nl_response_complete_check(NMPlatform * platf if (data->seq_result) delayed_action_wait_for_nl_response_complete(platform, i, data->seq_result); - else if (p_now_ns - && ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_nsec())) - >= data->timeout_abs_ns)) { - /* the caller can optionally check for timeout by providing a p_now_ns argument. */ + else if (p_now_nsec + && ((now_nsec ?: (now_nsec = nm_utils_get_monotonic_timestamp_nsec())) + >= data->timeout_abs_nsec)) { + /* the caller can optionally check for timeout by providing a p_now_nsec argument. */ delayed_action_wait_for_nl_response_complete( platform, i, @@ -5963,9 +6033,9 @@ delayed_action_wait_for_nl_response_complete_check(NMPlatform * platf } else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) delayed_action_wait_for_nl_response_complete(platform, i, force_result); else { - if (next_seq_number == 0 || next_timeout_abs_ns > data->timeout_abs_ns) { + if (next_seq_number == 0 || next_timeout_abs_ns > data->timeout_abs_nsec) { next_seq_number = data->seq_number; - next_timeout_abs_ns = data->timeout_abs_ns; + next_timeout_abs_ns = data->timeout_abs_nsec; } i++; } @@ -5979,11 +6049,11 @@ delayed_action_wait_for_nl_response_complete_check(NMPlatform * platf NM_SET_OUT(out_next_seq_number, next_seq_number); NM_SET_OUT(out_next_timeout_abs_ns, next_timeout_abs_ns); - NM_SET_OUT(p_now_ns, now_ns); + NM_SET_OUT(p_now_nsec, now_nsec); } static void -delayed_action_wait_for_nl_response_complete_all(NMPlatform * platform, +delayed_action_wait_for_nl_response_complete_all(NMPlatform *platform, WaitForNlResponseResult fallback_result) { delayed_action_wait_for_nl_response_complete_check(platform, fallback_result, NULL, NULL, NULL); @@ -6080,8 +6150,8 @@ delayed_action_handle_one(NMPlatform *platform) priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL; if (_LOGt_ENABLED()) { - FOR_EACH_DELAYED_ACTION(iflags, flags) - _LOGt_delayed_action(iflags, NULL, "handle"); + FOR_EACH_DELAYED_ACTION (iflags, flags) + _LOGt_delayed_action(iflags, NULL, "handle"); } delayed_action_handle_REFRESH_ALL(platform, flags); @@ -6177,22 +6247,22 @@ delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpo priv->delayed_action.flags |= action_type; if (_LOGt_ENABLED()) { - FOR_EACH_DELAYED_ACTION(iflags, action_type) - _LOGt_delayed_action(iflags, user_data, "schedule"); + FOR_EACH_DELAYED_ACTION (iflags, action_type) + _LOGt_delayed_action(iflags, user_data, "schedule"); } } static void -delayed_action_schedule_WAIT_FOR_NL_RESPONSE(NMPlatform * platform, +delayed_action_schedule_WAIT_FOR_NL_RESPONSE(NMPlatform *platform, guint32 seq_number, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, + WaitForNlResponseResult *out_seq_result, + char **out_errmsg, DelayedActionWaitForNlResponseType response_type, gpointer response_out_data) { DelayedActionWaitForNlResponseData data = { .seq_number = seq_number, - .timeout_abs_ns = + .timeout_abs_nsec = nm_utils_get_monotonic_timestamp_nsec() + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)), .out_seq_result = out_seq_result, .out_errmsg = out_errmsg, @@ -6211,7 +6281,7 @@ cache_prune_one_type(NMPlatform *platform, const NMPLookup *lookup) NMDedupMultiIter iter; const NMPObject *obj; NMPCacheOpsType cache_op; - NMPCache * cache = nm_platform_get_cache(platform); + NMPCache *cache = nm_platform_get_cache(platform); nm_dedup_multi_iter_init(&iter, nmp_cache_lookup(cache, lookup)); while (nm_dedup_multi_iter_next(&iter)) { @@ -6260,7 +6330,7 @@ cache_prune_all(NMPlatform *platform) } static void -cache_on_change(NMPlatform * platform, +cache_on_change(NMPlatform *platform, NMPCacheOpsType cache_op, const NMPObject *obj_old, const NMPObject *obj_new) @@ -6268,7 +6338,7 @@ cache_on_change(NMPlatform * platform, const NMPClass *klass; char str_buf[sizeof(_nm_utils_to_string_buffer)]; char str_buf2[sizeof(_nm_utils_to_string_buffer)]; - NMPCache * cache = nm_platform_get_cache(platform); + NMPCache *cache = nm_platform_get_cache(platform); ASSERT_nmp_cache_ops(cache, cache_op, obj_old, obj_new); nm_assert(cache_op != NMP_CACHE_OPS_UNCHANGED); @@ -6531,10 +6601,10 @@ _nlh_seq_next_get(NMLinuxPlatformPrivate *priv) * Returns: 0 on success or a negative errno. */ static int -_nl_send_nlmsghdr(NMPlatform * platform, - struct nlmsghdr * nlhdr, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, +_nl_send_nlmsghdr(NMPlatform *platform, + struct nlmsghdr *nlhdr, + WaitForNlResponseResult *out_seq_result, + char **out_errmsg, DelayedActionWaitForNlResponseType response_type, gpointer response_out_data) { @@ -6598,15 +6668,15 @@ again: * Returns: 0 on success, or a negative libnl3 error code (beware, it's not an errno). */ static int -_nl_send_nlmsg(NMPlatform * platform, - struct nl_msg * nlmsg, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, +_nl_send_nlmsg(NMPlatform *platform, + struct nl_msg *nlmsg, + WaitForNlResponseResult *out_seq_result, + char **out_errmsg, DelayedActionWaitForNlResponseType response_type, gpointer response_out_data) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - struct nlmsghdr * nlhdr; + struct nlmsghdr *nlhdr; guint32 seq; int nle; @@ -6632,7 +6702,7 @@ _nl_send_nlmsg(NMPlatform * platform, static void do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name) { - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); nm_auto_nlmsg struct nl_msg *nlmsg = NULL; int nle; @@ -6680,7 +6750,7 @@ static struct nl_msg * _nl_msg_new_dump(NMPObjectType obj_type, int preferred_addr_family) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPClass * klass; + const NMPClass *klass; klass = nmp_class_from_type(obj_type); @@ -6753,8 +6823,7 @@ do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action action_type_prune &= ~DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL; } - FOR_EACH_DELAYED_ACTION(iflags, action_type_prune) - { + FOR_EACH_DELAYED_ACTION (iflags, action_type_prune) { RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); NMPLookup lookup; @@ -6763,12 +6832,11 @@ do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action nmp_cache_dirty_set_all_main(nm_platform_get_cache(platform), &lookup); } - FOR_EACH_DELAYED_ACTION(iflags, action_type) - { + FOR_EACH_DELAYED_ACTION (iflags, action_type) { RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); const RefreshAllInfo *refresh_all_info = refresh_all_type_get_info(refresh_all_type); nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int * out_refresh_all_in_progress; + int *out_refresh_all_in_progress; out_refresh_all_in_progress = &priv->delayed_action.refresh_all_in_progress[refresh_all_type]; @@ -6826,7 +6894,7 @@ do_request_one_type_by_needle_object(NMPlatform *platform, const NMPObject *obj_ static void event_seq_check_refresh_all(NMPlatform *platform, guint32 seq_number) { - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); DelayedActionWaitForNlResponseData *data; guint i; @@ -6855,12 +6923,12 @@ event_seq_check_refresh_all(NMPlatform *platform, guint32 seq_number) } static void -event_seq_check(NMPlatform * platform, +event_seq_check(NMPlatform *platform, guint32 seq_number, WaitForNlResponseResult seq_result, - const char * msg) + const char *msg) { - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); DelayedActionWaitForNlResponseData *data; guint i; @@ -6901,14 +6969,14 @@ event_seq_check(NMPlatform * platform, static void event_valid_msg(NMPlatform *platform, struct nl_msg *msg, gboolean handle_events) { - NMLinuxPlatformPrivate *priv; + NMLinuxPlatformPrivate *priv; nm_auto_nmpobj NMPObject *obj = NULL; NMPCacheOpsType cache_op; - struct nlmsghdr * msghdr; + struct nlmsghdr *msghdr; char buf_nlmsghdr[400]; gboolean is_del = FALSE; gboolean is_dump = FALSE; - NMPCache * cache = nm_platform_get_cache(platform); + NMPCache *cache = nm_platform_get_cache(platform); msghdr = nlmsg_hdr(msg); @@ -7010,6 +7078,17 @@ event_valid_msg(NMPlatform *platform, struct nl_msg *msg, gboolean handle_events } } + if (ip_route_ignored_protocol(NMP_OBJECT_CAST_IP_ROUTE(obj))) { + /* We ignore certain rtm_protocol, because NetworkManager would only ever + * configure certain protocols. Other routes were not added by NetworkManager + * and we don't need to track them in the platform cache. + * + * This is to help with the performance overhead of a huge number of + * routes, for example with the bird BGP software, that adds routes + * with RTPROT_BIRD protocol. */ + return; + } + cache_op = nmp_cache_update_netlink_route(cache, obj, is_dump, @@ -7085,18 +7164,18 @@ event_valid_msg(NMPlatform *platform, struct nl_msg *msg, gboolean handle_events /*****************************************************************************/ static int -do_add_link_with_lookup(NMPlatform * platform, +do_add_link_with_lookup(NMPlatform *platform, NMLinkType link_type, - const char * name, - struct nl_msg * nlmsg, + const char *name, + struct nl_msg *nlmsg, const NMPlatformLink **out_link) { - const NMPObject * obj = NULL; + const NMPObject *obj = NULL; WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; - NMPCache * cache = nm_platform_get_cache(platform); + NMPCache *cache = nm_platform_get_cache(platform); event_handler_read_netlink(platform, FALSE); @@ -7135,13 +7214,13 @@ do_add_link_with_lookup(NMPlatform * platform, } static int -do_add_addrroute(NMPlatform * platform, +do_add_addrroute(NMPlatform *platform, const NMPObject *obj_id, - struct nl_msg * nlmsg, + struct nl_msg *nlmsg, gboolean suppress_netlink_failure) { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; @@ -7200,11 +7279,11 @@ static gboolean do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *nlmsg) { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; gboolean success; - const char * log_detail = ""; + const char *log_detail = ""; event_handler_read_netlink(platform, FALSE); @@ -7270,23 +7349,23 @@ do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *n } static int -do_change_link(NMPlatform * platform, +do_change_link(NMPlatform *platform, ChangeLinkType change_link_type, int ifindex, - struct nl_msg * nlmsg, + struct nl_msg *nlmsg, const ChangeLinkData *data) { nm_auto_pop_netns NMPNetns *netns = NULL; int nle; WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; char s_buf[256]; int result = 0; NMLogLevel log_level = LOGL_DEBUG; - const char * log_result = "failure"; - const char * log_detail = ""; - gs_free char * log_detail_free = NULL; - const NMPObject * obj_cache; + const char *log_result = "failure"; + const char *log_detail = ""; + gs_free char *log_detail_free = NULL; + const NMPObject *obj_cache; if (!nm_platform_netns_push(platform, &netns)) { log_level = LOGL_ERR; @@ -7368,11 +7447,11 @@ out: } static int -link_add(NMPlatform * platform, +link_add(NMPlatform *platform, NMLinkType type, - const char * name, + const char *name, int parent, - const void * address, + const void *address, size_t address_len, guint32 mtu, gconstpointer extra_data, @@ -7418,7 +7497,7 @@ link_delete(NMPlatform *platform, int ifindex) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; NMPObject obj_id; - const NMPObject * obj; + const NMPObject *obj; obj = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); if (!obj || !obj->_link.netlink.is_in_netlink) @@ -7527,7 +7606,7 @@ static gboolean link_supports_vlans(NMPlatform *platform, int ifindex) { nm_auto_pop_netns NMPNetns *netns = NULL; - const NMPObject * obj; + const NMPObject *obj; obj = nm_platform_link_get_obj(platform, ifindex, TRUE); @@ -7569,10 +7648,10 @@ link_set_address(NMPlatform *platform, int ifindex, gconstpointer address, size_ { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; const ChangeLinkData d = { - .set_address = + .set_address = { - .address = address, - .length = length, + .address = address, + .length = length, }, }; @@ -7643,11 +7722,11 @@ nla_put_failure: static void sriov_idle_cb(gpointer user_data, GCancellable *cancellable) { - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError * error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; + gs_unref_object NMPlatform *platform = NULL; + gs_free_error GError *cancelled_error = NULL; + gs_free_error GError *error = NULL; + NMPlatformAsyncCallback callback; + gpointer callback_data; g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); nm_utils_user_data_unpack(user_data, &platform, &error, &callback, &callback_data); @@ -7655,24 +7734,24 @@ sriov_idle_cb(gpointer user_data, GCancellable *cancellable) } static void -link_set_sriov_params_async(NMPlatform * platform, +link_set_sriov_params_async(NMPlatform *platform, int ifindex, guint num_vfs, NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer data, - GCancellable * cancellable) + GCancellable *cancellable) { nm_auto_pop_netns NMPNetns *netns = NULL; - gs_free_error GError *error = NULL; - nm_auto_close int dirfd = -1; - int current_autoprobe; - guint i, total; - gint64 current_num; - char ifname[IFNAMSIZ]; - gpointer packed; - const char * values[3]; - char buf[64]; + gs_free_error GError *error = NULL; + nm_auto_close int dirfd = -1; + int current_autoprobe; + guint i, total; + gint64 current_num; + char ifname[IFNAMSIZ]; + gpointer packed; + const char *values[3]; + char buf[64]; g_return_if_fail(callback || !data); g_return_if_fail(cancellable); @@ -7781,7 +7860,7 @@ static gboolean link_set_sriov_vfs(NMPlatform *platform, int ifindex, const NMPlatformVF *const *vfs) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr * list, *info, *vlan_list; + struct nlattr *list, *info, *vlan_list; guint i; nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); @@ -7868,13 +7947,13 @@ nla_put_failure: } static gboolean -link_set_bridge_vlans(NMPlatform * platform, +link_set_bridge_vlans(NMPlatform *platform, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr * list; + struct nlattr *list; struct bridge_vlan_info vinfo = {}; guint i; @@ -7959,13 +8038,13 @@ link_get_dev_id(NMPlatform *platform, int ifindex) } static gboolean -link_tun_add(NMPlatform * platform, - const char * name, +link_tun_add(NMPlatform *platform, + const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink ** out_link, - int * out_fd) + const NMPlatformLink **out_link, + int *out_fd) { - const NMPObject * obj; + const NMPObject *obj; struct ifreq ifr = {}; nm_auto_close int fd = -1; @@ -8023,8 +8102,8 @@ _vlan_change_vlan_qos_mapping_create(gboolean is_ingress_map, guint current_n_map, const NMVlanQosMapping *set_map, guint set_n_map, - NMVlanQosMapping ** out_map, - guint * out_n_map) + NMVlanQosMapping **out_map, + guint *out_n_map) { NMVlanQosMapping *map; guint i, j, len; @@ -8087,7 +8166,7 @@ _vlan_change_vlan_qos_mapping_create(gboolean is_ingress_map, } static gboolean -link_vlan_change(NMPlatform * platform, +link_vlan_change(NMPlatform *platform, int ifindex, _NMVlanFlags flags_mask, _NMVlanFlags flags_set, @@ -8098,13 +8177,13 @@ link_vlan_change(NMPlatform * platform, const NMVlanQosMapping *egress_map, gsize n_egress_map) { - const NMPObject * obj_cache; + const NMPObject *obj_cache; nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPObjectLnkVlan * lnk; + const NMPObjectLnkVlan *lnk; guint new_n_ingress_map = 0; guint new_n_egress_map = 0; - gs_free NMVlanQosMapping *new_ingress_map = NULL; - gs_free NMVlanQosMapping *new_egress_map = NULL; + gs_free NMVlanQosMapping *new_ingress_map = NULL; + gs_free NMVlanQosMapping *new_egress_map = NULL; obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); if (!obj_cache || !obj_cache->_link.netlink.is_in_netlink) { @@ -8175,7 +8254,7 @@ link_release(NMPlatform *platform, int master, int slave) /*****************************************************************************/ static gboolean -_infiniband_partition_action(NMPlatform * platform, +_infiniband_partition_action(NMPlatform *platform, InfinibandAction action, int parent, int p_key, @@ -8183,7 +8262,7 @@ _infiniband_partition_action(NMPlatform * platform, { nm_auto_close int dirfd = -1; char ifname_parent[IFNAMSIZ]; - const NMPObject * obj; + const NMPObject *obj; char id[20]; char name[IFNAMSIZ]; gboolean success; @@ -8234,7 +8313,7 @@ _infiniband_partition_action(NMPlatform * platform, } static gboolean -infiniband_partition_add(NMPlatform * platform, +infiniband_partition_add(NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) @@ -8274,7 +8353,7 @@ get_ext_data(NMPlatform *platform, int ifindex) #define WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, retval) \ nm_auto_pop_netns NMPNetns *netns = NULL; \ - NMWifiUtils * wifi_data; \ + NMWifiUtils *wifi_data; \ if (!nm_platform_netns_push(platform, &netns)) \ return retval; \ wifi_data = NM_WIFI_UTILS(get_ext_data(platform, ifindex)); \ @@ -8298,11 +8377,11 @@ wifi_get_frequency(NMPlatform *platform, int ifindex) } static gboolean -wifi_get_station(NMPlatform * platform, +wifi_get_station(NMPlatform *platform, int ifindex, NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) + int *out_quality, + guint32 *out_rate) { WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); return nm_wifi_utils_get_station(wifi_data, out_bssid, out_quality, out_rate); @@ -8365,7 +8444,7 @@ link_can_assume(NMPlatform *platform, int ifindex) NMPLookup lookup; const NMPObject *link, *o; NMDedupMultiIter iter; - NMPCache * cache = nm_platform_get_cache(platform); + NMPCache *cache = nm_platform_get_cache(platform); if (ifindex <= 0) return FALSE; @@ -8488,9 +8567,9 @@ link_get_wake_on_lan(NMPlatform *platform, int ifindex) static gboolean link_get_driver_info(NMPlatform *platform, int ifindex, - char ** out_driver_name, - char ** out_driver_version, - char ** out_fw_version) + char **out_driver_name, + char **out_driver_version, + char **out_fw_version) { nm_auto_pop_netns NMPNetns *netns = NULL; NMPUtilsEthtoolDriverInfo driver_info; @@ -8543,7 +8622,7 @@ ip4_address_add(NMPlatform *platform, } static gboolean -ip6_address_add(NMPlatform * platform, +ip6_address_add(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen, @@ -8632,7 +8711,7 @@ ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guin /*****************************************************************************/ static int -ip_route_add(NMPlatform * platform, +ip_route_add(NMPlatform *platform, NMPNlmFlags flags, int addr_family, const NMPlatformIPRoute *route) @@ -8659,7 +8738,7 @@ static gboolean object_delete(NMPlatform *platform, const NMPObject *obj) { nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL; - nm_auto_nlmsg struct nl_msg * nlmsg = NULL; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; if (!NMP_OBJECT_IS_STACKINIT(obj)) obj_keep_alive = nmp_object_ref(obj); @@ -8690,17 +8769,17 @@ object_delete(NMPlatform *platform, const NMPObject *obj) /*****************************************************************************/ static int -ip_route_get(NMPlatform * platform, +ip_route_get(NMPlatform *platform, int addr_family, gconstpointer address, int oif_ifindex, - NMPObject ** out_route) + NMPObject **out_route) { - const gboolean is_v4 = (addr_family == AF_INET); - const int addr_len = is_v4 ? 4 : 16; - int try_count = 0; - WaitForNlResponseResult seq_result; - int nle; + const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int addr_len = IS_IPv4 ? 4 : 16; + int try_count = 0; + WaitForNlResponseResult seq_result; + int nle; nm_auto_nmpobj NMPObject *route = NULL; nm_assert(NM_IS_LINUX_PLATFORM(platform)); @@ -8718,7 +8797,7 @@ ip_route_get(NMPlatform * platform, .n.nlmsg_type = RTM_GETROUTE, .r.rtm_family = addr_family, .r.rtm_tos = 0, - .r.rtm_dst_len = is_v4 ? 32 : 128, + .r.rtm_dst_len = IS_IPv4 ? 32 : 128, .r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */, }; @@ -8778,7 +8857,7 @@ routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutin { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; nm_auto_nlmsg struct nl_msg *msg = NULL; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; char s_buf[256]; int nle; @@ -8818,7 +8897,7 @@ static int qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc) { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; nm_auto_nlmsg struct nl_msg *msg = NULL; @@ -8860,14 +8939,14 @@ static int tc_delete(NMPlatform *platform, int nlmsgtype, int ifindex, guint32 parent, gboolean log_error) { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; - const char * log_tag; + const char *log_tag; nm_auto_nlmsg struct nl_msg *msg = NULL; const struct tcmsg tcm = { - .tcm_ifindex = ifindex, - .tcm_parent = parent, + .tcm_ifindex = ifindex, + .tcm_parent = parent, }; switch (nlmsgtype) { @@ -8934,7 +9013,7 @@ static int tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tfilter) { WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; + gs_free char *errmsg = NULL; int nle; char s_buf[256]; nm_auto_nlmsg struct nl_msg *msg = NULL; @@ -8992,39 +9071,44 @@ event_handler(int fd, GIOCondition io_condition, gpointer user_data) static int event_handler_recvmsgs(NMPlatform *platform, gboolean handle_events) { - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - struct nl_sock * sk = priv->nlh; - int n; - int err = 0; - gboolean multipart = 0; - gboolean interrupted = FALSE; - struct nlmsghdr * hdr; - WaitForNlResponseResult seq_result; - struct sockaddr_nl nla = {0}; - struct ucred creds; - gboolean creds_has; - nm_auto_free unsigned char *buf = NULL; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + struct nl_sock *sk = priv->nlh; + int n; + int err = 0; + gboolean multipart = 0; + gboolean interrupted = FALSE; + struct nlmsghdr *hdr; + WaitForNlResponseResult seq_result; + struct sockaddr_nl nla; + struct ucred creds; + gboolean creds_has; + unsigned char *buf; continue_reading: - nm_clear_pointer(&buf, free); - n = nl_recv(sk, &nla, &buf, &creds, &creds_has); + buf = NULL; + + n = nl_recv(sk, + priv->netlink_recv_buf.buf, + priv->netlink_recv_buf.len, + &nla, + &buf, + &creds, + &creds_has); + + nm_assert((n <= 0 && !buf) + || (n > 0 && n <= priv->netlink_recv_buf.len && buf == priv->netlink_recv_buf.buf)); if (n <= 0) { if (n == -NME_NL_MSG_TRUNC) { - int buf_size; - /* the message receive buffer was too small. We lost one message, which * is unfortunate. Try to double the buffer size for the next time. */ - buf_size = nl_socket_get_msg_buf_size(sk); - if (buf_size < 512 * 1024) { - buf_size *= 2; - _LOGT("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", - buf_size); - if (nl_socket_set_msg_buf_size(sk, buf_size) < 0) - nm_assert_not_reached(); - if (!handle_events) - goto continue_reading; - } + priv->netlink_recv_buf.len *= 2; + priv->netlink_recv_buf.buf = + g_realloc(priv->netlink_recv_buf.buf, priv->netlink_recv_buf.len); + _LOGT("netlink: recvmsg: increase message buffer size for recvmsg() to %zu bytes", + priv->netlink_recv_buf.len); + if (!handle_events) + goto continue_reading; } return n; @@ -9037,7 +9121,7 @@ continue_reading: gboolean process_valid_msg = FALSE; guint32 seq_number; char buf_nlmsghdr[400]; - const char * extack_msg = NULL; + const char *extack_msg = NULL; msg = nlmsg_alloc_convert(hdr); @@ -9195,15 +9279,15 @@ static gboolean event_handler_read_netlink(NMPlatform *platform, gboolean wait_for_acks) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); int r; struct pollfd pfd; gboolean any = FALSE; int timeout_msec; struct { guint32 seq_number; - gint64 timeout_abs_ns; - gint64 now_ns; + gint64 timeout_abs_nsec; + gint64 now_nsec; } next; if (!nm_platform_netns_push(platform, &netns)) { @@ -9275,25 +9359,33 @@ after_read: delayed_action_wait_for_nl_response_complete_check(platform, WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN, &next.seq_number, - &next.timeout_abs_ns, - &next.now_ns); + &next.timeout_abs_nsec, + &next.now_nsec); if (!wait_for_acks || !NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) return any; nm_assert(next.seq_number); - nm_assert(next.now_ns > 0); - nm_assert(next.timeout_abs_ns > next.now_ns); + nm_assert(next.now_nsec > 0); + nm_assert(next.timeout_abs_nsec > next.now_nsec); + nm_assert(next.timeout_abs_nsec - next.now_nsec <= 200 * (NM_UTILS_NSEC_PER_SEC / 1000)); - _LOGT("netlink: read: wait for ACK for sequence number %u...", next.seq_number); + timeout_msec = + NM_CLAMP((next.timeout_abs_nsec - next.now_nsec) / (NM_UTILS_NSEC_PER_SEC / 1000), + 1, + 1000); - timeout_msec = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NSEC_PER_SEC / 1000); + _LOGT("netlink: read: wait for ACK for sequence number %u... (%d msec)", + next.seq_number, + timeout_msec); memset(&pfd, 0, sizeof(pfd)); pfd.fd = nl_socket_get_fd(priv->nlh); pfd.events = POLLIN; - r = poll(&pfd, 1, MAX(1, timeout_msec)); + r = poll(&pfd, 1, timeout_msec); + + _LOGT("netlink: read: poll done (r=%d)", r); if (r == 0) { /* timeout and there is nothing to read. */ @@ -9412,11 +9504,11 @@ static void handle_udev_event(NMUdevClient *udev_client, struct udev_device *udevice, gpointer user_data) { nm_auto_pop_netns NMPNetns *netns = NULL; - NMPlatform * platform = NM_PLATFORM(user_data); - const char * subsys; - const char * ifindex; + NMPlatform *platform = NM_PLATFORM(user_data); + const char *subsys; + const char *ifindex; guint64 seqnum; - const char * action; + const char *action; action = udev_device_get_action(udevice); g_return_if_fail(action); @@ -9449,6 +9541,9 @@ nm_linux_platform_init(NMLinuxPlatform *self) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(self); + priv->netlink_recv_buf.len = 32 * 1024; + priv->netlink_recv_buf.buf = g_malloc(priv->netlink_recv_buf.len); + c_list_init(&priv->sysctl_clear_cache_lst); c_list_init(&priv->sysctl_list); @@ -9461,7 +9556,7 @@ nm_linux_platform_init(NMLinuxPlatform *self) static void constructed(GObject *_object) { - NMPlatform * platform = NM_PLATFORM(_object); + NMPlatform *platform = NM_PLATFORM(_object); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); int nle; int fd; @@ -9517,10 +9612,10 @@ constructed(GObject *_object) _LOGD("could not enable extended acks on netlink socket"); /* explicitly set the msg buffer size and disable MSG_PEEK. - * If we later encounter NME_NL_MSG_TRUNC, we will adjust the buffer size. */ + * We use our own receive buffer priv->netlink_recv_buf. + * If we encounter NME_NL_MSG_TRUNC, we will increase the buffer + * and resync (as we would have lost the message without NL_MSG_PEEK). */ nl_socket_disable_msg_peek(priv->nlh); - nle = nl_socket_set_msg_buf_size(priv->nlh, 32 * 1024); - g_assert(!nle); nle = nl_socket_add_memberships(priv->nlh, RTNLGRP_IPV4_IFADDR, @@ -9571,7 +9666,7 @@ constructed(GObject *_object) /* Set up udev monitoring */ if (priv->udev_client) { - struct udev_enumerate * enumerator; + struct udev_enumerate *enumerator; struct udev_list_entry *devices, *l; /* And read initial device list */ @@ -9643,7 +9738,7 @@ nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support, gboolean ca static void dispose(GObject *object) { - NMPlatform * platform = NM_PLATFORM(object); + NMPlatform *platform = NM_PLATFORM(object); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); _LOGD("dispose"); @@ -9688,12 +9783,14 @@ finalize(GObject *object) priv->udev_client = nm_udev_client_destroy(priv->udev_client); G_OBJECT_CLASS(nm_linux_platform_parent_class)->finalize(object); + + g_free(priv->netlink_recv_buf.buf); } static void nm_linux_platform_class_init(NMLinuxPlatformClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMPlatformClass *platform_class = NM_PLATFORM_CLASS(klass); object_class->constructed = constructed; |