From 430f07f4f8d1c0c214e50447390ee060386574a7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 17 Feb 2022 21:14:36 +0900 Subject: [PATCH 1/2] networkctl: show netdev kind --- src/network/networkctl.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 20e176e854..8fe9844c4f 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -263,7 +263,7 @@ typedef struct VxLanInfo { typedef struct LinkInfo { char name[IFNAMSIZ+1]; - char netdev_kind[NETDEV_KIND_MAX]; + char *netdev_kind; sd_device *sd_device; int ifindex; unsigned short iftype; @@ -364,6 +364,7 @@ static int link_info_compare(const LinkInfo *a, const LinkInfo *b) { static LinkInfo* link_info_array_free(LinkInfo *array) { for (unsigned i = 0; array && array[i].needs_freeing; i++) { sd_device_unref(array[i].sd_device); + free(array[i].netdev_kind); free(array[i].ssid); free(array[i].qdisc); strv_free(array[i].alternative_names); @@ -374,7 +375,6 @@ static LinkInfo* link_info_array_free(LinkInfo *array) { DEFINE_TRIVIAL_CLEANUP_FUNC(LinkInfo*, link_info_array_free); static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { - const char *received_kind; int r; assert(m); @@ -384,15 +384,17 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { if (r < 0) return r; - r = sd_netlink_message_read_string(m, IFLA_INFO_KIND, &received_kind); - if (r < 0) + r = sd_netlink_message_read_string_strdup(m, IFLA_INFO_KIND, &info->netdev_kind); + if (r < 0) { + (void) sd_netlink_message_exit_container(m); return r; + } r = sd_netlink_message_enter_container(m, IFLA_INFO_DATA); if (r < 0) return r; - if (streq(received_kind, "bridge")) { + if (streq(info->netdev_kind, "bridge")) { (void) sd_netlink_message_read_u32(m, IFLA_BR_FORWARD_DELAY, &info->forward_delay); (void) sd_netlink_message_read_u32(m, IFLA_BR_HELLO_TIME, &info->hello_time); (void) sd_netlink_message_read_u32(m, IFLA_BR_MAX_AGE, &info->max_age); @@ -402,12 +404,12 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { (void) sd_netlink_message_read_u16(m, IFLA_BR_PRIORITY, &info->priority); (void) sd_netlink_message_read_u8(m, IFLA_BR_MCAST_IGMP_VERSION, &info->mcast_igmp_version); (void) sd_netlink_message_read_u8(m, IFLA_BRPORT_STATE, &info->port_state); - } if (streq(received_kind, "bond")) { + } if (streq(info->netdev_kind, "bond")) { (void) sd_netlink_message_read_u8(m, IFLA_BOND_MODE, &info->mode); (void) sd_netlink_message_read_u32(m, IFLA_BOND_MIIMON, &info->miimon); (void) sd_netlink_message_read_u32(m, IFLA_BOND_DOWNDELAY, &info->downdelay); (void) sd_netlink_message_read_u32(m, IFLA_BOND_UPDELAY, &info->updelay); - } else if (streq(received_kind, "vxlan")) { + } else if (streq(info->netdev_kind, "vxlan")) { (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_ID, &info->vxlan_info.vni); r = sd_netlink_message_read_in_addr(m, IFLA_VXLAN_GROUP, &info->vxlan_info.group.in); @@ -437,12 +439,12 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_L2MISS, &info->vxlan_info.l2miss); (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_TOS, &info->vxlan_info.tos); (void) sd_netlink_message_read_u8(m, IFLA_VXLAN_TTL, &info->vxlan_info.ttl); - } else if (streq(received_kind, "vlan")) + } else if (streq(info->netdev_kind, "vlan")) (void) sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &info->vlan_id); - else if (STR_IN_SET(received_kind, "ipip", "sit")) { + else if (STR_IN_SET(info->netdev_kind, "ipip", "sit")) { (void) sd_netlink_message_read_in_addr(m, IFLA_IPTUN_LOCAL, &info->local.in); (void) sd_netlink_message_read_in_addr(m, IFLA_IPTUN_REMOTE, &info->remote.in); - } else if (streq(received_kind, "geneve")) { + } else if (streq(info->netdev_kind, "geneve")) { (void) sd_netlink_message_read_u32(m, IFLA_GENEVE_ID, &info->vni); r = sd_netlink_message_read_in_addr(m, IFLA_GENEVE_REMOTE, &info->remote.in); @@ -460,27 +462,25 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { (void) sd_netlink_message_read_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, &info->csum6_rx); (void) sd_netlink_message_read_u16(m, IFLA_GENEVE_PORT, &info->tunnel_port); (void) sd_netlink_message_read_u32(m, IFLA_GENEVE_LABEL, &info->label); - } else if (STR_IN_SET(received_kind, "gre", "gretap", "erspan")) { + } else if (STR_IN_SET(info->netdev_kind, "gre", "gretap", "erspan")) { (void) sd_netlink_message_read_in_addr(m, IFLA_GRE_LOCAL, &info->local.in); (void) sd_netlink_message_read_in_addr(m, IFLA_GRE_REMOTE, &info->remote.in); - } else if (STR_IN_SET(received_kind, "ip6gre", "ip6gretap", "ip6erspan")) { + } else if (STR_IN_SET(info->netdev_kind, "ip6gre", "ip6gretap", "ip6erspan")) { (void) sd_netlink_message_read_in6_addr(m, IFLA_GRE_LOCAL, &info->local.in6); (void) sd_netlink_message_read_in6_addr(m, IFLA_GRE_REMOTE, &info->remote.in6); - } else if (streq(received_kind, "vti")) { + } else if (streq(info->netdev_kind, "vti")) { (void) sd_netlink_message_read_in_addr(m, IFLA_VTI_LOCAL, &info->local.in); (void) sd_netlink_message_read_in_addr(m, IFLA_VTI_REMOTE, &info->remote.in); - } else if (streq(received_kind, "vti6")) { + } else if (streq(info->netdev_kind, "vti6")) { (void) sd_netlink_message_read_in6_addr(m, IFLA_VTI_LOCAL, &info->local.in6); (void) sd_netlink_message_read_in6_addr(m, IFLA_VTI_REMOTE, &info->remote.in6); - } else if (STR_IN_SET(received_kind, "macvlan", "macvtap")) + } else if (STR_IN_SET(info->netdev_kind, "macvlan", "macvtap")) (void) sd_netlink_message_read_u32(m, IFLA_MACVLAN_MODE, &info->macvlan_mode); - else if (streq(received_kind, "ipvlan")) { + else if (streq(info->netdev_kind, "ipvlan")) { (void) sd_netlink_message_read_u16(m, IFLA_IPVLAN_MODE, &info->ipvlan_mode); (void) sd_netlink_message_read_u16(m, IFLA_IPVLAN_FLAGS, &info->ipvlan_flags); } - strncpy(info->netdev_kind, received_kind, IFNAMSIZ); - (void) sd_netlink_message_exit_container(m); (void) sd_netlink_message_exit_container(m); @@ -1644,6 +1644,9 @@ static int link_status_one( TABLE_STRING, "Type:", TABLE_STRING, strna(t), TABLE_EMPTY, + TABLE_STRING, "Kind:", + TABLE_STRING, strna(info->netdev_kind), + TABLE_EMPTY, TABLE_STRING, "State:"); if (r < 0) return table_log_add_error(r); From 65022cd7abc64da553a037d2e918adddce34ceda Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 17 Feb 2022 21:06:12 +0900 Subject: [PATCH 2/2] network,udev/net: add Kind= settings in [Match] section This may be useful for writing .network or .link files matching with virtual interfaces. Closes #22541. --- man/systemd.link.xml | 14 ++++++++++++++ man/systemd.network.xml | 1 + src/libsystemd/sd-netlink/netlink-util.c | 17 +++++++++++++++++ src/libsystemd/sd-netlink/netlink-util.h | 1 + src/network/networkd-link.c | 1 + src/network/networkd-network-gperf.gperf | 1 + src/shared/net-condition.c | 6 ++++++ src/shared/net-condition.h | 4 +++- src/udev/net/link-config-gperf.gperf | 1 + src/udev/net/link-config.c | 5 ++++- src/udev/net/link-config.h | 1 + src/udev/udev-event.c | 2 +- test/fuzz/fuzz-link-parser/directives.link | 1 + .../fuzz/fuzz-network-parser/directives.network | 1 + 14 files changed, 53 insertions(+), 3 deletions(-) diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 55ca597c97..1eaf8e14cb 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -178,6 +178,20 @@ + + Kind= + + A whitespace-separated list of shell-style globs matching the device kind, as exposed by + networkctl status INTERFACE or + ip -d link show INTERFACE. If the list is + prefixed with a "!", the test is inverted. Some valid values are bond, + bridge, gre, tun, + veth. Valid kinds are given by netlink's IFLA_INFO_KIND + attribute, so this is not comprehensive. + + + + Property= diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 52d017bb78..3e8d9affd9 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -85,6 +85,7 @@ + diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 8b4ed44790..ce2c4f3b54 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -366,11 +366,13 @@ int rtnl_get_link_info( int ifindex, unsigned short *ret_iftype, unsigned *ret_flags, + char **ret_kind, struct hw_addr_data *ret_hw_addr, struct hw_addr_data *ret_permanent_hw_addr) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; struct hw_addr_data addr = HW_ADDR_NULL, perm_addr = HW_ADDR_NULL; + _cleanup_free_ char *kind = NULL; unsigned short iftype; unsigned flags; int r; @@ -409,6 +411,19 @@ int rtnl_get_link_info( return r; } + if (ret_kind) { + r = sd_netlink_message_enter_container(reply, IFLA_LINKINFO); + if (r >= 0) { + r = sd_netlink_message_read_string_strdup(reply, IFLA_INFO_KIND, &kind); + if (r < 0 && r != -ENODATA) + return r; + + r = sd_netlink_message_exit_container(reply); + if (r < 0) + return r; + } + } + if (ret_hw_addr) { r = netlink_message_read_hw_addr(reply, IFLA_ADDRESS, &addr); if (r < 0 && r != -ENODATA) @@ -425,6 +440,8 @@ int rtnl_get_link_info( *ret_iftype = iftype; if (ret_flags) *ret_flags = flags; + if (ret_kind) + *ret_kind = TAKE_PTR(kind); if (ret_hw_addr) *ret_hw_addr = addr; if (ret_permanent_hw_addr) diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index 097483c435..fee450cdc2 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -94,6 +94,7 @@ int rtnl_get_link_info( int ifindex, unsigned short *ret_iftype, unsigned *ret_flags, + char **ret_kind, struct hw_addr_data *ret_hw_addr, struct hw_addr_data *ret_permanent_hw_addr); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 238b68579c..fe90bc4da5 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1169,6 +1169,7 @@ static int link_get_network(Link *link, Network **ret) { &link->permanent_hw_addr, link->driver, link->iftype, + link->kind, link->ifname, link->alternative_names, link->wlan_iftype, diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index c3de7d7239..edce61996a 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -52,6 +52,7 @@ Match.PermanentMACAddress, config_parse_hw_addrs, Match.Path, config_parse_match_strv, 0, offsetof(Network, match.path) Match.Driver, config_parse_match_strv, 0, offsetof(Network, match.driver) Match.Type, config_parse_match_strv, 0, offsetof(Network, match.iftype) +Match.Kind, config_parse_match_strv, 0, offsetof(Network, match.kind) Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match.wlan_iftype) Match.SSID, config_parse_match_strv, 0, offsetof(Network, match.ssid) Match.BSSID, config_parse_ether_addrs, 0, offsetof(Network, match.bssid) diff --git a/src/shared/net-condition.c b/src/shared/net-condition.c index 006676d973..b96cb60064 100644 --- a/src/shared/net-condition.c +++ b/src/shared/net-condition.c @@ -22,6 +22,7 @@ void net_match_clear(NetMatch *match) { match->path = strv_free(match->path); match->driver = strv_free(match->driver); match->iftype = strv_free(match->iftype); + match->kind = strv_free(match->kind); match->ifname = strv_free(match->ifname); match->property = strv_free(match->property); match->wlan_iftype = strv_free(match->wlan_iftype); @@ -38,6 +39,7 @@ bool net_match_is_empty(const NetMatch *match) { strv_isempty(match->path) && strv_isempty(match->driver) && strv_isempty(match->iftype) && + strv_isempty(match->kind) && strv_isempty(match->ifname) && strv_isempty(match->property) && strv_isempty(match->wlan_iftype) && @@ -126,6 +128,7 @@ int net_match_config( const struct hw_addr_data *permanent_hw_addr, const char *driver, unsigned short iftype, + const char *kind, const char *ifname, char * const *alternative_names, enum nl80211_iftype wlan_iftype, @@ -160,6 +163,9 @@ int net_match_config( if (!net_condition_test_strv(match->iftype, iftype_str)) return false; + if (!net_condition_test_strv(match->kind, kind)) + return false; + if (!net_condition_test_ifname(match->ifname, ifname, alternative_names)) return false; diff --git a/src/shared/net-condition.h b/src/shared/net-condition.h index e767439335..0884d43f46 100644 --- a/src/shared/net-condition.h +++ b/src/shared/net-condition.h @@ -15,7 +15,8 @@ typedef struct NetMatch { Set *permanent_hw_addr; char **path; char **driver; - char **iftype; + char **iftype; /* udev's DEVTYPE field or ARPHRD_XXX, e.g. ether, wlan. */ + char **kind; /* IFLA_INFO_KIND attribute, e.g. gre, gretap, erspan. */ char **ifname; char **property; char **wlan_iftype; @@ -33,6 +34,7 @@ int net_match_config( const struct hw_addr_data *permanent_hw_addr, const char *driver, unsigned short iftype, + const char *kind, const char *ifname, char * const *alternative_names, enum nl80211_iftype wlan_iftype, diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 17b3697077..96280148c7 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -28,6 +28,7 @@ Match.OriginalName, config_parse_match_ifnames, Match.Path, config_parse_match_strv, 0, offsetof(LinkConfig, match.path) Match.Driver, config_parse_match_strv, 0, offsetof(LinkConfig, match.driver) Match.Type, config_parse_match_strv, 0, offsetof(LinkConfig, match.iftype) +Match.Kind, config_parse_match_strv, 0, offsetof(LinkConfig, match.kind) Match.Property, config_parse_match_property, 0, offsetof(LinkConfig, match.property) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(LinkConfig, conditions) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(LinkConfig, conditions) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 29e960acc0..9b51025c6a 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -361,6 +361,7 @@ Link *link_free(Link *link) { return NULL; sd_device_unref(link->device); + free(link->kind); free(link->driver); return mfree(link); } @@ -402,7 +403,8 @@ int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link if (r < 0) log_link_debug_errno(link, r, "Failed to get \"addr_assign_type\" attribute, ignoring: %m"); - r = rtnl_get_link_info(rtnl, link->ifindex, &link->iftype, &link->flags, &link->hw_addr, &link->permanent_hw_addr); + r = rtnl_get_link_info(rtnl, link->ifindex, &link->iftype, &link->flags, + &link->kind, &link->hw_addr, &link->permanent_hw_addr); if (r < 0) return r; @@ -439,6 +441,7 @@ int link_get_config(LinkConfigContext *ctx, Link *link) { &link->permanent_hw_addr, link->driver, link->iftype, + link->kind, link->ifname, /* alternative_names = */ NULL, /* wlan_iftype = */ 0, diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index 90cb438e4b..ea9f560f45 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -32,6 +32,7 @@ typedef struct Link { sd_device *device; sd_device_action_t action; + char *kind; char *driver; uint16_t iftype; uint32_t flags; diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index aa7d229816..85f89fadd8 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -900,7 +900,7 @@ static int rename_netif(UdevEvent *event) { return 0; } - r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags, NULL, NULL); + r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags, NULL, NULL, NULL); if (r < 0) return log_device_warning_errno(dev, r, "Failed to get link flags: %m"); diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link index eae76749eb..d6c6cc6f2e 100644 --- a/test/fuzz/fuzz-link-parser/directives.link +++ b/test/fuzz/fuzz-link-parser/directives.link @@ -5,6 +5,7 @@ OriginalName= Path= Driver= Type= +Kind= Property= Host= Virtualization= diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 10a40d2664..ef302dca7b 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -17,6 +17,7 @@ MulticastRouter= [Match] KernelVersion= Type= +Kind= Driver= Architecture= Firmware=