diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/nm-fake-platform.c | 178 | ||||
| -rw-r--r-- | src/platform/nm-linux-platform.c | 1170 | ||||
| -rw-r--r-- | src/platform/nm-platform-utils.c | 3 | ||||
| -rw-r--r-- | src/platform/nm-platform.c | 813 | ||||
| -rw-r--r-- | src/platform/nm-platform.h | 340 | ||||
| -rw-r--r-- | src/platform/nmp-netns.c | 3 | ||||
| -rw-r--r-- | src/platform/nmp-object.c | 28 | ||||
| -rw-r--r-- | src/platform/nmp-object.h | 8 | ||||
| -rw-r--r-- | src/platform/tests/meson.build | 2 | ||||
| -rw-r--r-- | src/platform/tests/test-cleanup.c | 3 | ||||
| -rw-r--r-- | src/platform/tests/test-common.c | 124 | ||||
| -rw-r--r-- | src/platform/tests/test-common.h | 23 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 33 | ||||
| -rw-r--r-- | src/platform/tests/test-route.c | 11 | ||||
| -rw-r--r-- | src/platform/wifi/nm-wifi-utils-nl80211.c | 2 |
15 files changed, 1315 insertions, 1426 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 6aae808a..4a81dc49 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -46,7 +46,7 @@ struct _NMFakePlatformClass { G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM) -#define NM_FAKE_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMFakePlatform, NM_IS_FAKE_PLATFORM) +#define NM_FAKE_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMFakePlatform, NM_IS_FAKE_PLATFORM, NMPlatform) /*****************************************************************************/ @@ -126,7 +126,7 @@ static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in static gboolean sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); ASSERT_SYSCTL_ARGS (pathid, dirfd, path); @@ -138,7 +138,7 @@ sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *pat static char * sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *path) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); const char *v; ASSERT_SYSCTL_ARGS (pathid, dirfd, path); @@ -155,7 +155,7 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat static NMFakePlatformLink * link_get (NMPlatform *platform, int ifindex) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformLink *device; int idx; @@ -223,7 +223,7 @@ link_add_pre (NMPlatform *platform, const void *address, size_t address_len) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformLink *device; int ifindex; NMPObject *o; @@ -276,11 +276,12 @@ link_add_pre (NMPlatform *platform, 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) { NMFakePlatformLink *device; @@ -291,14 +292,52 @@ link_add (NMPlatform *platform, nm_auto_nmpobj const NMPObject *obj_new_veth = NULL; NMPCacheOpsType cache_op; NMPCacheOpsType cache_op_veth = NMP_CACHE_OPS_UNCHANGED; + const char *veth_peer = NULL; + NMPObject *dev_obj; + NMPObject *dev_lnk = NULL; device = link_add_pre (platform, name, type, address, address_len); - if (veth_peer) { - g_assert (type == NM_LINK_TYPE_VETH); + g_assert (device); + + dev_obj = (NMPObject *) device->obj; + + if (parent > 0) + dev_obj->link.parent = parent; + else + g_assert (parent == 0); + + g_assert ((parent != 0) == NM_IN_SET (type, NM_LINK_TYPE_VLAN)); + + switch (type) { + case NM_LINK_TYPE_VETH: + veth_peer = extra_data; + g_assert (veth_peer); device_veth = link_add_pre (platform, veth_peer, type, NULL, 0); - } else - g_assert (type != NM_LINK_TYPE_VETH); + break; + case NM_LINK_TYPE_VLAN: { + const NMPlatformLnkVlan *props = extra_data; + + g_assert (props); + + dev_lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, props); + break; + } + case NM_LINK_TYPE_VXLAN: { + const NMPlatformLnkVxlan *props = extra_data; + + g_assert (props); + + dev_lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, props); + break; + } + default: + g_assert (!extra_data); + break; + } + + if (dev_lnk) + dev_obj->_link.netlink.lnk = dev_lnk; link_add_prepare (platform, device, (NMPObject *) device->obj); cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform), @@ -381,7 +420,7 @@ link_delete (NMPlatform *platform, int ifindex) return FALSE; obj_old = g_steal_pointer (&device->obj); - g_clear_pointer (&device->udi, g_free); + nm_clear_g_free (&device->udi); cache_op = nmp_cache_remove (nm_platform_get_cache (platform), obj_old, @@ -710,45 +749,6 @@ link_release (NMPlatform *platform, int master_idx, int slave_idx) return TRUE; } -struct vlan_add_data { - guint32 vlan_flags; - int parent; - int vlan_id; -}; - -static void -_vlan_add_prepare (NMPlatform *platform, - NMFakePlatformLink *device, - gconstpointer user_data) -{ - const struct vlan_add_data *d = user_data; - NMPObject *obj_tmp; - NMPObject *lnk; - - obj_tmp = (NMPObject *) device->obj; - - lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL); - lnk->lnk_vlan.id = d->vlan_id; - lnk->lnk_vlan.flags = d->vlan_flags; - - obj_tmp->link.parent = d->parent; - obj_tmp->_link.netlink.lnk = lnk; -} - -static gboolean -vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags, const NMPlatformLink **out_link) -{ - const struct vlan_add_data d = { - .parent = parent, - .vlan_id = vlan_id, - .vlan_flags = vlan_flags, - }; - - link_add_one (platform, name, NM_LINK_TYPE_VLAN, - _vlan_add_prepare, &d, out_link); - return TRUE; -} - static gboolean link_vlan_change (NMPlatform *platform, int ifindex, @@ -764,35 +764,6 @@ link_vlan_change (NMPlatform *platform, return FALSE; } -static void -_vxlan_add_prepare (NMPlatform *platform, - NMFakePlatformLink *device, - gconstpointer user_data) -{ - const NMPlatformLnkVxlan *props = user_data; - NMPObject *obj_tmp; - NMPObject *lnk; - - obj_tmp = (NMPObject *) device->obj; - - lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL); - lnk->lnk_vxlan = *props; - - obj_tmp->link.parent = props->parent_ifindex; - obj_tmp->_link.netlink.lnk = lnk; -} - -static gboolean -link_vxlan_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link) -{ - link_add_one (platform, name, NM_LINK_TYPE_VXLAN, - _vxlan_add_prepare, props, out_link); - return TRUE; -} - struct infiniband_add_data { int parent; int p_key; @@ -967,6 +938,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, @@ -974,16 +946,19 @@ ip4_address_add (NMPlatform *platform, { NMPlatformIP4Address address; - memset (&address, 0, sizeof (address)); - address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; - address.ifindex = ifindex; - address.address = addr; - address.peer_address = peer_addr; - address.plen = plen; - address.timestamp = nm_utils_get_monotonic_timestamp_s (); - address.lifetime = lifetime; - address.preferred = preferred; - address.n_ifa_flags = flags; + address = (NMPlatformIP4Address) { + .addr_source = NM_IP_CONFIG_SOURCE_KERNEL, + .ifindex = ifindex, + .address = addr, + .plen = plen, + .peer_address = peer_addr, + .broadcast_address = broadcast_address, + .use_ip4_broadcast_address = TRUE, + .timestamp = nm_utils_get_monotonic_timestamp_sec (), + .lifetime = lifetime, + .preferred = preferred, + .n_ifa_flags = flags, + }; if (label) g_strlcpy (address.label, label, sizeof (address.label)); @@ -1008,7 +983,7 @@ ip6_address_add (NMPlatform *platform, address.address = addr; address.peer_address = (IN6_IS_ADDR_UNSPECIFIED (&peer_addr) || IN6_ARE_ADDR_EQUAL (&addr, &peer_addr)) ? in6addr_any : peer_addr; address.plen = plen; - address.timestamp = nm_utils_get_monotonic_timestamp_s (); + address.timestamp = nm_utils_get_monotonic_timestamp_sec (); address.lifetime = lifetime; address.preferred = preferred; address.n_ifa_flags = flags; @@ -1262,10 +1237,10 @@ ip_route_add (NMPlatform *platform, if (addr_family == AF_INET) { nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable", - r->ifindex, nm_utils_inet4_ntop (r4->network, sbuf), r->plen, r->metric); + r->ifindex, _nm_utils_inet4_ntop (r4->network, sbuf), r->plen, r->metric); } else { nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable", - r->ifindex, nm_utils_inet6_ntop (&r6->network, sbuf), r->plen, r->metric); + r->ifindex, _nm_utils_inet6_ntop (&r6->network, sbuf), r->plen, r->metric); } return -NME_UNSPEC; } @@ -1354,19 +1329,16 @@ nm_fake_platform_setup (void) nm_platform_setup (platform); - /* add loopback interface */ - link_add (platform, "lo", NM_LINK_TYPE_LOOPBACK, NULL, NULL, 0, NULL); - - /* add some ethernets */ - link_add (platform, "eth0", NM_LINK_TYPE_ETHERNET, NULL, NULL, 0, NULL); - link_add (platform, "eth1", NM_LINK_TYPE_ETHERNET, NULL, NULL, 0, NULL); - link_add (platform, "eth2", NM_LINK_TYPE_ETHERNET, NULL, NULL, 0, NULL); + link_add (platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, NULL, NULL); + link_add (platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, NULL, NULL); + link_add (platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, NULL, NULL); + link_add (platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, NULL, NULL); } static void finalize (GObject *object) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) object); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object); int i; g_hash_table_unref (priv->options); @@ -1374,7 +1346,7 @@ finalize (GObject *object) NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i); g_free (device->udi); - g_clear_pointer (&device->obj, nmp_object_unref); + nm_clear_pointer (&device->obj, nmp_object_unref); } g_array_unref (priv->links); @@ -1418,9 +1390,7 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->link_enslave = link_enslave; platform_class->link_release = link_release; - platform_class->vlan_add = vlan_add; platform_class->link_vlan_change = link_vlan_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; 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; diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index b55fbd66..98884cd7 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -262,7 +262,8 @@ out: * ethtool *****************************************************************************/ -NM_UTILS_ENUM2STR_DEFINE_STATIC (_ethtool_cmd_to_string, guint32, +static +NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32, NM_UTILS_ENUM2STR (ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"), NM_UTILS_ENUM2STR (ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"), NM_UTILS_ENUM2STR (ETHTOOL_GLINK, "ETHTOOL_GLINK"), diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 6795dde7..9bbc3745 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -298,7 +298,8 @@ nm_platform_get_multi_idx (NMPlatform *self) /*****************************************************************************/ -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_nmp_nlm_flag_to_string_lookup, NMPNlmFlags, +static +NM_UTILS_LOOKUP_STR_DEFINE (_nmp_nlm_flag_to_string_lookup, NMPNlmFlags, NM_UTILS_LOOKUP_DEFAULT (NULL), NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_ADD, "add"), NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_CHANGE, "change"), @@ -1150,11 +1151,12 @@ _link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, c /** * nm_platform_link_add: * @self: platform instance - * @name: Interface name * @type: Interface type - * @veth_peer: For veths, the peer name + * @name: Interface name + * @parent: the IFLA_LINK parameter or 0. * @address: (allow-none): set the mac address of the link * @address_len: the length of the @address + * @extra_data: depending on @type, additional data. * @out_link: on success, the link object * * Add a software interface. If the interface already exists and is of type @@ -1167,66 +1169,104 @@ _link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, c * * Returns: the negative nm-error on failure. */ -static int +int nm_platform_link_add (NMPlatform *self, - 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) { int r; char addr_buf[NM_UTILS_HWADDR_LEN_MAX * 3]; + char parent_buf[64]; + char buf[512]; _CHECK_SELF (self, klass, -NME_BUG); g_return_val_if_fail (name, -NME_BUG); g_return_val_if_fail ((address != NULL) ^ (address_len == 0) , -NME_BUG); g_return_val_if_fail (address_len <= NM_UTILS_HWADDR_LEN_MAX, -NME_BUG); - g_return_val_if_fail ((!!veth_peer) == (type == NM_LINK_TYPE_VETH), -NME_BUG); + g_return_val_if_fail (parent >= 0, -NME_BUG); r = _link_add_check_existing (self, name, type, out_link); if (r < 0) return r; - _LOG2D ("link: adding link: %s (%d)" - "%s%s" /* address */ - "%s%s" /* veth peer */ + _LOG2D ("link: adding link: " + "%s " /* type */ + "\"%s\"" /* name */ + "%s%s" /* parent */ + "%s%s" /* address */ + "%s" /* extra_data */ "", nm_link_type_to_string (type), - (int) type, + name, + parent > 0 ? ", parent " : "", + parent > 0 ? nm_sprintf_buf (parent_buf, "%d", parent) : "", address ? ", address: " : "", address ? nm_utils_hwaddr_ntoa_buf (address, address_len, FALSE, addr_buf, sizeof (addr_buf)) : "", - veth_peer ? ", veth-peer: " : "", - veth_peer ?: ""); - - return klass->link_add (self, name, type, veth_peer, address, address_len, out_link); -} - -int -nm_platform_link_veth_add (NMPlatform *self, - const char *name, - const char *peer, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_VETH, peer, NULL, 0, out_link); -} - -/** - * nm_platform_link_dummy_add: - * @self: platform instance - * @name: New interface name - * @out_link: on success, the link object - * - * Create a software ethernet-like interface - */ -int -nm_platform_link_dummy_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_DUMMY, NULL, NULL, 0, out_link); + ({ + char *buf_p = buf; + gsize buf_len = sizeof (buf); + + buf[0] = '\0'; + + switch (type) { + case NM_LINK_TYPE_VLAN: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_vlan_to_string ((const NMPlatformLnkVlan *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_VRF: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_vrf_to_string ((const NMPlatformLnkVrf *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_VXLAN: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_vxlan_to_string ((const NMPlatformLnkVxlan *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_VETH: + nm_sprintf_buf (buf, ", veth-peer \"%s\"", (const char *) extra_data); + break; + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_gre_to_string ((const NMPlatformLnkGre *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_SIT: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_sit_to_string ((const NMPlatformLnkSit *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_IP6TNL: + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_ip6tnl_to_string ((const NMPlatformLnkIp6Tnl *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_IPIP: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_ipip_to_string ((const NMPlatformLnkIpIp *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_MACSEC: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_macsec_to_string ((const NMPlatformLnkMacsec *) extra_data, buf_p, buf_len); + break; + case NM_LINK_TYPE_MACVLAN: + case NM_LINK_TYPE_MACVTAP: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_macvlan_to_string ((const NMPlatformLnkMacvlan *) extra_data, buf_p, buf_len); + break; + default: + nm_assert (!extra_data); + break; + } + + buf; + })); + + return klass->link_add (self, type, name, parent, address, address_len, extra_data, out_link); } /** @@ -1283,7 +1323,7 @@ nm_platform_link_get_ifindex (NMPlatform *self, const char *name) } const char * -nm_platform_if_indextoname (NMPlatform *self, int ifindex, char *out_ifname/* of size IFNAMSIZ */) +nm_platform_if_indextoname (NMPlatform *self, int ifindex, char out_ifname[static 16 /* IFNAMSIZ */]) { _CHECK_SELF_NETNS (self, klass, netns, FALSE); @@ -1408,7 +1448,7 @@ nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanag gboolean nm_platform_link_is_software (NMPlatform *self, int ifindex) { - return (nm_platform_link_get_type (self, ifindex) & 0x10000); + return nm_link_type_is_software (nm_platform_link_get_type (self, ifindex)); } /** @@ -1422,7 +1462,7 @@ nm_platform_link_is_software (NMPlatform *self, int ifindex) gboolean nm_platform_link_supports_slaves (NMPlatform *self, int ifindex) { - return (nm_platform_link_get_type (self, ifindex) & 0x20000); + return nm_link_type_supports_slaves (nm_platform_link_get_type (self, ifindex)); } /** @@ -2193,7 +2233,7 @@ nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatfor return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); } -const NMPlatformLnkMacvtap * +const NMPlatformLnkMacvlan * nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVTAP, out_link); @@ -2217,6 +2257,12 @@ nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLi return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link); } +const NMPlatformLnkVrf * +nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VRF, out_link); +} + const NMPlatformLnkVxlan * nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -2231,7 +2277,8 @@ nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatf /*****************************************************************************/ -NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_flags_to_string, NMPlatformWireGuardChangeFlags, +static +NM_UTILS_FLAGS2STR_DEFINE (_wireguard_change_flags_to_string, NMPlatformWireGuardChangeFlags, NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE, "none"), NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS, "replace-peers"), NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY, "has-private-key"), @@ -2239,7 +2286,8 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_flags_to_string, NMPlatformW NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"), ); -NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_peer_flags_to_string, NMPlatformWireGuardChangePeerFlags, +static +NM_UTILS_FLAGS2STR_DEFINE (_wireguard_change_peer_flags_to_string, NMPlatformWireGuardChangePeerFlags, NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"), NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"), NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"), @@ -2250,14 +2298,6 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_peer_flags_to_string, NMPlat ); int -nm_platform_link_wireguard_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_WIREGUARD, NULL, NULL, 0, out_link); -} - -int nm_platform_link_wireguard_change (NMPlatform *self, int ifindex, const NMPlatformLnkWireGuard *lnk_wireguard, @@ -2316,128 +2356,6 @@ nm_platform_link_wireguard_change (NMPlatform *self, /*****************************************************************************/ /** - * nm_platform_link_bridge_add: - * @self: platform instance - * @name: New interface name - * @address: (allow-none): set the mac address of the new bridge - * @address_len: the length of the @address - * @out_link: on success, the link object - * - * Create a software bridge. - */ -int -nm_platform_link_bridge_add (NMPlatform *self, - const char *name, - const void *address, - size_t address_len, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_BRIDGE, NULL, address, address_len, out_link); -} - -/** - * nm_platform_link_bond_add: - * @self: platform instance - * @name: New interface name - * @out_link: on success, the link object - * - * Create a software bonding device. - */ -int -nm_platform_link_bond_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_BOND, NULL, NULL, 0, out_link); -} - -/** - * nm_platform_link_team_add: - * @self: platform instance - * @name: New interface name - * @out_link: on success, the link object - * - * Create a software teaming device. - */ -int -nm_platform_link_team_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add (self, name, NM_LINK_TYPE_TEAM, NULL, NULL, 0, out_link); -} - -/** - * nm_platform_link_vlan_add: - * @self: platform instance - * @name: New interface name - * @vlanid: VLAN identifier - * @vlanflags: VLAN flags from libnm - * @out_link: on success, the link object - * - * Create a software VLAN device. - */ -int -nm_platform_link_vlan_add (NMPlatform *self, - const char *name, - int parent, - int vlanid, - guint32 vlanflags, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (parent >= 0, -NME_BUG); - g_return_val_if_fail (vlanid >= 0, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_VLAN, out_link); - if (r < 0) - return r; - - _LOG2D ("link: adding link vlan parent %d vlanid %d vlanflags %x", - parent, vlanid, vlanflags); - - if (!klass->vlan_add (self, name, parent, vlanid, vlanflags, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_link_vxlan_add: - * @self: platform instance - * @name: New interface name - * @props: properties of the new link - * @out_link: on success, the link object - * - * Create a VXLAN device. - */ -int -nm_platform_link_vxlan_add (NMPlatform *self, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_VXLAN, out_link); - if (r < 0) - return r; - - _LOG2D ("link: adding link %s", nm_platform_lnk_vxlan_to_string (props, NULL, 0)); - - if (!klass->link_vxlan_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** * nm_platform_link_tun_add: * @self: platform instance * @name: new interface name @@ -2489,38 +2407,6 @@ nm_platform_link_tun_add (NMPlatform *self, return 0; } -/** - * nm_platform_6lowpan_add: - * @self: platform instance - * @parent: parent link - * @name: name of the new interface - * @out_link: on success, the link object - * - * Create a 6LoWPAN interface. - */ -int -nm_platform_link_6lowpan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_6LOWPAN, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link 6lowpan parent %u", parent); - - if (!klass->link_6lowpan_add (self, name, parent, out_link)) - return -NME_UNSPEC; - return 0; -} - gboolean nm_platform_link_6lowpan_get_properties (NMPlatform *self, int ifindex, int *out_parent) { @@ -2761,39 +2647,6 @@ nm_platform_link_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, i return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); } -/** - * nm_platform_link_gre_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create a software GRE device. - */ -int -nm_platform_link_gre_add (NMPlatform *self, - const char *name, - const NMPlatformLnkGre *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_gre_to_string (props, NULL, 0)); - - if (!klass->link_gre_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - static int _infiniband_add_add_or_delete (NMPlatform *self, int ifindex, @@ -2918,217 +2771,6 @@ nm_platform_link_infiniband_get_properties (NMPlatform *self, return TRUE; } -/** - * nm_platform_ip6tnl_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create an IPv6 tunnel. - */ -int -nm_platform_link_ip6tnl_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - g_return_val_if_fail (!props->is_gre, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_IP6TNL, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_ip6tnl_to_string (props, NULL, 0)); - - if (!klass->link_ip6tnl_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_ip6gre_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create an IPv6 GRE/GRETAP tunnel. - */ -int -nm_platform_link_ip6gre_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - g_return_val_if_fail (props->is_gre, -NME_BUG); - - r = _link_add_check_existing (self, - name, - props->is_tap - ? NM_LINK_TYPE_IP6GRETAP - : NM_LINK_TYPE_IP6GRE, - out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_ip6tnl_to_string (props, NULL, 0)); - - if (!klass->link_ip6gre_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_ipip_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create an IPIP tunnel. - */ -int -nm_platform_link_ipip_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_IPIP, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_ipip_to_string (props, NULL, 0)); - - if (!klass->link_ipip_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_macsec_add: - * @self: platform instance - * @name: name of the new interface - * @parent: parent link - * @props: interface properties - * @out_link: on success, the link object - * - * Create a MACsec interface. - */ -int -nm_platform_link_macsec_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_MACSEC, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_macsec_to_string (props, NULL, 0)); - - if (!klass->link_macsec_add (self, name, parent, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_macvlan_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create a MACVLAN or MACVTAP device. - */ -int -nm_platform_link_macvlan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink **out_link) -{ - int r; - NMLinkType type; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - type = props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; - - r = _link_add_check_existing (self, name, type, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_macvlan_to_string (props, NULL, 0)); - - if (!klass->link_macvlan_add (self, name, parent, props, out_link)) - return -NME_UNSPEC; - return 0; -} - -/** - * nm_platform_sit_add: - * @self: platform instance - * @name: name of the new interface - * @props: interface properties - * @out_link: on success, the link object - * - * Create a software SIT device. - */ -int -nm_platform_link_sit_add (NMPlatform *self, - const char *name, - const NMPlatformLnkSit *props, - const NMPlatformLink **out_link) -{ - int r; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - - r = _link_add_check_existing (self, name, NM_LINK_TYPE_SIT, out_link); - if (r < 0) - return r; - - _LOG2D ("adding link %s", nm_platform_lnk_sit_to_string (props, NULL, 0)); - - if (!klass->link_sit_add (self, name, props, out_link)) - return -NME_UNSPEC; - return 0; -} - gboolean nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_peer_ifindex) { @@ -3675,6 +3317,7 @@ nm_platform_ip4_address_add (NMPlatform *self, in_addr_t address, guint8 plen, in_addr_t peer_address, + in_addr_t broadcast_address, guint32 lifetime, guint32 preferred, guint32 flags, @@ -3689,22 +3332,26 @@ nm_platform_ip4_address_add (NMPlatform *self, g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE); if (_LOGD_ENABLED ()) { - NMPlatformIP4Address addr = { 0 }; - - addr.ifindex = ifindex; - addr.address = address; - addr.peer_address = peer_address; - addr.plen = plen; - addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */ - addr.lifetime = lifetime; - addr.preferred = preferred; - addr.n_ifa_flags = flags; + NMPlatformIP4Address addr; + + addr = (NMPlatformIP4Address) { + .ifindex = ifindex, + .address = address, + .peer_address = peer_address, + .plen = plen, + .timestamp = 0, /* set it at zero, which to_string will treat as *now* */ + .lifetime = lifetime, + .preferred = preferred, + .n_ifa_flags = flags, + .broadcast_address = broadcast_address, + .use_ip4_broadcast_address = TRUE, + }; if (label) g_strlcpy (addr.label, label, sizeof (addr.label)); _LOG3D ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0)); } - return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags, label); + return klass->ip4_address_add (self, ifindex, address, plen, peer_address, broadcast_address, lifetime, preferred, flags, label); } gboolean @@ -3755,12 +3402,12 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address g_return_val_if_fail (plen <= 32, FALSE); _LOG3D ("address: deleting IPv4 address %s/%d, %s%s", - nm_utils_inet4_ntop (address, b1), + _nm_utils_inet4_ntop (address, b1), plen, peer_address != address ? nm_sprintf_buf (str_peer, "peer %s, ", - nm_utils_inet4_ntop (peer_address, b2)) + _nm_utils_inet4_ntop (peer_address, b2)) : "", _to_string_dev (self, ifindex, str_dev, sizeof (str_dev))); return klass->ip4_address_delete (self, ifindex, address, plen, peer_address); @@ -3778,7 +3425,7 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a g_return_val_if_fail (plen <= 128, FALSE); _LOG3D ("address: deleting IPv6 address %s/%d, %s", - nm_utils_inet6_ntop (&address, sbuf), plen, + _nm_utils_inet6_ntop (&address, sbuf), plen, _to_string_dev (self, ifindex, str_dev, sizeof (str_dev))); return klass->ip6_address_delete (self, ifindex, address, plen); } @@ -4048,7 +3695,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, { gs_unref_ptrarray GPtrArray *plat_addresses = NULL; const NMPlatformIP4Address *known_address; - gint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_sec (); GHashTable *plat_subnets = NULL; GHashTable *known_subnets = NULL; gs_unref_hashtable GHashTable *known_addresses_idx = NULL; @@ -4163,8 +3810,14 @@ nm_platform_ip4_address_sync (NMPlatform *self, if (!lifetime) goto delete_and_next2; - if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, - known_address->peer_address, lifetime, preferred, + if (!nm_platform_ip4_address_add (self, + ifindex, + known_address->address, + known_address->plen, + known_address->peer_address, + nm_platform_ip4_broadcast_address_from_addr (known_address), + lifetime, + preferred, ifa_flags, known_address->label)) goto delete_and_next2; @@ -4178,23 +3831,39 @@ delete_and_next2: return TRUE; } -static guint -ip6_address_scope_priority (const struct in6_addr *addr) +typedef enum { + IP6_ADDR_SCOPE_LOOPBACK, + IP6_ADDR_SCOPE_LINKLOCAL, + IP6_ADDR_SCOPE_SITELOCAL, + IP6_ADDR_SCOPE_OTHER, +} IP6AddrScope; + +static IP6AddrScope +ip6_address_scope (const NMPlatformIP6Address *a) { - if (IN6_IS_ADDR_LINKLOCAL (addr)) - return 1; - if (IN6_IS_ADDR_SITELOCAL (addr)) - return 2; - return 3; + if (IN6_IS_ADDR_LOOPBACK (&a->address)) + return IP6_ADDR_SCOPE_LOOPBACK; + if (IN6_IS_ADDR_LINKLOCAL (&a->address)) + return IP6_ADDR_SCOPE_LINKLOCAL; + if (IN6_IS_ADDR_SITELOCAL (&a->address)) + return IP6_ADDR_SCOPE_SITELOCAL; + return IP6_ADDR_SCOPE_OTHER; } static int -ip6_address_scope_cmp (gconstpointer a, gconstpointer b) +ip6_address_scope_cmp (gconstpointer p_a, gconstpointer p_b, gpointer increasing) { - const NMPlatformIP6Address *x = NMP_OBJECT_CAST_IP6_ADDRESS (*(const void **) a); - const NMPlatformIP6Address *y = NMP_OBJECT_CAST_IP6_ADDRESS (*(const void **) b); + const NMPlatformIP6Address *a; + const NMPlatformIP6Address *b; - return ip6_address_scope_priority (&x->address) - ip6_address_scope_priority (&y->address); + if (!increasing) + NM_SWAP (p_a, p_b); + + a = NMP_OBJECT_CAST_IP6_ADDRESS (*(const NMPObject *const*) p_a); + b = NMP_OBJECT_CAST_IP6_ADDRESS (*(const NMPObject *const*) p_b); + + NM_CMP_DIRECT (ip6_address_scope (a), ip6_address_scope (b)); + return 0; } /** @@ -4224,7 +3893,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, gboolean full_sync) { gs_unref_ptrarray GPtrArray *plat_addresses = NULL; - gint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_sec (); guint i_plat, i_know; gs_unref_hashtable GHashTable *known_addresses_idx = NULL; NMPLookup lookup; @@ -4235,7 +3904,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, * apply the same sorting to known addresses, so that we don't try to * unnecessary change the order of addresses with different scopes. */ if (known_addresses) - g_ptr_array_sort (known_addresses, ip6_address_scope_cmp); + g_ptr_array_sort_with_data (known_addresses, ip6_address_scope_cmp, GINT_TO_POINTER (TRUE)); if (!_addr_array_clean_expired (AF_INET6, ifindex, known_addresses, now, &known_addresses_idx)) known_addresses = NULL; @@ -4250,6 +3919,10 @@ nm_platform_ip6_address_sync (NMPlatform *self, if (plat_addresses) { guint known_addresses_len; + IP6AddrScope cur_scope; + gboolean delete_remaining_addrs; + + g_ptr_array_sort_with_data (plat_addresses, ip6_address_scope_cmp, GINT_TO_POINTER (FALSE)); known_addresses_len = known_addresses ? known_addresses->len : 0; @@ -4301,38 +3974,54 @@ clear_and_next: * selection will choose addresses in the order as they are reported by kernel. * Note that the order in @plat_addresses of the remaining matches is highest * priority first. - * We need to compare this to the order in @known_addresses (which has lowest - * priority first). + * We need to compare this to the order of addresses with same scope in + * @known_addresses (which has lowest priority first). * * If we find a first discrepancy, we need to delete all remaining addresses - * from that point on, because below we must re-add all the addresses in the - * right order to get their priority right. */ + * with same scope from that point on, because below we must re-add all the + * addresses in the right order to get their priority right. */ + cur_scope = IP6_ADDR_SCOPE_LOOPBACK; + delete_remaining_addrs = FALSE; i_plat = plat_addresses->len; i_know = 0; while (i_plat > 0) { const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS (plat_addresses->pdata[--i_plat]); + IP6AddrScope plat_scope; if (!plat_addr) continue; - for (; i_know < known_addresses_len; i_know++) { - const NMPlatformIP6Address *know_addr = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); + plat_scope = ip6_address_scope (plat_addr); + if (cur_scope != plat_scope) { + nm_assert (cur_scope < plat_scope); + delete_remaining_addrs = FALSE; + cur_scope = plat_scope; + } - if (!know_addr) - continue; + if (!delete_remaining_addrs) { + delete_remaining_addrs = TRUE; + for (; i_know < known_addresses_len; i_know++) { + const NMPlatformIP6Address *know_addr = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); + IP6AddrScope know_scope; - if (IN6_ARE_ADDR_EQUAL (&plat_addr->address, &know_addr->address)) { - /* we have a match. Mark address as handled. */ - i_know++; - goto next_plat; - } + if (!know_addr) + continue; - /* all remainging addresses need to be removed as well, so that we can - * re-add them in the correct order. Signal that, by setting @i_know - * so that the next @i_plat iteration, we won't enter the loop and - * delete the address right away */ - i_know = known_addresses_len; - break; + know_scope = ip6_address_scope (know_addr); + if (know_scope < plat_scope) + continue; + + if (IN6_ARE_ADDR_EQUAL (&plat_addr->address, &know_addr->address)) { + /* we have a match. Mark address as handled. */ + i_know++; + delete_remaining_addrs = FALSE; + goto next_plat; + } + + /* plat_address has no match. Now delete_remaining_addrs is TRUE and we will + * delete all the remaining addresses with cur_scope. */ + break; + } } nm_platform_ip6_address_delete (self, ifindex, plat_addr->address, plat_addr->plen); @@ -4965,15 +4654,15 @@ nm_platform_ip_route_get (NMPlatform *self, #define IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S ((int) (((IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS + 999) * 3) / 1000)) static gint64 -_ip4_dev_route_blacklist_timeout_ms_get (gint64 timeout_ms) +_ip4_dev_route_blacklist_timeout_ms_get (gint64 timeout_msec) { - return timeout_ms >> 1; + return timeout_msec >> 1; } static gint64 -_ip4_dev_route_blacklist_timeout_ms_marked (gint64 timeout_ms) +_ip4_dev_route_blacklist_timeout_ms_marked (gint64 timeout_msec) { - return !!(timeout_ms & ((gint64) 1)); + return !!(timeout_msec & ((gint64) 1)); } static gboolean @@ -4992,7 +4681,7 @@ again: if (!priv->ip4_dev_route_blacklist_hash) goto out; - now_ms = nm_utils_get_monotonic_timestamp_ms (); + now_ms = nm_utils_get_monotonic_timestamp_msec (); g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash); while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { @@ -5055,7 +4744,7 @@ _ip4_dev_route_blacklist_notify_route (NMPlatform *self, (gpointer *) &p_timeout_ms)) return; - now_ms = nm_utils_get_monotonic_timestamp_ms (); + now_ms = nm_utils_get_monotonic_timestamp_msec (); if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) { /* already expired. Wait for gc. */ return; @@ -5086,7 +4775,7 @@ _ip4_dev_route_blacklist_gc_timeout_handle (gpointer user_data) nm_assert (priv->ip4_dev_route_blacklist_gc_timeout_id); - now_ms = nm_utils_get_monotonic_timestamp_ms (); + now_ms = nm_utils_get_monotonic_timestamp_msec (); g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash); while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { @@ -5108,7 +4797,7 @@ _ip4_dev_route_blacklist_schedule (NMPlatform *self) if ( !priv->ip4_dev_route_blacklist_hash || g_hash_table_size (priv->ip4_dev_route_blacklist_hash) == 0) { - g_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); + nm_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id); } else { if (!priv->ip4_dev_route_blacklist_gc_timeout_id) { @@ -5155,8 +4844,8 @@ nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, GHashTableIter iter; const NMPObject *p_obj; guint i; - gint64 timeout_ms; - gint64 timeout_ms_val; + gint64 timeout_msec; + gint64 timeout_msec_val; gint64 *p_timeout_ms; gboolean needs_check = FALSE; @@ -5191,8 +4880,8 @@ nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, nm_g_slice_free_fcn_gint64); } - timeout_ms = nm_utils_get_monotonic_timestamp_ms () + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS; - timeout_ms_val = (timeout_ms << 1) | ((gint64) 1); + timeout_msec = nm_utils_get_monotonic_timestamp_msec () + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS; + timeout_msec_val = (timeout_msec << 1) | ((gint64) 1); for (i = 0; i < ip4_dev_route_blacklist->len; i++) { const NMPObject *o; @@ -5206,7 +4895,7 @@ nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, /* un-expire and reuse the entry. */ _LOGT ("ip4-dev-route: register %s (update)", nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - *p_timeout_ms = timeout_ms_val; + *p_timeout_ms = timeout_msec_val; continue; } } @@ -5214,7 +4903,7 @@ nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, _LOGT ("ip4-dev-route: register %s", nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); p_timeout_ms = g_slice_new (gint64); - *p_timeout_ms = timeout_ms_val; + *p_timeout_ms = timeout_msec_val; g_hash_table_replace (priv->ip4_dev_route_blacklist_hash, (gpointer) nmp_object_ref (o), p_timeout_ms); @@ -5605,16 +5294,16 @@ nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len "%s" /* okey */ "", lnk->is_tap ? "tap" : "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", lnk->path_mtu_discovery ? "" : " nopmtudisc", lnk->input_flags ? nm_sprintf_buf (str_input_flags, " iflags 0x%x", lnk->input_flags) : "", lnk->output_flags ? nm_sprintf_buf (str_output_flags, " oflags 0x%x", lnk->output_flags) : "", - NM_FLAGS_HAS (lnk->input_flags, GRE_KEY) || lnk->input_key ? nm_sprintf_buf (str_input_key, " ikey %s", nm_utils_inet4_ntop (lnk->input_key, str_input_key1)) : "", - NM_FLAGS_HAS (lnk->output_flags, GRE_KEY) || lnk->output_key ? nm_sprintf_buf (str_output_key, " okey %s", nm_utils_inet4_ntop (lnk->output_key, str_output_key1)) : ""); + NM_FLAGS_HAS (lnk->input_flags, GRE_KEY) || lnk->input_key ? nm_sprintf_buf (str_input_key, " ikey %s", _nm_utils_inet4_ntop (lnk->input_key, str_input_key1)) : "", + NM_FLAGS_HAS (lnk->output_flags, GRE_KEY) || lnk->output_key ? nm_sprintf_buf (str_output_key, " okey %s", _nm_utils_inet4_ntop (lnk->output_key, str_output_key1)) : ""); return buf; } @@ -5673,8 +5362,8 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi " flags 0x%x" "", str_type, - nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet6_ntop (&lnk->remote, str_remote1)), - nm_sprintf_buf (str_local, " local %s", nm_utils_inet6_ntop (&lnk->local, str_local1)), + nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet6_ntop (&lnk->remote, str_remote1)), + nm_sprintf_buf (str_local, " local %s", _nm_utils_inet6_ntop (&lnk->local, str_local1)), lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass), @@ -5708,8 +5397,8 @@ nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize l "%s" /* tos */ "%s" /* path_mtu_discovery */ "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", @@ -5791,8 +5480,8 @@ nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len "%s" /* flags */ "%s" /* proto */ "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", @@ -5856,6 +5545,20 @@ nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize l } const char * +nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len) +{ + char *b; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + b = buf; + + nm_utils_strbuf_append (&b, &len, "table %u", lnk->table); + return buf; +} + +const char * nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len) { char str_group[100]; @@ -5879,7 +5582,7 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize g_snprintf (str_group, sizeof (str_group), " %s %s", IN_MULTICAST (ntohl (lnk->group)) ? "group" : "remote", - nm_utils_inet4_ntop (lnk->group, sbuf)); + _nm_utils_inet4_ntop (lnk->group, sbuf)); } if (IN6_IS_ADDR_UNSPECIFIED (&lnk->group6)) str_group6[0] = '\0'; @@ -5888,7 +5591,7 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize " %s%s %s", IN6_IS_ADDR_MULTICAST (&lnk->group6) ? "group" : "remote", str_group[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - nm_utils_inet6_ntop (&lnk->group6, sbuf)); + _nm_utils_inet6_ntop (&lnk->group6, sbuf)); } if (lnk->local == 0) @@ -5896,7 +5599,7 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize else { g_snprintf (str_local, sizeof (str_local), " local %s", - nm_utils_inet4_ntop (lnk->local, sbuf)); + _nm_utils_inet4_ntop (lnk->local, sbuf)); } if (IN6_IS_ADDR_UNSPECIFIED (&lnk->local6)) str_local6[0] = '\0'; @@ -5904,7 +5607,7 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize g_snprintf (str_local6, sizeof (str_local6), " local%s %s", str_local[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - nm_utils_inet6_ntop (&lnk->local6, sbuf)); + _nm_utils_inet6_ntop (&lnk->local6, sbuf)); } g_snprintf (buf, len, @@ -6054,7 +5757,9 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu char str_lft[30], str_pref[30], str_time[50], s_source[50]; char *str_peer = NULL; const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_sec (); + in_addr_t broadcast_address; + char str_broadcast[INET_ADDRSTRLEN]; if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) return buf; @@ -6083,9 +5788,27 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu now, str_pref, sizeof (str_pref)) ); str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); + broadcast_address = nm_platform_ip4_broadcast_address_from_addr (address); + g_snprintf (buf, len, - "%s/%d lft %s pref %s%s%s%s%s%s src %s%s", - s_address, address->plen, str_lft_p, str_pref_p, str_time_p, + "%s/%d" + "%s%s" /* broadcast */ + " lft %s" + " pref %s" + "%s" /* time */ + "%s" /* peer */ + "%s" /* dev */ + "%s" /* flags */ + "%s" /* label */ + " src %s" + "%s" /* external */ + "", + s_address, address->plen, + broadcast_address ? " brd " : "", + broadcast_address ? nm_utils_inet4_ntop (broadcast_address, str_broadcast) : "", + str_lft_p, + str_pref_p, + str_time_p, str_peer ?: "", str_dev, _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), @@ -6167,7 +5890,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu char str_dev[TO_STRING_DEV_BUF_SIZE]; char *str_peer = NULL; const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_s (); + gint32 now = nm_utils_get_monotonic_timestamp_sec (); if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) return buf; @@ -6203,7 +5926,8 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu return buf; } -NM_UTILS_FLAGS2STR_DEFINE_STATIC (_rtm_flags_to_string, unsigned, +static +NM_UTILS_FLAGS2STR_DEFINE (_rtm_flags_to_string, unsigned, NM_UTILS_FLAGS2STR (RTNH_F_DEAD, "dead"), NM_UTILS_FLAGS2STR (RTNH_F_PERVASIVE, "pervasive"), NM_UTILS_FLAGS2STR (RTNH_F_ONLINK, "onlink"), @@ -6380,7 +6104,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi route->mss, nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), route->src_plen || !IN6_IS_ADDR_UNSPECIFIED (&route->src) - ? nm_sprintf_buf (s_src_all, " src %s/%u", nm_utils_inet6_ntop (&route->src, s_src), (unsigned) route->src_plen) + ? nm_sprintf_buf (s_src_all, " src %s/%u", _nm_utils_inet6_ntop (&route->src, s_src), (unsigned) route->src_plen) : "", _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags), s_pref_src[0] ? " pref-src " : "", @@ -7222,6 +6946,21 @@ nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b } void +nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h) +{ + nm_hash_update_vals (h, + obj->table); +} + +int +nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b) +{ + NM_CMP_SELF (a, b); + NM_CMP_FIELD (a, b, table); + return 0; +} + +void nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h) { nm_hash_update_vals (h, @@ -7298,6 +7037,7 @@ nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashStat nm_hash_update_vals (h, obj->ifindex, obj->addr_source, + nm_platform_ip4_broadcast_address_from_addr (obj), obj->timestamp, obj->lifetime, obj->preferred, @@ -7317,6 +7057,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A NM_CMP_FIELD (a, b, address); NM_CMP_FIELD (a, b, plen); NM_CMP_FIELD (a, b, peer_address); + NM_CMP_DIRECT (nm_platform_ip4_broadcast_address_from_addr (a), nm_platform_ip4_broadcast_address_from_addr (b)); NM_CMP_FIELD (a, b, addr_source); NM_CMP_FIELD (a, b, timestamp); NM_CMP_FIELD (a, b, lifetime); @@ -8238,7 +7979,7 @@ finalize (GObject *object) nm_clear_g_source (&priv->ip4_dev_route_blacklist_check_id); nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id); - g_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); + nm_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); g_clear_object (&self->_netns); nm_dedup_multi_index_unref (priv->multi_idx); nmp_cache_free (priv->cache); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 4bd8e34d..7edaaf58 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -287,7 +287,7 @@ typedef enum { * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly * set to 0). Such addresses are permanent. * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp - * and never returned by nm_utils_get_monotonic_timestamp_s(). In this case @valid/@preferred + * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred * is anchored at @timestamp. * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add(). @@ -308,6 +308,8 @@ typedef enum { guint8 plen; \ \ bool external:1; \ + \ + bool use_ip4_broadcast_address:1; \ ; /** @@ -325,7 +327,7 @@ typedef struct { /** * NMPlatformIP4Address: - * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() + * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() **/ struct _NMPlatformIP4Address { __NMPlatformIPAddress_COMMON; @@ -344,12 +346,18 @@ struct _NMPlatformIP4Address { * */ in_addr_t peer_address; /* PTP peer address */ + /* IFA_BROADCAST. + * + * This parameter is ignored unless use_ip4_broadcast_address is TRUE. + * See nm_platform_ip4_broadcast_address_from_addr(). */ + in_addr_t broadcast_address; + char label[NMP_IFNAMSIZ]; }; /** * NMPlatformIP6Address: - * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() + * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() **/ struct _NMPlatformIP6Address { __NMPlatformIPAddress_COMMON; @@ -795,8 +803,6 @@ typedef struct { bool tap:1; } NMPlatformLnkMacvlan; -typedef NMPlatformLnkMacvlan NMPlatformLnkMacvtap; - typedef struct { in_addr_t local; in_addr_t remote; @@ -830,6 +836,10 @@ typedef struct { } NMPlatformLnkVlan; typedef struct { + guint32 table; +} NMPlatformLnkVrf; + +typedef struct { struct in6_addr group6; struct in6_addr local6; in_addr_t group; @@ -965,11 +975,12 @@ typedef struct { void (*process_events) (NMPlatform *self); int (*link_add) (NMPlatform *self, - 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); gboolean (*link_delete) (NMPlatform *self, int ifindex); gboolean (*link_refresh) (NMPlatform *self, int ifindex); @@ -1028,7 +1039,6 @@ typedef struct { guint peers_len, NMPlatformWireGuardChangeFlags change_flags); - gboolean (*vlan_add) (NMPlatform *self, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link); gboolean (*link_vlan_change) (NMPlatform *self, int ifindex, NMVlanFlags flags_mask, @@ -1039,49 +1049,11 @@ typedef struct { gboolean egress_reset_all, const NMVlanQosMapping *egress_map, gsize n_egress_map); - gboolean (*link_vxlan_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link); - gboolean (*link_gre_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkGre *props, - const NMPlatformLink **out_link); - gboolean (*link_ip6tnl_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link); - gboolean (*link_ip6gre_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link); - gboolean (*link_ipip_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink **out_link); - gboolean (*link_macsec_add) (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink **out_link); - gboolean (*link_macvlan_add) (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink **out_link); - gboolean (*link_sit_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkSit *props, - const NMPlatformLink **out_link); gboolean (*link_tun_add) (NMPlatform *self, const char *name, const NMPlatformLnkTun *props, const NMPlatformLink **out_link, int *out_fd); - gboolean (*link_6lowpan_add) (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLink **out_link); gboolean (*infiniband_partition_add) (NMPlatform *self, int parent, int p_key, const NMPlatformLink **out_link); gboolean (*infiniband_partition_delete) (NMPlatform *self, int parent, int p_key); @@ -1116,6 +1088,7 @@ typedef struct { in_addr_t address, guint8 plen, in_addr_t peer_address, + in_addr_t broadcast_address, guint32 lifetime, guint32 preferred_lft, guint32 flags, @@ -1187,6 +1160,31 @@ NMPlatform *nm_platform_get (void); /*****************************************************************************/ +static inline in_addr_t +nm_platform_ip4_broadcast_address_create (in_addr_t address, + guint8 plen) +{ + return address | ~_nm_utils_ip4_prefix_to_netmask (plen); +} + +static inline in_addr_t +nm_platform_ip4_broadcast_address_from_addr (const NMPlatformIP4Address *addr) +{ + nm_assert (addr); + + if (addr->use_ip4_broadcast_address) + return addr->broadcast_address; + + /* the set broadcast-address gets ignored, and we determine a default brd base + * on the peer IFA_ADDRESS. */ + if ( addr->peer_address != 0u + && addr->plen < 31 /* RFC3021 */) + return nm_platform_ip4_broadcast_address_create (addr->peer_address, addr->plen); + return 0u; +} + +/*****************************************************************************/ + /** * nm_platform_route_table_coerce: * @table: the route table, in its original value as received @@ -1352,7 +1350,8 @@ int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4 (NMPlatform *platform, gboolean consider_all, gboolean *out_due_to_all); -const char *nm_platform_if_indextoname (NMPlatform *self, int ifindex, char *out_ifname/* of size IFNAMSIZ */); +const char *nm_platform_if_indextoname (NMPlatform *self, int ifindex, + char out_ifname[static 16 /* IFNAMSIZ */]); int nm_platform_if_nametoindex (NMPlatform *self, const char *ifname); const NMPObject *nm_platform_link_get_obj (NMPlatform *self, @@ -1363,11 +1362,200 @@ const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const ch const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, NMLinkType link_type, gconstpointer address, size_t length); GPtrArray *nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name); -int nm_platform_link_dummy_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); -int nm_platform_link_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, const NMPlatformLink **out_link); -int nm_platform_link_bond_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); -int nm_platform_link_team_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); -int nm_platform_link_veth_add (NMPlatform *self, const char *name, const char *peer, const NMPlatformLink **out_link); + +int nm_platform_link_add (NMPlatform *self, + NMLinkType type, + const char *name, + int parent, + const void *address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link); + +static inline int +nm_platform_link_veth_add (NMPlatform *self, + const char *name, + const char *peer, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_VETH, name, 0, NULL, 0, peer, out_link); +} + +static inline int +nm_platform_link_dummy_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_DUMMY, name, 0, NULL, 0, NULL, out_link); +} + +static inline int +nm_platform_link_bridge_add (NMPlatform *self, + const char *name, + const void *address, + size_t address_len, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_BRIDGE, name, 0, address, address_len, NULL, out_link); +} + +static inline int +nm_platform_link_bond_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_BOND, name, 0, NULL, 0, NULL, out_link); +} + +static inline int +nm_platform_link_team_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_TEAM, name, 0, NULL, 0, NULL, out_link); +} + +static inline int +nm_platform_link_wireguard_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_WIREGUARD, name, 0, NULL, 0, NULL, out_link); +} + +static inline int +nm_platform_link_gre_add (NMPlatform *self, + const char *name, + const void *address, + size_t address_len, + const NMPlatformLnkGre *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + + return nm_platform_link_add (self, props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, name, 0, address, address_len, props, out_link); +} + +static inline int +nm_platform_link_sit_add (NMPlatform *self, + const char *name, + const NMPlatformLnkSit *props, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_vlan_add (NMPlatform *self, + const char *name, + int parent, + int vlanid, + guint32 vlanflags, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (parent >= 0, -NME_BUG); + g_return_val_if_fail (vlanid >= 0, -NME_BUG); + + return nm_platform_link_add (self, + NM_LINK_TYPE_VLAN, + name, + parent, + NULL, + 0, + &((NMPlatformLnkVlan) { + .id = vlanid, + .flags = vlanflags, + }), + out_link); +} + +static inline int +nm_platform_link_vrf_add (NMPlatform *self, + const char *name, + const NMPlatformLnkVrf *props, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_vxlan_add (NMPlatform *self, + const char *name, + const NMPlatformLnkVxlan *props, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_6lowpan_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLink **out_link) +{ + return nm_platform_link_add (self, NM_LINK_TYPE_6LOWPAN, name, parent, NULL, 0, NULL, out_link); +} + +static inline int +nm_platform_link_ip6tnl_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + g_return_val_if_fail (!props->is_gre, -NME_BUG); + + return nm_platform_link_add (self, NM_LINK_TYPE_IP6TNL, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_ip6gre_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + g_return_val_if_fail (props->is_gre, -NME_BUG); + + return nm_platform_link_add (self, props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_ipip_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIpIp *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + + return nm_platform_link_add (self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_macsec_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + g_return_val_if_fail (parent > 0, -NME_BUG); + + return nm_platform_link_add (self, NM_LINK_TYPE_MACSEC, name, parent, NULL, 0, props, out_link); +} + +static inline int +nm_platform_link_macvlan_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLnkMacvlan *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail (props, -NME_BUG); + g_return_val_if_fail (parent > 0, -NME_BUG); + + return nm_platform_link_add (self, props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN, name, parent, NULL, 0, props, out_link); +} gboolean nm_platform_link_delete (NMPlatform *self, int ifindex); @@ -1477,19 +1665,14 @@ const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform * const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacsec *nm_platform_link_get_lnk_macsec (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacvtap *nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkTun *nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkVrf *nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkVxlan *nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkWireGuard *nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -int nm_platform_link_vlan_add (NMPlatform *self, - const char *name, - int parent, - int vlanid, - guint32 vlanflags, - const NMPlatformLink **out_link); gboolean nm_platform_link_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to); gboolean nm_platform_link_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to); gboolean nm_platform_link_vlan_change (NMPlatform *self, @@ -1503,11 +1686,6 @@ gboolean nm_platform_link_vlan_change (NMPlatform *self, const NMVlanQosMapping *egress_map, gsize n_egress_map); -int nm_platform_link_vxlan_add (NMPlatform *self, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link); - int nm_platform_link_infiniband_add (NMPlatform *self, int parent, int p_key, @@ -1550,32 +1728,6 @@ const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Addr const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address); -int nm_platform_link_gre_add (NMPlatform *self, - const char *name, - const NMPlatformLnkGre *props, - const NMPlatformLink **out_link); -int nm_platform_link_ip6tnl_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link); -int nm_platform_link_ip6gre_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link); -int nm_platform_link_ipip_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink **out_link); -int nm_platform_link_macsec_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink **out_link); -int nm_platform_link_macvlan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink **out_link); int nm_platform_link_sit_add (NMPlatform *self, const char *name, const NMPlatformLnkSit *props, @@ -1585,10 +1737,6 @@ int nm_platform_link_tun_add (NMPlatform *self, const NMPlatformLnkTun *props, const NMPlatformLink **out_link, int *out_fd); -int nm_platform_link_6lowpan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLink **out_link); gboolean nm_platform_link_6lowpan_get_properties (NMPlatform *self, int ifindex, int *out_parent); @@ -1614,6 +1762,7 @@ gboolean nm_platform_ip4_address_add (NMPlatform *self, in_addr_t address, guint8 plen, in_addr_t peer_address, + in_addr_t broadcast_address, guint32 lifetime, guint32 preferred_lft, guint32 flags, @@ -1693,6 +1842,7 @@ const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); const char *nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len); const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len); +const char *nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len); const char *nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len); const char *nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len); const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len); @@ -1725,6 +1875,7 @@ int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatform int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); int nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b); int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); +int nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b); int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b); int nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b); int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); @@ -1771,6 +1922,7 @@ void nm_platform_lnk_macvlan_hash_update (const NMPlatformLnkMacvlan *obj, NMHas void nm_platform_lnk_sit_hash_update (const NMPlatformLnkSit *obj, NMHashState *h); void nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h); void nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h); +void nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h); void nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h); void nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireGuard *obj, NMHashState *h); diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c index 78f76cc7..bc91d7a8 100644 --- a/src/platform/nmp-netns.c +++ b/src/platform/nmp-netns.c @@ -31,7 +31,8 @@ #define _CLONE_NS_ALL ((int) (CLONE_NEWNS | CLONE_NEWNET)) #define _CLONE_NS_ALL_V CLONE_NEWNS , CLONE_NEWNET -NM_UTILS_FLAGS2STR_DEFINE_STATIC (_clone_ns_to_str, int, +static +NM_UTILS_FLAGS2STR_DEFINE (_clone_ns_to_str, int, NM_UTILS_FLAGS2STR (CLONE_NEWNS, "mnt"), NM_UTILS_FLAGS2STR (CLONE_NEWNET, "net"), ); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 97aa4f28..541211cd 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -233,13 +233,13 @@ nm_sock_addr_union_to_string (const NMSockAddrUnion *sa, case AF_INET: g_snprintf (buf, len, "%s:%u", - nm_utils_inet4_ntop (sa->in.sin_addr.s_addr, s_addr), + _nm_utils_inet4_ntop (sa->in.sin_addr.s_addr, s_addr), (guint) htons (sa->in.sin_port)); break; case AF_INET6: g_snprintf (buf, len, "[%s%s]:%u", - nm_utils_inet6_ntop (&sa->in6.sin6_addr, s_addr), + _nm_utils_inet6_ntop (&sa->in6.sin6_addr, s_addr), ( sa->in6.sin6_scope_id != 0 ? nm_sprintf_buf (s_scope_id, "%u", sa->in6.sin6_scope_id) : ""), @@ -525,11 +525,11 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map, const NMVlanQosMapping *src_map) { if (src_n_map == 0) { - g_clear_pointer (dst_map, g_free); + nm_clear_g_free (dst_map); *dst_n_map = 0; } else if ( src_n_map != *dst_n_map || _vlan_xgress_qos_mappings_cmp (src_n_map, *dst_map, src_map) != 0) { - g_clear_pointer (dst_map, g_free); + nm_clear_g_free (dst_map); *dst_n_map = src_n_map; if (src_n_map > 0) *dst_map = nm_memdup (src_map, sizeof (*src_map) * src_n_map); @@ -1082,10 +1082,10 @@ _vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsiz return buf; \ } _vt_cmd_plobj_to_string_id (link, NMPlatformLink, "%d", obj->ifindex); -_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s", obj->ifindex, nm_utils_inet4_ntop ( obj->address, buf1), obj->plen, +_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s", obj->ifindex, _nm_utils_inet4_ntop ( obj->address, buf1), obj->plen, obj->peer_address != obj->address ? "," : "", - obj->peer_address != obj->address ? nm_utils_inet4_ntop (nm_utils_ip4_address_clear_host_address (obj->peer_address, obj->plen), buf2) : ""); -_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, nm_utils_inet6_ntop (&obj->address, buf1)); + obj->peer_address != obj->address ? _nm_utils_inet4_ntop (nm_utils_ip4_address_clear_host_address (obj->peer_address, obj->plen), buf2) : ""); +_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, _nm_utils_inet6_ntop (&obj->address, buf1)); _vt_cmd_plobj_to_string_id (qdisc, NMPlatformQdisc, "%d: %d", obj->ifindex, obj->parent); _vt_cmd_plobj_to_string_id (tfilter, NMPlatformTfilter, "%d: %d", obj->ifindex, obj->parent); @@ -3291,7 +3291,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), .obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP, .sizeof_data = sizeof (NMPObjectLnkMacvtap), - .sizeof_public = sizeof (NMPlatformLnkMacvtap), + .sizeof_public = sizeof (NMPlatformLnkMacvlan), .obj_type_name = "macvtap", .lnk_link_type = NM_LINK_TYPE_MACVTAP, .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macvlan_to_string, @@ -3336,6 +3336,18 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vlan_hash_update, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp, }, + [NMP_OBJECT_TYPE_LNK_VRF - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_VRF, + .sizeof_data = sizeof (NMPObjectLnkVrf), + .sizeof_public = sizeof (NMPlatformLnkVrf), + .obj_type_name = "vrf", + .lnk_link_type = NM_LINK_TYPE_VRF, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vrf_to_string, + .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vrf_hash_update, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vrf_cmp, + }, + [NMP_OBJECT_TYPE_LNK_VXLAN - 1] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), .obj_type = NMP_OBJECT_TYPE_LNK_VXLAN, diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 0c0796c3..44525ed0 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -287,6 +287,10 @@ typedef struct { } NMPObjectLnkVlan; typedef struct { + NMPlatformLnkVrf _public; +} NMPObjectLnkVrf; + +typedef struct { NMPlatformLnkVxlan _public; } NMPObjectLnkVxlan; @@ -366,6 +370,9 @@ struct _NMPObject { NMPlatformLnkVlan lnk_vlan; NMPObjectLnkVlan _lnk_vlan; + NMPlatformLnkVrf lnk_vrf; + NMPObjectLnkVrf _lnk_vrf; + NMPlatformLnkVxlan lnk_vxlan; NMPObjectLnkVxlan _lnk_vxlan; @@ -493,6 +500,7 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type) case NMP_OBJECT_TYPE_LNK_SIT: case NMP_OBJECT_TYPE_LNK_TUN: case NMP_OBJECT_TYPE_LNK_VLAN: + case NMP_OBJECT_TYPE_LNK_VRF: case NMP_OBJECT_TYPE_LNK_VXLAN: case NMP_OBJECT_TYPE_LNK_WIREGUARD: return TRUE; diff --git a/src/platform/tests/meson.build b/src/platform/tests/meson.build index 6f7173b6..4a50bca9 100644 --- a/src/platform/tests/meson.build +++ b/src/platform/tests/meson.build @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1+ + test_fake_c_flags = test_c_flags + ['-DSETUP=nm_fake_platform_setup'] test_linux_c_flags = test_c_flags + ['-DSETUP=nm_linux_platform_setup'] diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 34175c01..d19ff1f0 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -61,8 +61,7 @@ test_cleanup_internal (void) break; }); - /* Add routes and addresses */ - g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, 0, NULL)); + g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, nm_platform_ip4_broadcast_address_create (addr4, plen4), lifetime, preferred, 0, NULL)); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags)); nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss); nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index f831fe94..f393ae93 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -190,7 +190,7 @@ _accept_or_wait_signal (const char *file, int line, const char *func, SignalData if (data->received_count == 0) { data->loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data->loop); - g_clear_pointer (&data->loop, g_main_loop_unref); + nm_clear_pointer (&data->loop, g_main_loop_unref); } _accept_signal (file, line, func, data); @@ -205,7 +205,7 @@ _wait_signal (const char *file, int line, const char *func, SignalData *data) data->loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data->loop); - g_clear_pointer (&data->loop, g_main_loop_unref); + nm_clear_pointer (&data->loop, g_main_loop_unref); _accept_signal (file, line, func, data); } @@ -356,7 +356,7 @@ _nmtstp_assert_ip4_route_exists (const char *file, g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but platform has it %u times", file, line, func, - nm_utils_inet4_ntop (network, sbuf), + _nm_utils_inet4_ntop (network, sbuf), plen, metric, tos, @@ -467,10 +467,10 @@ _nmtstp_assert_ip6_route_exists (const char *file, g_error ("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but platform has it %u times", file, line, func, - nm_utils_inet6_ntop (network, s_network), + _nm_utils_inet6_ntop (network, s_network), plen, metric, - nm_utils_inet6_ntop (src, s_src), + _nm_utils_inet6_ntop (src, s_src), src_plen, c_exists, c); @@ -553,7 +553,7 @@ _wait_for_signal_timeout (gpointer user_data) } guint -nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms) +nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_msec) { WaitForSignalData data = { 0 }; gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; @@ -568,7 +568,7 @@ nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms) id_ip4_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); id_ip6_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - /* if timeout_ms is negative, it means the wait-time already expired. + /* if timeout_msec is negative, it means the wait-time already expired. * Maybe, we should do nothing and return right away, without even * processing events from platform. However, that inconsistency (of not * processing events from mainloop) is inconvenient. @@ -578,7 +578,7 @@ nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms) * a zero timeout: we check whether there are any events pending in platform, * and quite the mainloop immediately afterwards. But we always check. */ - data.id = g_timeout_add (CLAMP (timeout_ms, 0, G_MAXUINT32), + data.id = g_timeout_add (CLAMP (timeout_msec, 0, G_MAXUINT32), _wait_for_signal_timeout, &data); g_main_loop_run (data.loop); @@ -590,7 +590,7 @@ nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms) g_assert (nm_clear_g_signal_handler (platform, &id_ip4_route)); g_assert (nm_clear_g_signal_handler (platform, &id_ip6_route)); - g_clear_pointer (&data.loop, g_main_loop_unref); + nm_clear_pointer (&data.loop, g_main_loop_unref); /* return the number of signals, or 0 if timeout was reached .*/ return data.signal_counts; @@ -603,7 +603,7 @@ nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) guint signal_counts; while (TRUE) { - now = nm_utils_get_monotonic_timestamp_ms (); + now = nm_utils_get_monotonic_timestamp_msec (); if (until_ms < now) return 0; @@ -615,11 +615,11 @@ nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) } const NMPlatformLink * -nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_ms) +nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_msec) { return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, - timeout_ms - ? nm_utils_get_monotonic_timestamp_ms () + timeout_ms + timeout_msec + ? nm_utils_get_monotonic_timestamp_msec () + timeout_msec : 0); } @@ -633,7 +633,7 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType _init_platform (&platform, FALSE); while (TRUE) { - now = nm_utils_get_monotonic_timestamp_ms (); + now = nm_utils_get_monotonic_timestamp_msec (); plink = nm_platform_link_get_by_ifname (platform, ifname); if ( plink @@ -704,7 +704,7 @@ nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr, g_assert (addr); if (now == -1) - now = nm_utils_get_monotonic_timestamp_s (); + now = nm_utils_get_monotonic_timestamp_sec (); g_assert (now > 0); g_assert (expected_preferred <= expected_lifetime); @@ -750,7 +750,7 @@ nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr, g_assert (addr); if (now == -1) - now = nm_utils_get_monotonic_timestamp_s (); + now = nm_utils_get_monotonic_timestamp_sec (); g_assert (now > 0); g_assert (expected_preferred <= expected_lifetime); @@ -831,12 +831,12 @@ _ip_address_add (NMPlatform *platform, if ( peer_address->addr4 != address->addr4 || nmtst_get_rand_uint32 () % 2) { /* If the peer is the same as the local address, we can omit it. The result should be identical */ - nm_sprintf_buf (s_peer, " peer %s", nm_utils_inet4_ntop (peer_address->addr4, b2)); + nm_sprintf_buf (s_peer, " peer %s", _nm_utils_inet4_ntop (peer_address->addr4, b2)); } else s_peer[0] = '\0'; nmtstp_run_command_check ("ip address change %s%s/%d dev %s%s%s%s", - nm_utils_inet4_ntop (address->addr4, b1), + _nm_utils_inet4_ntop (address->addr4, b1), s_peer, plen, ifname, @@ -849,9 +849,9 @@ _ip_address_add (NMPlatform *platform, /* flags not implemented (yet) */ g_assert (flags == 0); nmtstp_run_command_check ("ip address change %s%s%s/%d dev %s%s%s%s", - nm_utils_inet6_ntop (&address->addr6, b1), + _nm_utils_inet6_ntop (&address->addr6, b1), !IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? " peer " : "", - !IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? nm_utils_inet6_ntop (&peer_address->addr6, b2) : "", + !IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? _nm_utils_inet6_ntop (&peer_address->addr6, b2) : "", plen, ifname, s_valid ?: "", @@ -867,6 +867,7 @@ _ip_address_add (NMPlatform *platform, address->addr4, plen, peer_address->addr4, + 0u, lifetime, preferred, flags, @@ -886,7 +887,7 @@ _ip_address_add (NMPlatform *platform, } /* Let's wait until we see the address. */ - end_time = nm_utils_get_monotonic_timestamp_ms () + 500; + end_time = nm_utils_get_monotonic_timestamp_msec () + 500; do { if (external_command) @@ -1058,15 +1059,15 @@ _ip_address_del (NMPlatform *platform, if (is_v4) { success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s", - nm_utils_inet4_ntop (address->addr4, b1), + _nm_utils_inet4_ntop (address->addr4, b1), peer_address->addr4 != address->addr4 ? " peer " : "", - peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "", + peer_address->addr4 != address->addr4 ? _nm_utils_inet4_ntop (peer_address->addr4, b2) : "", plen, ifname); } else { g_assert (!peer_address); success = nmtstp_run_command ("ip address delete %s/%d dev %s", - nm_utils_inet6_ntop (&address->addr6, b1), + _nm_utils_inet6_ntop (&address->addr6, b1), plen, ifname); } @@ -1091,7 +1092,7 @@ _ip_address_del (NMPlatform *platform, } /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_ms () + 250; + end_time = nm_utils_get_monotonic_timestamp_msec () + 250; do { if (external_command) nm_platform_process_events (platform); @@ -1257,15 +1258,15 @@ nmtstp_link_gre_add (NMPlatform *platform, name, type, dev ?: "", - nm_utils_inet4_ntop (lnk->local, b1), - nm_utils_inet4_ntop (lnk->remote, b2), + _nm_utils_inet4_ntop (lnk->local, b1), + _nm_utils_inet4_ntop (lnk->remote, b2), lnk->ttl, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100); } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_gre_add (platform, name, lnk, &pllink)); + success = NMTST_NM_ERR_SUCCESS (nm_platform_link_gre_add (platform, name, NULL, 0, lnk, &pllink)); _assert_pllink (platform, success, pllink, name, link_type); @@ -1319,8 +1320,8 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform, name, mode, dev, - nm_utils_inet6_ntop (&lnk->local, b1), - nm_utils_inet6_ntop (&lnk->remote, b2), + _nm_utils_inet6_ntop (&lnk->local, b1), + _nm_utils_inet6_ntop (&lnk->remote, b2), lnk->ttl, tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass), encap_ignore ? "none" : nm_sprintf_buf (encap, "%u", lnk->encap_limit), @@ -1367,8 +1368,8 @@ nmtstp_link_ip6gre_add (NMPlatform *platform, name, lnk->is_tap ? "ip6gretap" : "ip6gre", dev, - nm_utils_inet6_ntop (&lnk->local, b1), - nm_utils_inet6_ntop (&lnk->remote, b2), + _nm_utils_inet6_ntop (&lnk->local, b1), + _nm_utils_inet6_ntop (&lnk->remote, b2), lnk->ttl, tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass), lnk->flow_label); @@ -1412,8 +1413,8 @@ nmtstp_link_ipip_add (NMPlatform *platform, success = !nmtstp_run_command ("ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", name, dev, - nm_utils_inet4_ntop (lnk->local, b1), - nm_utils_inet4_ntop (lnk->remote, b2), + _nm_utils_inet4_ntop (lnk->local, b1), + _nm_utils_inet4_ntop (lnk->remote, b2), lnk->ttl, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); @@ -1506,8 +1507,8 @@ nmtstp_link_sit_add (NMPlatform *platform, success = !nmtstp_run_command ("ip tunnel add %s mode sit%s local %s remote %s ttl %u tos %02x %s", name, dev, - nm_utils_inet4_ntop (lnk->local, b1), - nm_utils_inet4_ntop (lnk->remote, b2), + _nm_utils_inet4_ntop (lnk->local, b1), + _nm_utils_inet4_ntop (lnk->remote, b2), lnk->ttl, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); @@ -1586,6 +1587,45 @@ nmtstp_link_tun_add (NMPlatform *platform, } const NMPlatformLink * +nmtstp_link_vrf_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkVrf *lnk, + gboolean *out_not_supported) +{ + const NMPlatformLink *pllink = NULL; + int r = 0; + + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + + NM_SET_OUT (out_not_supported, FALSE); + external_command = nmtstp_run_command_check_external (external_command); + + _init_platform (&platform, external_command); + + if (external_command) { + r = nmtstp_run_command ("ip link add %s type vrf table %u", + name, + lnk->table); + + if (r == 0) + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VRF, 100); + else + _LOGI ("Adding vrf device via iproute2 failed. Assume iproute2 is not up to the task."); + } + + if (!pllink) { + r = nm_platform_link_vrf_add (platform, name, lnk, &pllink); + if (r == -EOPNOTSUPP) + NM_SET_OUT (out_not_supported, TRUE); + } + + _assert_pllink (platform, r == 0, pllink, name, NM_LINK_TYPE_VRF); + + return pllink; +} + +const NMPlatformLink * nmtstp_link_vxlan_add (NMPlatform *platform, gboolean external_command, const char *name, @@ -1610,16 +1650,16 @@ nmtstp_link_vxlan_add (NMPlatform *platform, dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); if (lnk->local) - nm_utils_inet4_ntop (lnk->local, local); + _nm_utils_inet4_ntop (lnk->local, local); else if (memcmp (&lnk->local6, &in6addr_any, sizeof (in6addr_any))) - nm_utils_inet6_ntop (&lnk->local6, local); + _nm_utils_inet6_ntop (&lnk->local6, local); else local[0] = '\0'; if (lnk->group) - nm_utils_inet4_ntop (lnk->group, group); + _nm_utils_inet4_ntop (lnk->group, group); else if (memcmp (&lnk->group6, &in6addr_any, sizeof (in6addr_any))) - nm_utils_inet6_ntop (&lnk->group6, group); + _nm_utils_inet6_ntop (&lnk->group6, group); else group[0] = '\0'; @@ -1736,7 +1776,7 @@ nmtstp_link_delete (NMPlatform *platform, } /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_ms () + 250; + end_time = nm_utils_get_monotonic_timestamp_msec () + 250; do { if (external_command) nm_platform_process_events (platform); @@ -1785,7 +1825,7 @@ nmtstp_link_set_updown (NMPlatform *platform, } /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_ms () + 250; + end_time = nm_utils_get_monotonic_timestamp_msec () + 250; do { if (external_command) nm_platform_process_events (platform); diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index c571df6a..522c3756 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -32,13 +32,13 @@ const NMLogDomain __domain = (domain); \ \ if (nm_logging_enabled (__level, __domain)) { \ - gint64 _ts = nm_utils_get_monotonic_timestamp_ns (); \ + gint64 _ts = nm_utils_get_monotonic_timestamp_nsec (); \ \ _nm_log (__level, __domain, 0, NULL, NULL, \ "%s[%ld.%09ld]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ - (long) (_ts / NM_UTILS_NS_PER_SECOND), \ - (long) (_ts % NM_UTILS_NS_PER_SECOND) \ + (long) (_ts / NM_UTILS_NSEC_PER_SEC), \ + (long) (_ts % NM_UTILS_NSEC_PER_SEC) \ _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END @@ -101,14 +101,14 @@ int nmtstp_run_command (const char *format, ...) _nm_printf (1, 2); /*****************************************************************************/ -guint nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms); +guint nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_msec); guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms); -const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_ms); +const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_msec); const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); -#define nmtstp_assert_wait_for_signal(platform, timeout_ms) \ +#define nmtstp_assert_wait_for_signal(platform, timeout_msec) \ G_STMT_START { \ - if (nmtstp_wait_for_signal (platform, timeout_ms) == 0) \ + if (nmtstp_wait_for_signal (platform, timeout_msec) == 0) \ g_assert_not_reached (); \ } G_STMT_END @@ -118,8 +118,8 @@ const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const ch g_assert_not_reached (); \ } G_STMT_END -#define nmtstp_assert_wait_for_link(platform, ifname, expected_link_type, timeout_ms) \ - nmtst_assert_nonnull (nmtstp_wait_for_link (platform, ifname, expected_link_type, timeout_ms)) +#define nmtstp_assert_wait_for_link(platform, ifname, expected_link_type, timeout_msec) \ + nmtst_assert_nonnull (nmtstp_wait_for_link (platform, ifname, expected_link_type, timeout_msec)) #define nmtstp_assert_wait_for_link_until(platform, ifname, expected_link_type, until_ms) \ nmtst_assert_nonnull (nmtstp_wait_for_link_until (platform, ifname, expected_link_type, until_ms)) @@ -360,6 +360,11 @@ const NMPlatformLink *nmtstp_link_tun_add (NMPlatform *platform, const char *name, const NMPlatformLnkTun *lnk, int *out_fd); +const NMPlatformLink *nmtstp_link_vrf_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkVrf *lnk, + gboolean *out_not_supported); const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 37e1cde5..2661914b 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1144,7 +1144,7 @@ test_software_detect (gconstpointer user_data) break; } case NM_LINK_TYPE_MACVTAP: { - NMPlatformLnkMacvtap lnk_macvtap = { }; + NMPlatformLnkMacvlan lnk_macvtap = { }; lnk_macvtap.mode = MACVLAN_MODE_PRIVATE; lnk_macvtap.no_promisc = FALSE; @@ -1182,6 +1182,21 @@ test_software_detect (gconstpointer user_data) case NM_LINK_TYPE_VLAN: nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1242", DEVICE_NAME, PARENT_NAME); break; + case NM_LINK_TYPE_VRF: { + NMPlatformLnkVrf lnk_vrf = { }; + gboolean not_supported; + + lnk_vrf.table = 9876; + + if (!nmtstp_link_vrf_add (NULL, ext, DEVICE_NAME, &lnk_vrf, ¬_supported)) { + if (not_supported) { + g_test_skip ("Cannot create VRF interface because of missing kernel support"); + goto out_delete_parent; + } + g_error ("Failed adding VRF interface"); + } + break; + } case NM_LINK_TYPE_VXLAN: { NMPlatformLnkVxlan lnk_vxlan = { }; @@ -1389,7 +1404,7 @@ test_software_detect (gconstpointer user_data) break; } case NM_LINK_TYPE_MACVTAP: { - const NMPlatformLnkMacvtap *plnk = &lnk->lnk_macvlan; + const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; g_assert (plnk == nm_platform_link_get_lnk_macvtap (NM_PLATFORM_GET, ifindex, NULL)); g_assert_cmpint (plnk->no_promisc, ==, FALSE); @@ -1444,6 +1459,13 @@ test_software_detect (gconstpointer user_data) g_assert_cmpint (plnk->id, ==, 1242); break; } + case NM_LINK_TYPE_VRF: { + const NMPlatformLnkVrf *plnk = &lnk->lnk_vrf; + + g_assert (plnk == nm_platform_link_get_lnk_vrf (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->table, ==, 9876); + break; + } case NM_LINK_TYPE_VXLAN: { const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan; @@ -2095,7 +2117,7 @@ test_vlan_set_xgress (void) static void test_create_many_links_do (guint n_devices) { - gint64 time, start_time = nm_utils_get_monotonic_timestamp_ns (); + gint64 time, start_time = nm_utils_get_monotonic_timestamp_nsec (); guint i; char name[64]; const NMPlatformLink *pllink; @@ -2149,8 +2171,8 @@ test_create_many_links_do (guint n_devices) _LOGI (">>> process events after deleting devices..."); nm_platform_process_events (NM_PLATFORM_GET); - time = nm_utils_get_monotonic_timestamp_ns () - start_time; - _LOGI (">>> finished in %ld.%09ld seconds", (long) (time / NM_UTILS_NS_PER_SECOND), (long) (time % NM_UTILS_NS_PER_SECOND)); + time = nm_utils_get_monotonic_timestamp_nsec () - start_time; + _LOGI (">>> finished in %ld.%09ld seconds", (long) (time / NM_UTILS_NSEC_PER_SEC), (long) (time % NM_UTILS_NSEC_PER_SEC)); } static void @@ -3313,6 +3335,7 @@ _nmtstp_setup_tests (void) test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); test_software_detect_add ("/link/software/detect/tun", NM_LINK_TYPE_TUN, 0); test_software_detect_add ("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0); + test_software_detect_add ("/link/software/detect/vrf", NM_LINK_TYPE_VRF, 0); test_software_detect_add ("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0); test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1); test_software_detect_add ("/link/software/detect/wireguard/0", NM_LINK_TYPE_WIREGUARD, 0); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index f8b1bb9a..f074ca69 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -19,7 +19,7 @@ static void _wait_for_ipv4_addr_device_route (NMPlatform *platform, - gint64 timeout_ms, + gint64 timeout_msec, int ifindex, in_addr_t addr, guint8 plen) @@ -55,7 +55,7 @@ _wait_for_ipv4_addr_device_route (NMPlatform *platform, static void _wait_for_ipv6_addr_non_tentative (NMPlatform *platform, - gint64 timeout_ms, + gint64 timeout_msec, int ifindex, guint addr_n, const struct in6_addr *addrs) @@ -67,7 +67,7 @@ _wait_for_ipv6_addr_non_tentative (NMPlatform *platform, * small amount of time, which prevents the immediate addition of the route * with RTA_PREFSRC */ - NMTST_WAIT_ASSERT (timeout_ms, { + NMTST_WAIT_ASSERT (timeout_msec, { gboolean should_wait = FALSE; const NMPlatformIP6Address *plt_addr; @@ -544,6 +544,7 @@ test_ip4_route_options (gconstpointer test_data) a->address, a->plen, a->peer_address, + nm_platform_ip4_broadcast_address_create (a->address, a->plen), a->lifetime, a->preferred, a->n_ifa_flags, @@ -1238,7 +1239,7 @@ again_uid_range: rr->uid_range.end = nmtst_rand_select (0u, uids.uid, uids.euid); if (rr->uid_range_has) { if (rr->uid_range.end < rr->uid_range.start) - NMTST_SWAP (rr->uid_range.start, rr->uid_range.end); + NM_SWAP (rr->uid_range.start, rr->uid_range.end); if ( rr->uid_range.start == ((guint32) -1) || rr->uid_range.end == ((guint32) -1)) goto again_uid_range; @@ -1258,7 +1259,7 @@ again_uid_range: range->start = nmtst_rand_select (1u, 0xFFFEu, ((p ) % 0xFFFEu) + 1); range->end = nmtst_rand_select (1u, 0xFFFEu, ((p >> 16) % 0xFFFEu) + 1, range->start); if (range->end < range->start) - NMTST_SWAP (range->start, range->end); + NM_SWAP (range->start, range->end); } } } diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c index afeb3b02..a090ef9e 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/platform/wifi/nm-wifi-utils-nl80211.c @@ -152,7 +152,7 @@ dispose (GObject *object) { NMWifiUtilsNl80211 *self = NM_WIFI_UTILS_NL80211 (object); - g_clear_pointer (&self->freqs, g_free); + nm_clear_g_free (&self->freqs); } struct nl80211_iface_info { |