diff options
Diffstat (limited to 'src/platform/nm-linux-platform.c')
| -rw-r--r-- | src/platform/nm-linux-platform.c | 1170 |
1 files changed, 552 insertions, 618 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 7abe4dfc..f7249bb7 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -418,13 +418,14 @@ typedef struct { struct nl_sock *genl; struct nl_sock *nlh; + + GSource *event_source; + guint32 nlh_seq_next; #if NM_MORE_LOGGING guint32 nlh_seq_last_handled; #endif guint32 nlh_seq_last_seen; - GIOChannel *event_channel; - guint event_id; guint32 pruning[_REFRESH_ALL_TYPE_NUM]; @@ -603,7 +604,7 @@ _vlan_qos_mapping_cmp_from_ptr (gconstpointer a, gconstpointer b, gpointer user_ ******************************************************************/ typedef struct { - const NMLinkType nm_type; + const char *type_string; /* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type @@ -623,68 +624,202 @@ typedef struct { const char *devtype; } LinkDesc; -static const LinkDesc linktypes[] = { - { NM_LINK_TYPE_NONE, "none", NULL, NULL }, - { NM_LINK_TYPE_UNKNOWN, "unknown", NULL, NULL }, - - { NM_LINK_TYPE_ETHERNET, "ethernet", NULL, NULL }, - { NM_LINK_TYPE_INFINIBAND, "infiniband", NULL, NULL }, - { NM_LINK_TYPE_OLPC_MESH, "olpc-mesh", NULL, NULL }, - { NM_LINK_TYPE_WIFI, "wifi", NULL, "wlan" }, - { NM_LINK_TYPE_WWAN_NET, "wwan", NULL, "wwan" }, - { NM_LINK_TYPE_WIMAX, "wimax", "wimax", "wimax" }, - { NM_LINK_TYPE_WPAN, "wpan", NULL, NULL }, - { NM_LINK_TYPE_6LOWPAN, "6lowpan", NULL, NULL }, - - { NM_LINK_TYPE_BNEP, "bluetooth", NULL, "bluetooth" }, - { NM_LINK_TYPE_DUMMY, "dummy", "dummy", NULL }, - { NM_LINK_TYPE_GRE, "gre", "gre", NULL }, - { NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL }, - { NM_LINK_TYPE_IFB, "ifb", "ifb", NULL }, - { NM_LINK_TYPE_IP6TNL, "ip6tnl", "ip6tnl", NULL }, - { NM_LINK_TYPE_IP6GRE, "ip6gre", "ip6gre", NULL }, - { NM_LINK_TYPE_IP6GRETAP, "ip6gretap", "ip6gretap", NULL }, - { NM_LINK_TYPE_IPIP, "ipip", "ipip", NULL }, - { NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL }, - { NM_LINK_TYPE_MACSEC, "macsec", "macsec", NULL }, - { NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL }, - { NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL }, - { NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL }, - { NM_LINK_TYPE_PPP, "ppp", NULL, "ppp" }, - { NM_LINK_TYPE_SIT, "sit", "sit", NULL }, - { NM_LINK_TYPE_TUN, "tun", "tun", NULL }, - { NM_LINK_TYPE_VETH, "veth", "veth", NULL }, - { NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" }, - { NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" }, - { NM_LINK_TYPE_WIREGUARD, "wireguard", "wireguard", "wireguard" }, - - { NM_LINK_TYPE_BRIDGE, "bridge", "bridge", "bridge" }, - { NM_LINK_TYPE_BOND, "bond", "bond", "bond" }, - { NM_LINK_TYPE_TEAM, "team", "team", NULL }, +static const LinkDesc link_descs[] = { + [NM_LINK_TYPE_NONE] = { "none", NULL, NULL }, + [NM_LINK_TYPE_UNKNOWN] = { "unknown", NULL, NULL }, + [NM_LINK_TYPE_ANY] = { "any", NULL, NULL }, + + [NM_LINK_TYPE_ETHERNET] = { "ethernet", NULL, NULL }, + [NM_LINK_TYPE_INFINIBAND] = { "infiniband", NULL, NULL }, + [NM_LINK_TYPE_OLPC_MESH] = { "olpc-mesh", NULL, NULL }, + [NM_LINK_TYPE_WIFI] = { "wifi", NULL, "wlan" }, + [NM_LINK_TYPE_WWAN_NET] = { "wwan", NULL, "wwan" }, + [NM_LINK_TYPE_WIMAX] = { "wimax", "wimax", "wimax" }, + [NM_LINK_TYPE_WPAN] = { "wpan", NULL, NULL }, + [NM_LINK_TYPE_6LOWPAN] = { "6lowpan", NULL, NULL }, + + [NM_LINK_TYPE_BNEP] = { "bluetooth", NULL, "bluetooth" }, + [NM_LINK_TYPE_DUMMY] = { "dummy", "dummy", NULL }, + [NM_LINK_TYPE_GRE] = { "gre", "gre", NULL }, + [NM_LINK_TYPE_GRETAP] = { "gretap", "gretap", NULL }, + [NM_LINK_TYPE_IFB] = { "ifb", "ifb", NULL }, + [NM_LINK_TYPE_IP6TNL] = { "ip6tnl", "ip6tnl", NULL }, + [NM_LINK_TYPE_IP6GRE] = { "ip6gre", "ip6gre", NULL }, + [NM_LINK_TYPE_IP6GRETAP] = { "ip6gretap", "ip6gretap", NULL }, + [NM_LINK_TYPE_IPIP] = { "ipip", "ipip", NULL }, + [NM_LINK_TYPE_LOOPBACK] = { "loopback", NULL, NULL }, + [NM_LINK_TYPE_MACSEC] = { "macsec", "macsec", NULL }, + [NM_LINK_TYPE_MACVLAN] = { "macvlan", "macvlan", NULL }, + [NM_LINK_TYPE_MACVTAP] = { "macvtap", "macvtap", NULL }, + [NM_LINK_TYPE_OPENVSWITCH] = { "openvswitch", "openvswitch", NULL }, + [NM_LINK_TYPE_PPP] = { "ppp", NULL, "ppp" }, + [NM_LINK_TYPE_SIT] = { "sit", "sit", NULL }, + [NM_LINK_TYPE_TUN] = { "tun", "tun", NULL }, + [NM_LINK_TYPE_VETH] = { "veth", "veth", NULL }, + [NM_LINK_TYPE_VLAN] = { "vlan", "vlan", "vlan" }, + [NM_LINK_TYPE_VRF] = { "vrf", "vrf", "vrf" }, + [NM_LINK_TYPE_VXLAN] = { "vxlan", "vxlan", "vxlan" }, + [NM_LINK_TYPE_WIREGUARD] = { "wireguard", "wireguard", "wireguard" }, + + [NM_LINK_TYPE_BRIDGE] = { "bridge", "bridge", "bridge" }, + [NM_LINK_TYPE_BOND] = { "bond", "bond", "bond" }, + [NM_LINK_TYPE_TEAM] = { "team", "team", NULL }, }; -static const char * -nm_link_type_to_rtnl_type_string (NMLinkType type) +static const LinkDesc * +_link_desc_from_link_type (NMLinkType link_type) { - int i; + nm_assert (_NM_INT_NOT_NEGATIVE (link_type)); + nm_assert (link_type < G_N_ELEMENTS (link_descs)); + nm_assert (link_descs[link_type].type_string); - for (i = 0; i < G_N_ELEMENTS (linktypes); i++) { - if (type == linktypes[i].nm_type) - return linktypes[i].rtnl_type; + return &link_descs[link_type]; +} + +static NMLinkType +_link_type_from_rtnl_type (const char *name) \ +{ + static const NMLinkType LIST[] = { + NM_LINK_TYPE_BOND, /* "bond" */ + NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_DUMMY, /* "dummy" */ + NM_LINK_TYPE_GRE, /* "gre" */ + NM_LINK_TYPE_GRETAP, /* "gretap" */ + NM_LINK_TYPE_IFB, /* "ifb" */ + NM_LINK_TYPE_IP6GRE, /* "ip6gre" */ + NM_LINK_TYPE_IP6GRETAP, /* "ip6gretap" */ + NM_LINK_TYPE_IP6TNL, /* "ip6tnl" */ + NM_LINK_TYPE_IPIP, /* "ipip" */ + NM_LINK_TYPE_MACSEC, /* "macsec" */ + NM_LINK_TYPE_MACVLAN, /* "macvlan" */ + NM_LINK_TYPE_MACVTAP, /* "macvtap" */ + NM_LINK_TYPE_OPENVSWITCH, /* "openvswitch" */ + NM_LINK_TYPE_SIT, /* "sit" */ + NM_LINK_TYPE_TEAM, /* "team" */ + NM_LINK_TYPE_TUN, /* "tun" */ + NM_LINK_TYPE_VETH, /* "veth" */ + NM_LINK_TYPE_VLAN, /* "vlan" */ + NM_LINK_TYPE_VRF, /* "vrf" */ + NM_LINK_TYPE_VXLAN, /* "vxlan" */ + NM_LINK_TYPE_WIMAX, /* "wimax" */ + NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ + }; + + nm_assert (name); + + if (NM_MORE_ASSERT_ONCE (5)) { + int i, j, k; + + for (i = 0; i < G_N_ELEMENTS (LIST); i++) { + nm_assert (_link_desc_from_link_type (LIST[i]) == &link_descs[LIST[i]]); + nm_assert (link_descs[LIST[i]].rtnl_type); + if (i > 0) + nm_assert (strcmp (link_descs[LIST[i - 1]].rtnl_type, link_descs[LIST[i]].rtnl_type) < 0); + } + for (i = 0; i < G_N_ELEMENTS (link_descs); i++) { + if (!link_descs[i].rtnl_type) + continue; + for (j = 0, k = 0; j < G_N_ELEMENTS (LIST); j++) + k += (LIST[j] == i); + nm_assert (k == 1); + } + } + + { + unsigned imin = 0; + unsigned imax = (G_N_ELEMENTS (LIST) - 1); + unsigned imid = (G_N_ELEMENTS (LIST) - 1) / 2; + + for (;;) { + const int cmp = strcmp (link_descs[LIST[imid]].rtnl_type, name); + + if (G_UNLIKELY (cmp == 0)) + return LIST[imid]; + + if (cmp < 0) + imin = imid + 1u; + else + imax = imid - 1u; + + if (G_UNLIKELY (imin > imax)) + return NM_LINK_TYPE_NONE; + + imid = (imin + imax) / 2u; + } } - g_return_val_if_reached (NULL); } -const char * -nm_link_type_to_string (NMLinkType type) -{ - int i; +static NMLinkType +_link_type_from_devtype (const char *name) \ +{ + static const NMLinkType LIST[] = { + NM_LINK_TYPE_BNEP, /* "bluetooth" */ + NM_LINK_TYPE_BOND, /* "bond" */ + NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_PPP, /* "ppp" */ + NM_LINK_TYPE_VLAN, /* "vlan" */ + NM_LINK_TYPE_VRF, /* "vrf" */ + NM_LINK_TYPE_VXLAN, /* "vxlan" */ + NM_LINK_TYPE_WIMAX, /* "wimax" */ + NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ + NM_LINK_TYPE_WIFI, /* "wlan" */ + NM_LINK_TYPE_WWAN_NET, /* "wwan" */ + }; + + nm_assert (name); - for (i = 0; i < G_N_ELEMENTS (linktypes); i++) { - if (type == linktypes[i].nm_type) - return linktypes[i].type_string; + if (NM_MORE_ASSERT_ONCE (5)) { + int i, j, k; + + for (i = 0; i < G_N_ELEMENTS (LIST); i++) { + nm_assert (_link_desc_from_link_type (LIST[i]) == &link_descs[LIST[i]]); + nm_assert (link_descs[LIST[i]].devtype); + if (i > 0) + nm_assert (strcmp (link_descs[LIST[i - 1]].devtype, link_descs[LIST[i]].devtype) < 0); + } + for (i = 0; i < G_N_ELEMENTS (link_descs); i++) { + if (!link_descs[i].devtype) + continue; + for (j = 0, k = 0; j < G_N_ELEMENTS (LIST); j++) + k += (LIST[j] == i); + nm_assert (k == 1); + } } - g_return_val_if_reached (NULL); + + { + unsigned imin = 0; + unsigned imax = (G_N_ELEMENTS (LIST) - 1); + unsigned imid = (G_N_ELEMENTS (LIST) - 1) / 2; + + for (;;) { + const int cmp = strcmp (link_descs[LIST[imid]].devtype, name); + + if (G_UNLIKELY (cmp == 0)) + return LIST[imid]; + + if (cmp < 0) + imin = imid + 1u; + else + imax = imid - 1u; + + if (G_UNLIKELY (imin > imax)) + return NM_LINK_TYPE_NONE; + + imid = (imin + imax) / 2u; + } + } +} + +static const char * +nm_link_type_to_rtnl_type_string (NMLinkType link_type) +{ + return _link_desc_from_link_type (link_type)->rtnl_type; +} + +const char * +nm_link_type_to_string (NMLinkType link_type) +{ + return _link_desc_from_link_type (link_type)->type_string; } /****************************************************************** @@ -738,8 +873,8 @@ _addrtime_timestamp_to_nm (guint32 timestamp, gint32 *out_now_nm) /* do all the calculations in milliseconds scale */ - now_nm = nm_utils_get_monotonic_timestamp_ms (); - now_nl = nm_utils_clock_gettime_ms (CLOCK_MONOTONIC); + now_nm = nm_utils_get_monotonic_timestamp_msec (); + now_nl = nm_utils_clock_gettime_msec (CLOCK_MONOTONIC); nm_assert (now_nm >= 1000); nm_assert (now_nl >= 0); @@ -748,13 +883,13 @@ _addrtime_timestamp_to_nm (guint32 timestamp, gint32 *out_now_nm) NM_SET_OUT (out_now_nm, now_nm / 1000); - /* converting the timestamp into nm_utils_get_monotonic_timestamp_ms() scale is + /* converting the timestamp into nm_utils_get_monotonic_timestamp_msec() scale is * a good guess but fails in the following situations: * * - If the address existed before start of the process, the timestamp in nm scale would * be negative or zero. In this case we default to 1. * - during hibernation, the CLOCK_MONOTONIC/timestamp drifts from - * nm_utils_get_monotonic_timestamp_ms() scale. + * nm_utils_get_monotonic_timestamp_msec() scale. */ if (result <= 1000) return 1; @@ -809,7 +944,7 @@ _addrtime_get_lifetimes (guint32 timestamp, if (now == 0) { /* strange. failed to detect the last-update time and assumed that timestamp is 1. */ nm_assert (timestamp == 1); - now = nm_utils_get_monotonic_timestamp_s (); + now = nm_utils_get_monotonic_timestamp_sec (); } if (timestamp < now) { guint32 diff = now - timestamp; @@ -894,10 +1029,12 @@ _linktype_get_type (NMPlatform *platform, const NMPObject **link_cached, const char **out_kind) { - guint i; + NMLinkType link_type; NMTST_ASSERT_PLATFORM_NETNS_CURRENT (platform); nm_assert (ifname); + nm_assert (_link_type_from_devtype ("wlan") == NM_LINK_TYPE_WIFI); + nm_assert (_link_type_from_rtnl_type ("bond") == NM_LINK_TYPE_BOND); if (completed_from_cache) { const NMPObject *obj; @@ -905,7 +1042,7 @@ _linktype_get_type (NMPlatform *platform, obj = _lookup_cached_link (cache, ifindex, completed_from_cache, link_cached); /* If we detected the link type before, we stick to that - * decision unless the "kind" no "name" changed. If "name" changed, + * decision unless the "kind" or "name" changed. If "name" changed, * it means that their type may not have been determined correctly * due to race conditions while accessing sysfs. * @@ -936,11 +1073,9 @@ _linktype_get_type (NMPlatform *platform, *out_kind = g_intern_string (kind); if (kind) { - for (i = 0; i < G_N_ELEMENTS (linktypes); i++) { - if (nm_streq0 (kind, linktypes[i].rtnl_type)) { - return linktypes[i].nm_type; - } - } + link_type = _link_type_from_rtnl_type (kind); + if (link_type != NM_LINK_TYPE_NONE) + return link_type; } if (arptype == ARPHRD_LOOPBACK) @@ -987,16 +1122,16 @@ _linktype_get_type (NMPlatform *platform, return NM_LINK_TYPE_OLPC_MESH; devtype = _linktype_read_devtype (dirfd); - for (i = 0; devtype && i < G_N_ELEMENTS (linktypes); i++) { - if (g_strcmp0 (devtype, linktypes[i].devtype) == 0) { - if (linktypes[i].nm_type == NM_LINK_TYPE_BNEP) { + if (devtype) { + link_type = _link_type_from_devtype (devtype); + if (link_type != NM_LINK_TYPE_NONE) { + if ( link_type == NM_LINK_TYPE_BNEP + && arptype != ARPHRD_ETHER) { /* Both BNEP and 6lowpan use DEVTYPE=bluetooth, so we must * use arptype to distinguish between them. */ - if (arptype != ARPHRD_ETHER) - continue; - } - return linktypes[i].nm_type; + } else + return link_type; } } @@ -1022,13 +1157,14 @@ _linktype_get_type (NMPlatform *platform, */ if (!kind && !devtype) return NM_LINK_TYPE_ETHERNET; + /* The USB gadget interfaces behave and look like ordinary ethernet devices * aside from the DEVTYPE. */ - if (!g_strcmp0 (devtype, "gadget")) + if (nm_streq0 (devtype, "gadget")) return NM_LINK_TYPE_ETHERNET; /* Distributed Switch Architecture switch chips */ - if (!g_strcmp0 (devtype, "dsa")) + if (nm_streq0 (devtype, "dsa")) return NM_LINK_TYPE_ETHERNET; } } @@ -1753,6 +1889,8 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data) #undef IFLA_VXLAN_MAX #define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6 +#define IFLA_VRF_TABLE 1 + /* older kernel header might not contain 'struct ifla_vxlan_port_range'. * Redefine it. */ struct nm_ifla_vxlan_port_range { @@ -1847,6 +1985,33 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data) return obj; } +static NMPObject * +_parse_lnk_vrf (const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_VRF_TABLE] = { .type = NLA_U32 }, + }; + NMPlatformLnkVrf *props; + struct nlattr *tb[G_N_ELEMENTS (policy)]; + NMPObject *obj; + + if ( !info_data + || !nm_streq0 (kind, "vrf")) + return NULL; + + if (nla_parse_nested_arr (tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VRF, NULL); + + props = &obj->lnk_vrf; + + if (tb[IFLA_VRF_TABLE]) + props->table = nla_get_u32 (tb[IFLA_VRF_TABLE]); + + return obj; +} + /*****************************************************************************/ static gboolean @@ -2797,6 +2962,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_VLAN: lnk_data = _parse_lnk_vlan (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_VRF: + lnk_data = _parse_lnk_vrf (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_VXLAN: lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data); break; @@ -2978,6 +3146,12 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only) memcpy (&obj->ip4_address.address, nla_data (tb[IFA_LOCAL]), addr_len); if (tb[IFA_ADDRESS]) memcpy (&obj->ip4_address.peer_address, nla_data (tb[IFA_ADDRESS]), addr_len); + + _check_addr_or_return_null (tb, IFA_BROADCAST, addr_len); + obj->ip4_address.broadcast_address = tb[IFA_BROADCAST] + ? nla_get_u32 (tb[IFA_BROADCAST]) + : 0u; + obj->ip4_address.use_ip4_broadcast_address = TRUE; } else { /* For IPv6, IFA_ADDRESS is always present. * @@ -3689,13 +3863,13 @@ nla_put_failure: static gboolean _nl_msg_new_link_set_linkinfo (struct nl_msg *msg, NMLinkType link_type, - const char *veth_peer) + gconstpointer extra_data) { struct nlattr *info; + struct nlattr *data = NULL; const char *kind; nm_assert (msg); - nm_assert (!!veth_peer == (link_type == NM_LINK_TYPE_VETH)); kind = nm_link_type_to_rtnl_type_string (link_type); if (!kind) @@ -3706,9 +3880,89 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg, NLA_PUT_STRING (msg, IFLA_INFO_KIND, kind); - if (veth_peer) { + switch (link_type) { + case NM_LINK_TYPE_VLAN: { + const NMPlatformLnkVlan *props = extra_data; + + nm_assert (extra_data); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U16 (msg, IFLA_VLAN_ID, props->id); + + { + struct ifla_vlan_flags flags = { + .flags = props->flags & NM_VLAN_FLAGS_ALL, + .mask = NM_VLAN_FLAGS_ALL, + }; + + NLA_PUT (msg, IFLA_VLAN_FLAGS, sizeof (flags), &flags); + } + break; + } + case NM_LINK_TYPE_VRF: { + const NMPlatformLnkVrf *props = extra_data; + + nm_assert (extra_data); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32 (msg, IFLA_VRF_TABLE, props->table); + break; + } + case NM_LINK_TYPE_VXLAN: { + const NMPlatformLnkVxlan *props = extra_data; + + nm_assert (extra_data); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32 (msg, IFLA_VXLAN_ID, props->id); + + if (props->group) + NLA_PUT (msg, IFLA_VXLAN_GROUP, sizeof (props->group), &props->group); + else if (!IN6_IS_ADDR_UNSPECIFIED (&props->group6)) + NLA_PUT (msg, IFLA_VXLAN_GROUP6, sizeof (props->group6), &props->group6); + + if (props->local) + NLA_PUT (msg, IFLA_VXLAN_LOCAL, sizeof (props->local), &props->local); + else if (!IN6_IS_ADDR_UNSPECIFIED (&props->local6)) + NLA_PUT (msg, IFLA_VXLAN_LOCAL6, sizeof (props->local6), &props->local6); + + if (props->parent_ifindex >= 0) + NLA_PUT_U32 (msg, IFLA_VXLAN_LINK, props->parent_ifindex); + + if ( props->src_port_min + || props->src_port_max) { + struct nm_ifla_vxlan_port_range port_range = { + .low = htons (props->src_port_min), + .high = htons (props->src_port_max), + }; + + NLA_PUT (msg, IFLA_VXLAN_PORT_RANGE, sizeof (port_range), &port_range); + } + + NLA_PUT_U16 (msg, IFLA_VXLAN_PORT, htons (props->dst_port)); + NLA_PUT_U8 (msg, IFLA_VXLAN_TOS, props->tos); + NLA_PUT_U8 (msg, IFLA_VXLAN_TTL, props->ttl); + NLA_PUT_U32 (msg, IFLA_VXLAN_AGEING, props->ageing); + NLA_PUT_U32 (msg, IFLA_VXLAN_LIMIT, props->limit); + NLA_PUT_U8 (msg, IFLA_VXLAN_LEARNING, !!props->learning); + NLA_PUT_U8 (msg, IFLA_VXLAN_PROXY, !!props->proxy); + NLA_PUT_U8 (msg, IFLA_VXLAN_RSC, !!props->rsc); + NLA_PUT_U8 (msg, IFLA_VXLAN_L2MISS, !!props->l2miss); + NLA_PUT_U8 (msg, IFLA_VXLAN_L3MISS, !!props->l3miss); + break; + } + case NM_LINK_TYPE_VETH: { + const char *veth_peer = extra_data; const struct ifinfomsg ifi = { }; - struct nlattr *data, *info_peer; + struct nlattr *info_peer; + + nm_assert (veth_peer); if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) goto nla_put_failure; @@ -3718,8 +3972,174 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg, goto nla_put_failure; NLA_PUT_STRING (msg, IFLA_IFNAME, veth_peer); nla_nest_end (msg, info_peer); - nla_nest_end (msg, data); + break; + } + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: { + const NMPlatformLnkGre *props = extra_data; + + nm_assert (props); + nm_assert (props->is_tap == (link_type == NM_LINK_TYPE_GRETAP)); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (msg, IFLA_GRE_LINK, props->parent_ifindex); + NLA_PUT_U32 (msg, IFLA_GRE_LOCAL, props->local); + NLA_PUT_U32 (msg, IFLA_GRE_REMOTE, props->remote); + NLA_PUT_U8 (msg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8 (msg, IFLA_GRE_TOS, props->tos); + NLA_PUT_U8 (msg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); + NLA_PUT_U32 (msg, IFLA_GRE_IKEY, htonl (props->input_key)); + NLA_PUT_U32 (msg, IFLA_GRE_OKEY, htonl (props->output_key)); + NLA_PUT_U16 (msg, IFLA_GRE_IFLAGS, htons (props->input_flags)); + NLA_PUT_U16 (msg, IFLA_GRE_OFLAGS, htons (props->output_flags)); + break; + } + case NM_LINK_TYPE_SIT: { + const NMPlatformLnkSit *props = extra_data; + + nm_assert (props); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32 (msg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32 (msg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (msg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8 (msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + break; + } + case NM_LINK_TYPE_IP6TNL: { + const NMPlatformLnkIp6Tnl *props = extra_data; + guint32 flowinfo; + + nm_assert (props); + nm_assert (!props->is_gre); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); + + if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) + NLA_PUT (msg, IFLA_IPTUN_LOCAL, sizeof (props->local), &props->local); + if (!IN6_IS_ADDR_UNSPECIFIED (&props->remote)) + NLA_PUT (msg, IFLA_IPTUN_REMOTE, sizeof (props->remote), &props->remote); + + NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (msg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) + & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32 (msg, IFLA_IPTUN_FLOWINFO, htonl (flowinfo)); + NLA_PUT_U8 (msg, IFLA_IPTUN_PROTO, props->proto); + NLA_PUT_U32 (msg, IFLA_IPTUN_FLAGS, props->flags); + break; + } + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: { + const NMPlatformLnkIp6Tnl *props = extra_data; + guint32 flowinfo; + + nm_assert (props); + nm_assert (props->is_gre); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (msg, IFLA_GRE_LINK, props->parent_ifindex); + + NLA_PUT_U32 (msg, IFLA_GRE_IKEY, htonl (props->input_key)); + NLA_PUT_U32 (msg, IFLA_GRE_OKEY, htonl (props->output_key)); + NLA_PUT_U16 (msg, IFLA_GRE_IFLAGS, htons (props->input_flags)); + NLA_PUT_U16 (msg, IFLA_GRE_OFLAGS, htons (props->output_flags)); + + if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) + NLA_PUT (msg, IFLA_GRE_LOCAL, sizeof (props->local), &props->local); + if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) + NLA_PUT (msg, IFLA_GRE_REMOTE, sizeof (props->remote), &props->remote); + + NLA_PUT_U8 (msg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8 (msg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) + & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32 (msg, IFLA_GRE_FLOWINFO, htonl (flowinfo)); + NLA_PUT_U32 (msg, IFLA_GRE_FLAGS, props->flags); + break; + } + case NM_LINK_TYPE_IPIP: { + const NMPlatformLnkIpIp *props = extra_data; + + nm_assert (props); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32 (msg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32 (msg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (msg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8 (msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + break; + } + case NM_LINK_TYPE_MACSEC: { + const NMPlatformLnkMacsec *props = extra_data; + + nm_assert (props); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->icv_length) + NLA_PUT_U8 (msg, IFLA_MACSEC_ICV_LEN, 16); + if (props->cipher_suite) + NLA_PUT_U64 (msg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); + if (props->replay_protect) + NLA_PUT_U32 (msg, IFLA_MACSEC_WINDOW, props->window); + + NLA_PUT_U64 (msg, IFLA_MACSEC_SCI, htobe64 (props->sci)); + NLA_PUT_U8 (msg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); + NLA_PUT_U8 (msg, IFLA_MACSEC_ENCRYPT, props->encrypt); + NLA_PUT_U8 (msg, IFLA_MACSEC_PROTECT, props->protect); + NLA_PUT_U8 (msg, IFLA_MACSEC_INC_SCI, props->include_sci); + NLA_PUT_U8 (msg, IFLA_MACSEC_ES, props->es); + NLA_PUT_U8 (msg, IFLA_MACSEC_SCB, props->scb); + NLA_PUT_U8 (msg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); + NLA_PUT_U8 (msg, IFLA_MACSEC_VALIDATION, props->validation); + break; + }; + case NM_LINK_TYPE_MACVTAP: + case NM_LINK_TYPE_MACVLAN: { + const NMPlatformLnkMacvlan *props = extra_data; + + nm_assert (props); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32 (msg, IFLA_MACVLAN_MODE, props->mode); + NLA_PUT_U16 (msg, IFLA_MACVLAN_FLAGS, props->no_promisc ? MACVLAN_FLAG_NOPROMISC : 0); + break; } + default: + nm_assert (!extra_data); + break; + } + + if (data) + nla_nest_end (msg, data); nla_nest_end (msg, info); @@ -3743,6 +4163,11 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg, guint i; gboolean has_any_vlan_properties = FALSE; + G_STATIC_ASSERT (NM_VLAN_FLAG_REORDER_HEADERS == (guint32) VLAN_FLAG_REORDER_HDR); + G_STATIC_ASSERT (NM_VLAN_FLAG_GVRP == (guint32) VLAN_FLAG_GVRP); + G_STATIC_ASSERT (NM_VLAN_FLAG_LOOSE_BINDING == (guint32) VLAN_FLAG_LOOSE_BINDING); + G_STATIC_ASSERT (NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); + #define VLAN_XGRESS_PRIO_VALID(from) (((from) & ~(guint32) 0x07) == 0) nm_assert (msg); @@ -3892,6 +4317,7 @@ _nl_msg_new_address (int nlmsg_type, int scope, guint32 lifetime, guint32 preferred, + in_addr_t ip4_broadcast_address, const char *label) { nm_auto_nlmsg struct nl_msg *msg = NULL; @@ -3935,16 +4361,8 @@ _nl_msg_new_address (int nlmsg_type, if (label && label[0]) NLA_PUT_STRING (msg, IFA_LABEL, label); - if ( family == AF_INET - && nlmsg_type != RTM_DELADDR - && plen < 31 /* RFC 3021 */ - && address - && *((in_addr_t *) address) != 0) { - in_addr_t broadcast; - - broadcast = *((in_addr_t *) address) | ~_nm_utils_ip4_prefix_to_netmask (plen); - NLA_PUT (msg, IFA_BROADCAST, addr_len, &broadcast); - } + if (ip4_broadcast_address != 0) + NLA_PUT (msg, IFA_BROADCAST, sizeof (in_addr_t), &ip4_broadcast_address); if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { @@ -4236,7 +4654,7 @@ _nl_msg_new_qdisc (int nlmsg_type, if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS))) goto nla_put_failure; - if (strcmp (qdisc->kind, "fq_codel") == 0) { + if (nm_streq (qdisc->kind, "fq_codel")) { if (qdisc->fq_codel.limit) NLA_PUT_U32 (msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit); if (qdisc->fq_codel.flows) @@ -4909,7 +5327,8 @@ refresh_all_type_get_info (RefreshAllType refresh_all_type) return &infos[refresh_all_type]; } -_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_type_to_refresh_all_type, DelayedActionType, RefreshAllType, +static +NM_UTILS_LOOKUP_DEFINE (delayed_action_type_to_refresh_all_type, DelayedActionType, RefreshAllType, NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (0), NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, REFRESH_ALL_TYPE_LINKS), NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, REFRESH_ALL_TYPE_IP4_ADDRESSES), @@ -4992,7 +5411,8 @@ delayed_action_refresh_from_needle_object (const NMPObject *obj_needle) return delayed_action_type_from_refresh_all_type (refresh_all_type_from_needle_object (obj_needle)); } -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (delayed_action_to_string, DelayedActionType, +static +NM_UTILS_LOOKUP_STR_DEFINE (delayed_action_to_string, DelayedActionType, NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, "refresh-all-links"), NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, "refresh-all-ip4-addresses"), @@ -5031,14 +5451,14 @@ delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data data = user_data; if (data) { - gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_ns (); + gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_nsec (); char b[255]; nm_utils_strbuf_append (&buf, &buf_size, " (seq %u, timeout in %s%"G_GINT64_FORMAT".%09"G_GINT64_FORMAT", response-type %d%s%s)", data->seq_number, timeout < 0 ? "-" : "", - (timeout < 0 ? -timeout : timeout) / NM_UTILS_NS_PER_SECOND, - (timeout < 0 ? -timeout : timeout) % NM_UTILS_NS_PER_SECOND, + (timeout < 0 ? -timeout : timeout) / NM_UTILS_NSEC_PER_SEC, + (timeout < 0 ? -timeout : timeout) % NM_UTILS_NSEC_PER_SEC, (int) data->response_type, data->seq_result ? ", " : "", data->seq_result ? wait_for_nl_response_to_string (data->seq_result, NULL, b, sizeof (b)) : ""); @@ -5140,7 +5560,7 @@ delayed_action_wait_for_nl_response_complete_check (NMPlatform *platform, 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_ns ())) >= data->timeout_abs_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. */ delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT); } else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) @@ -5360,7 +5780,7 @@ delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform, { DelayedActionWaitForNlResponseData data = { .seq_number = seq_number, - .timeout_abs_ns = nm_utils_get_monotonic_timestamp_ns () + (200 * (NM_UTILS_NS_PER_SECOND / 1000)), + .timeout_abs_ns = nm_utils_get_monotonic_timestamp_nsec () + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)), .out_seq_result = out_seq_result, .out_errmsg = out_errmsg, .response_type = response_type, @@ -6491,11 +6911,12 @@ out: static int link_add (NMPlatform *platform, - const char *name, NMLinkType type, - const char *veth_peer, + const char *name, + int parent, const void *address, size_t address_len, + gconstpointer extra_data, const NMPlatformLink **out_link) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; @@ -6519,10 +6940,13 @@ link_add (NMPlatform *platform, if (!nlmsg) return -NME_UNSPEC; + if (parent > 0) + NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); + if (address && address_len) NLA_PUT (nlmsg, IFLA_ADDRESS, address_len, address); - if (!_nl_msg_new_link_set_linkinfo (nlmsg, type, veth_peer)) + if (!_nl_msg_new_link_set_linkinfo (nlmsg, type, extra_data)) return -NME_UNSPEC; return do_add_link_with_lookup (platform, type, name, nlmsg, out_link); @@ -7158,385 +7582,6 @@ link_get_dev_id (NMPlatform *platform, int ifindex) } static gboolean -vlan_add (NMPlatform *platform, - const char *name, - int parent, - int vlan_id, - guint32 vlan_flags, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - G_STATIC_ASSERT (NM_VLAN_FLAG_REORDER_HEADERS == (guint32) VLAN_FLAG_REORDER_HDR); - G_STATIC_ASSERT (NM_VLAN_FLAG_GVRP == (guint32) VLAN_FLAG_GVRP); - G_STATIC_ASSERT (NM_VLAN_FLAG_LOOSE_BINDING == (guint32) VLAN_FLAG_LOOSE_BINDING); - G_STATIC_ASSERT (NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); - - vlan_flags &= (guint32) NM_VLAN_FLAGS_ALL; - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); - - if (!_nl_msg_new_link_set_linkinfo_vlan (nlmsg, - vlan_id, - NM_VLAN_FLAGS_ALL, - vlan_flags, - NULL, - 0, - NULL, - 0)) - return FALSE; - - return (do_add_link_with_lookup (platform, NM_LINK_TYPE_VLAN, name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_gre_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkGre *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->is_tap ? "gretap" : "gre"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (nlmsg, IFLA_GRE_LINK, props->parent_ifindex); - NLA_PUT_U32 (nlmsg, IFLA_GRE_LOCAL, props->local); - NLA_PUT_U32 (nlmsg, IFLA_GRE_REMOTE, props->remote); - NLA_PUT_U8 (nlmsg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8 (nlmsg, IFLA_GRE_TOS, props->tos); - NLA_PUT_U8 (nlmsg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); - NLA_PUT_U32 (nlmsg, IFLA_GRE_IKEY, htonl (props->input_key)); - NLA_PUT_U32 (nlmsg, IFLA_GRE_OKEY, htonl (props->output_key)); - NLA_PUT_U16 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); - NLA_PUT_U16 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, - props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, - name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_ip6tnl_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - guint32 flowinfo; - - g_return_val_if_fail (!props->is_gre, FALSE); - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "ip6tnl"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); - - if (memcmp (&props->local, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_IPTUN_LOCAL, sizeof (props->local), &props->local); - if (memcmp (&props->remote, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_IPTUN_REMOTE, sizeof (props->remote), &props->remote); - - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) - & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_FLOWINFO, htonl (flowinfo)); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PROTO, props->proto); - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_FLAGS, props->flags); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, NM_LINK_TYPE_IP6TNL, name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_ip6gre_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - guint32 flowinfo; - - g_return_val_if_fail (props->is_gre, FALSE); - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->is_tap ? "ip6gretap" : "ip6gre"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (nlmsg, IFLA_GRE_LINK, props->parent_ifindex); - - NLA_PUT_U32 (nlmsg, IFLA_GRE_IKEY, htonl (props->input_key)); - NLA_PUT_U32 (nlmsg, IFLA_GRE_OKEY, htonl (props->output_key)); - NLA_PUT_U16 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); - NLA_PUT_U16 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); - - if (memcmp (&props->local, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_GRE_LOCAL, sizeof (props->local), &props->local); - if (memcmp (&props->remote, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_GRE_REMOTE, sizeof (props->remote), &props->remote); - - NLA_PUT_U8 (nlmsg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8 (nlmsg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) - & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32 (nlmsg, IFLA_GRE_FLOWINFO, htonl (flowinfo)); - NLA_PUT_U32 (nlmsg, IFLA_GRE_FLAGS, props->flags); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, - props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, - name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_ipip_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "ipip"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, NM_LINK_TYPE_IPIP, name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_macsec_add (NMPlatform *platform, - const char *name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "macsec"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->icv_length) - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ICV_LEN, 16); - if (props->cipher_suite) - NLA_PUT_U64 (nlmsg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); - if (props->replay_protect) - NLA_PUT_U32 (nlmsg, IFLA_MACSEC_WINDOW, props->window); - - NLA_PUT_U64 (nlmsg, IFLA_MACSEC_SCI, htobe64 (props->sci)); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ENCRYPT, props->encrypt); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_PROTECT, props->protect); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_INC_SCI, props->include_sci); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ES, props->es); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_SCB, props->scb); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); - NLA_PUT_U8 (nlmsg, IFLA_MACSEC_VALIDATION, props->validation); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, - NM_LINK_TYPE_MACSEC, - name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_macvlan_add (NMPlatform *platform, - const char *name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->tap ? "macvtap" : "macvlan"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32 (nlmsg, IFLA_MACVLAN_MODE, props->mode); - NLA_PUT_U16 (nlmsg, IFLA_MACVLAN_FLAGS, props->no_promisc ? MACVLAN_FLAG_NOPROMISC : 0); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, - props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN, - name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_sit_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkSit *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "sit"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32 (nlmsg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, NM_LINK_TYPE_SIT, name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean link_tun_add (NMPlatform *platform, const char *name, const NMPlatformLnkTun *props, @@ -7592,107 +7637,6 @@ link_tun_add (NMPlatform *platform, return TRUE; } -static gboolean -link_vxlan_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - struct nlattr *data; - struct nm_ifla_vxlan_port_range port_range; - - g_return_val_if_fail (props, FALSE); - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "vxlan"); - - if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32 (nlmsg, IFLA_VXLAN_ID, props->id); - - if (props->group) - NLA_PUT (nlmsg, IFLA_VXLAN_GROUP, sizeof (props->group), &props->group); - else if (memcmp (&props->group6, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_VXLAN_GROUP6, sizeof (props->group6), &props->group6); - - if (props->local) - NLA_PUT (nlmsg, IFLA_VXLAN_LOCAL, sizeof (props->local), &props->local); - else if (memcmp (&props->local6, &in6addr_any, sizeof (in6addr_any))) - NLA_PUT (nlmsg, IFLA_VXLAN_LOCAL6, sizeof (props->local6), &props->local6); - - if (props->parent_ifindex >= 0) - NLA_PUT_U32 (nlmsg, IFLA_VXLAN_LINK, props->parent_ifindex); - - if (props->src_port_min || props->src_port_max) { - port_range.low = htons (props->src_port_min); - port_range.high = htons (props->src_port_max); - NLA_PUT (nlmsg, IFLA_VXLAN_PORT_RANGE, sizeof (port_range), &port_range); - } - - NLA_PUT_U16 (nlmsg, IFLA_VXLAN_PORT, htons (props->dst_port)); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_TOS, props->tos); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_TTL, props->ttl); - NLA_PUT_U32 (nlmsg, IFLA_VXLAN_AGEING, props->ageing); - NLA_PUT_U32 (nlmsg, IFLA_VXLAN_LIMIT, props->limit); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_LEARNING, !!props->learning); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_PROXY, !!props->proxy); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_RSC, !!props->rsc); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_L2MISS, !!props->l2miss); - NLA_PUT_U8 (nlmsg, IFLA_VXLAN_L3MISS, !!props->l3miss); - - nla_nest_end (nlmsg, data); - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, NM_LINK_TYPE_VXLAN, name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - -static gboolean -link_6lowpan_add (NMPlatform *platform, - const char *name, - int parent, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *info; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); - - if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "lowpan"); - - nla_nest_end (nlmsg, info); - - return (do_add_link_with_lookup (platform, - NM_LINK_TYPE_6LOWPAN, - name, nlmsg, out_link) >= 0); -nla_put_failure: - g_return_val_if_reached (FALSE); -} - - static void _vlan_change_vlan_qos_mapping_create (gboolean is_ingress_map, gboolean reset_all, @@ -8196,6 +8140,7 @@ ip4_address_add (NMPlatform *platform, in_addr_t addr, guint8 plen, in_addr_t peer_addr, + in_addr_t broadcast_address, guint32 lifetime, guint32 preferred, guint32 flags, @@ -8215,6 +8160,7 @@ ip4_address_add (NMPlatform *platform, nm_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE, lifetime, preferred, + broadcast_address, label); nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, addr, plen, peer_addr); @@ -8245,6 +8191,7 @@ ip6_address_add (NMPlatform *platform, RT_SCOPE_UNIVERSE, lifetime, preferred, + 0, NULL); nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &addr); @@ -8268,6 +8215,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 pl RT_SCOPE_NOWHERE, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, + 0, NULL); if (!nlmsg) g_return_val_if_reached (FALSE); @@ -8293,6 +8241,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui RT_SCOPE_NOWHERE, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, + 0, NULL); if (!nlmsg) g_return_val_if_reached (FALSE); @@ -8402,7 +8351,7 @@ ip_route_get (NMPlatform *platform, .r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */, }; - g_clear_pointer (&route, nmp_object_unref); + nm_clear_pointer (&route, nmp_object_unref); if (!_nl_addattr_l (&req.n, sizeof (req), RTA_DST, address, addr_len)) nm_assert_not_reached (); @@ -8576,12 +8525,8 @@ tfilter_add (NMPlatform *platform, /*****************************************************************************/ -#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) -#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) -#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP)) - static gboolean -event_handler (GIOChannel *channel, +event_handler (int fd, GIOCondition io_condition, gpointer user_data) { @@ -8609,7 +8554,7 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events) nm_auto_free unsigned char *buf = NULL; continue_reading: - g_clear_pointer (&buf, free); + nm_clear_pointer (&buf, free); n = nl_recv (sk, &nla, &buf, &creds, &creds_has); if (n <= 0) { @@ -8800,7 +8745,7 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks) int r; struct pollfd pfd; gboolean any = FALSE; - int timeout_ms; + int timeout_msec; struct { guint32 seq_number; gint64 timeout_abs_ns; @@ -8881,12 +8826,12 @@ after_read: _LOGT ("netlink: read: wait for ACK for sequence number %u...", next.seq_number); - timeout_ms = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NS_PER_SECOND / 1000); + timeout_msec = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NSEC_PER_SEC / 1000); memset (&pfd, 0, sizeof (pfd)); pfd.fd = nl_socket_get_fd (priv->nlh); pfd.events = POLLIN; - r = poll (&pfd, 1, MAX (1, timeout_ms)); + r = poll (&pfd, 1, MAX (1, timeout_msec)); if (r == 0) { /* timeout and there is nothing to read. */ @@ -9052,14 +8997,13 @@ constructed (GObject *_object) { NMPlatform *platform = NM_PLATFORM (_object); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - int channel_flags; - gboolean status; int nle; + int fd; nm_assert (!platform->_netns || platform->_netns == nmp_netns_get_current ()); if (nm_platform_get_use_udev (platform)) { - priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + priv->udev_client = nm_udev_client_new (NM_MAKE_STRV ("net"), handle_udev_event, platform); } @@ -9123,18 +9067,18 @@ constructed (GObject *_object) RTNLGRP_TC, 0); g_assert (!nle); - _LOGD ("Netlink socket for events established: port=%u, fd=%d", nl_socket_get_local_port (priv->nlh), nl_socket_get_fd (priv->nlh)); - priv->event_channel = g_io_channel_unix_new (nl_socket_get_fd (priv->nlh)); - g_io_channel_set_encoding (priv->event_channel, NULL, NULL); + fd = nl_socket_get_fd (priv->nlh); + + _LOGD ("Netlink socket for events established: port=%u, fd=%d", nl_socket_get_local_port (priv->nlh), fd); - channel_flags = g_io_channel_get_flags (priv->event_channel); - status = g_io_channel_set_flags (priv->event_channel, - channel_flags | G_IO_FLAG_NONBLOCK, NULL); - g_assert (status); - priv->event_id = g_io_add_watch (priv->event_channel, - (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), - event_handler, platform); + priv->event_source = nm_g_unix_fd_source_new (fd, + G_IO_IN | G_IO_NVAL | G_IO_PRI | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + event_handler, + platform, + NULL); + g_source_attach (priv->event_source, NULL); /* complete construction of the GObject instance before populating the cache. */ G_OBJECT_CLASS (nm_linux_platform_parent_class)->constructed (_object); @@ -9227,8 +9171,8 @@ finalize (GObject *object) nl_socket_free (priv->genl); - g_source_remove (priv->event_id); - g_io_channel_unref (priv->event_channel); + nm_clear_g_source_inst (&priv->event_source); + nl_socket_free (priv->nlh); if (priv->sysctl_get_prev_values) { @@ -9294,10 +9238,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_can_assume = link_can_assume; - platform_class->vlan_add = vlan_add; platform_class->link_vlan_change = link_vlan_change; platform_class->link_wireguard_change = link_wireguard_change; - platform_class->link_vxlan_add = link_vxlan_add; platform_class->infiniband_partition_add = infiniband_partition_add; platform_class->infiniband_partition_delete = infiniband_partition_delete; @@ -9325,15 +9267,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->wpan_set_short_addr = wpan_set_short_addr; platform_class->wpan_set_channel = wpan_set_channel; - platform_class->link_gre_add = link_gre_add; - platform_class->link_ip6tnl_add = link_ip6tnl_add; - platform_class->link_ip6gre_add = link_ip6gre_add; - platform_class->link_macsec_add = link_macsec_add; - platform_class->link_macvlan_add = link_macvlan_add; - platform_class->link_ipip_add = link_ipip_add; - platform_class->link_sit_add = link_sit_add; platform_class->link_tun_add = link_tun_add; - platform_class->link_6lowpan_add = link_6lowpan_add; platform_class->object_delete = object_delete; platform_class->ip4_address_add = ip4_address_add; |