</listitem>
</varlistentry>
+ <varlistentry id='kind'>
+ <term><varname>Kind=</varname></term>
+ <listitem>
+ <para>A whitespace-separated list of shell-style globs matching the device kind, as exposed by
+ <command>networkctl status <replaceable>INTERFACE</replaceable></command> or
+ <command>ip -d link show <replaceable>INTERFACE</replaceable></command>. If the list is
+ prefixed with a "!", the test is inverted. Some valid values are <literal>bond</literal>,
+ <literal>bridge</literal>, <literal>gre</literal>, <literal>tun</literal>,
+ <literal>veth</literal>. Valid kinds are given by netlink's <literal>IFLA_INFO_KIND</literal>
+ attribute, so this is not comprehensive.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id='property'>
<term><varname>Property=</varname></term>
<listitem>
<xi:include href="systemd.link.xml" xpointer="path" />
<xi:include href="systemd.link.xml" xpointer="driver" />
<xi:include href="systemd.link.xml" xpointer="type" />
+ <xi:include href="systemd.link.xml" xpointer="kind" />
<xi:include href="systemd.link.xml" xpointer="property" />
<varlistentry>
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;
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)
*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)
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);
&link->permanent_hw_addr,
link->driver,
link->iftype,
+ link->kind,
link->ifname,
link->alternative_names,
link->wlan_iftype,
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)
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);
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) &&
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,
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;
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;
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,
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)
return NULL;
sd_device_unref(link->device);
+ free(link->kind);
free(link->driver);
return mfree(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;
&link->permanent_hw_addr,
link->driver,
link->iftype,
+ link->kind,
link->ifname,
/* alternative_names = */ NULL,
/* wlan_iftype = */ 0,
sd_device *device;
sd_device_action_t action;
+ char *kind;
char *driver;
uint16_t iftype;
uint32_t flags;
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");
Path=
Driver=
Type=
+Kind=
Property=
Host=
Virtualization=
[Match]
KernelVersion=
Type=
+Kind=
Driver=
Architecture=
Firmware=