From 65022cd7abc64da553a037d2e918adddce34ceda Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 17 Feb 2022 21:06:12 +0900 Subject: [PATCH] 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 55ca597c97a..1eaf8e14cbc 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 52d017bb783..3e8d9affd96 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 8b4ed44790a..ce2c4f3b540 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 097483c4351..fee450cdc2a 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 238b68579c5..fe90bc4da54 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 c3de7d72390..edce61996ad 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 006676d973e..b96cb600649 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 e767439335d..0884d43f460 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 17b3697077c..96280148c7b 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 29e960acc04..9b51025c6a7 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 90cb438e4b6..ea9f560f45e 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 aa7d229816b..85f89fadd8d 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 eae76749eb6..d6c6cc6f2ef 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 10a40d26649..ef302dca7b7 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= -- 2.47.3