1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-25 01:34:28 +03:00

Merge pull request #20537 from yuwata/sd-netlink-more-attributes

udev: use link info obtained through netlink
This commit is contained in:
Lennart Poettering 2021-09-01 13:25:54 +02:00 committed by GitHub
commit 42ffc40ce3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1287 additions and 596 deletions

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_CFM_BRIDGE_H_
#define _UAPI_LINUX_CFM_BRIDGE_H_
#include <linux/types.h>
#include <linux/if_ether.h>
#define ETHER_HEADER_LENGTH (6+6+4+2)
#define CFM_MAID_LENGTH 48
#define CFM_CCM_PDU_LENGTH 75
#define CFM_PORT_STATUS_TLV_LENGTH 4
#define CFM_IF_STATUS_TLV_LENGTH 4
#define CFM_IF_STATUS_TLV_TYPE 4
#define CFM_PORT_STATUS_TLV_TYPE 2
#define CFM_ENDE_TLV_TYPE 0
#define CFM_CCM_MAX_FRAME_LENGTH (ETHER_HEADER_LENGTH+\
CFM_CCM_PDU_LENGTH+\
CFM_PORT_STATUS_TLV_LENGTH+\
CFM_IF_STATUS_TLV_LENGTH)
#define CFM_FRAME_PRIO 7
#define CFM_CCM_TLV_OFFSET 70
#define CFM_CCM_PDU_MAID_OFFSET 10
#define CFM_CCM_PDU_MEPID_OFFSET 8
#define CFM_CCM_PDU_SEQNR_OFFSET 4
#define CFM_CCM_PDU_TLV_OFFSET 74
#define CFM_CCM_ITU_RESERVED_SIZE 16
struct br_cfm_common_hdr {
__u8 mdlevel_version;
__u8 opcode;
__u8 flags;
__u8 tlv_offset;
};
enum br_cfm_opcodes {
BR_CFM_OPCODE_CCM = 0x1,
};
/* MEP domain */
enum br_cfm_domain {
BR_CFM_PORT,
BR_CFM_VLAN,
};
/* MEP direction */
enum br_cfm_mep_direction {
BR_CFM_MEP_DIRECTION_DOWN,
BR_CFM_MEP_DIRECTION_UP,
};
/* CCM interval supported. */
enum br_cfm_ccm_interval {
BR_CFM_CCM_INTERVAL_NONE,
BR_CFM_CCM_INTERVAL_3_3_MS,
BR_CFM_CCM_INTERVAL_10_MS,
BR_CFM_CCM_INTERVAL_100_MS,
BR_CFM_CCM_INTERVAL_1_SEC,
BR_CFM_CCM_INTERVAL_10_SEC,
BR_CFM_CCM_INTERVAL_1_MIN,
BR_CFM_CCM_INTERVAL_10_MIN,
};
#endif

View File

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_MRP_BRIDGE_H_
#define _UAPI_LINUX_MRP_BRIDGE_H_
#include <linux/types.h>
#include <linux/if_ether.h>
#define MRP_MAX_FRAME_LENGTH 200
#define MRP_DEFAULT_PRIO 0x8000
#define MRP_DOMAIN_UUID_LENGTH 16
#define MRP_VERSION 1
#define MRP_FRAME_PRIO 7
#define MRP_OUI_LENGTH 3
#define MRP_MANUFACTURE_DATA_LENGTH 2
enum br_mrp_ring_role_type {
BR_MRP_RING_ROLE_DISABLED,
BR_MRP_RING_ROLE_MRC,
BR_MRP_RING_ROLE_MRM,
BR_MRP_RING_ROLE_MRA,
};
enum br_mrp_in_role_type {
BR_MRP_IN_ROLE_DISABLED,
BR_MRP_IN_ROLE_MIC,
BR_MRP_IN_ROLE_MIM,
};
enum br_mrp_ring_state_type {
BR_MRP_RING_STATE_OPEN,
BR_MRP_RING_STATE_CLOSED,
};
enum br_mrp_in_state_type {
BR_MRP_IN_STATE_OPEN,
BR_MRP_IN_STATE_CLOSED,
};
enum br_mrp_port_state_type {
BR_MRP_PORT_STATE_DISABLED,
BR_MRP_PORT_STATE_BLOCKED,
BR_MRP_PORT_STATE_FORWARDING,
BR_MRP_PORT_STATE_NOT_CONNECTED,
};
enum br_mrp_port_role_type {
BR_MRP_PORT_ROLE_PRIMARY,
BR_MRP_PORT_ROLE_SECONDARY,
BR_MRP_PORT_ROLE_INTER,
};
enum br_mrp_tlv_header_type {
BR_MRP_TLV_HEADER_END = 0x0,
BR_MRP_TLV_HEADER_COMMON = 0x1,
BR_MRP_TLV_HEADER_RING_TEST = 0x2,
BR_MRP_TLV_HEADER_RING_TOPO = 0x3,
BR_MRP_TLV_HEADER_RING_LINK_DOWN = 0x4,
BR_MRP_TLV_HEADER_RING_LINK_UP = 0x5,
BR_MRP_TLV_HEADER_IN_TEST = 0x6,
BR_MRP_TLV_HEADER_IN_TOPO = 0x7,
BR_MRP_TLV_HEADER_IN_LINK_DOWN = 0x8,
BR_MRP_TLV_HEADER_IN_LINK_UP = 0x9,
BR_MRP_TLV_HEADER_IN_LINK_STATUS = 0xa,
BR_MRP_TLV_HEADER_OPTION = 0x7f,
};
enum br_mrp_sub_tlv_header_type {
BR_MRP_SUB_TLV_HEADER_TEST_MGR_NACK = 0x1,
BR_MRP_SUB_TLV_HEADER_TEST_PROPAGATE = 0x2,
BR_MRP_SUB_TLV_HEADER_TEST_AUTO_MGR = 0x3,
};
#endif

View File

@ -81,6 +81,7 @@ basic_sources = files('''
linux/btrfs_tree.h
linux/can/netlink.h
linux/can/vxcan.h
linux/cfm_bridge.h
linux/fib_rules.h
linux/fou.h
linux/genetlink.h
@ -101,6 +102,7 @@ basic_sources = files('''
linux/l2tp.h
linux/libc-compat.h
linux/loadavg.h
linux/mrp_bridge.h
linux/netdevice.h
linux/netfilter/nf_tables.h
linux/netfilter/nfnetlink.h

View File

@ -34,3 +34,13 @@
#ifndef ETHERTYPE_LLDP
#define ETHERTYPE_LLDP 0x88cc
#endif
/* Not exposed but defined in linux/netdevice.h */
#ifndef MAX_PHYS_ITEM_ID_LEN
#define MAX_PHYS_ITEM_ID_LEN 32
#endif
/* Not exposed but defined in include/net/bonding.h */
#ifndef BOND_MAX_ARP_TARGETS
#define BOND_MAX_ARP_TARGETS 16
#endif

View File

@ -112,7 +112,7 @@ struct netlink_container {
const struct NLTypeSystem *type_system; /* the type system of the container */
size_t offset; /* offset from hdr to the start of the container */
struct netlink_attribute *attributes;
unsigned short n_attributes; /* number of attributes in container */
uint16_t max_attribute; /* the maximum attribute in container */
};
struct sd_netlink_message {

View File

@ -712,7 +712,7 @@ static int netlink_message_read_internal(
if (!m->containers[m->n_containers].attributes)
return -ENODATA;
if (type >= m->containers[m->n_containers].n_attributes)
if (type > m->containers[m->n_containers].max_attribute)
return -ENODATA;
attribute = &m->containers[m->n_containers].attributes[type];
@ -1093,38 +1093,38 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
return 0;
}
static int netlink_container_parse(sd_netlink_message *m,
static int netlink_container_parse(
sd_netlink_message *m,
struct netlink_container *container,
struct rtattr *rta,
size_t rt_len) {
_cleanup_free_ struct netlink_attribute *attributes = NULL;
size_t n = 0;
uint16_t max_attr = 0;
/* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
* LGTM.com analysis does not like the type difference. Hence, here we
* introduce an unsigned short variable as a workaround. */
unsigned short len = rt_len;
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
unsigned short type;
uint16_t attr;
type = RTA_TYPE(rta);
attr = RTA_TYPE(rta);
max_attr = MAX(max_attr, attr);
if (!GREEDY_REALLOC0(attributes, type + 1))
if (!GREEDY_REALLOC0(attributes, (size_t) max_attr + 1))
return -ENOMEM;
if (attributes[type].offset != 0)
if (attributes[attr].offset != 0)
log_debug("sd-netlink: message parse - overwriting repeated attribute");
attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER;
if (type + 1U > n)
n = type + 1U;
attributes[attr].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
attributes[attr].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
attributes[attr].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER;
}
container->attributes = TAKE_PTR(attributes);
container->n_attributes = n;
container->max_attribute = max_attr;
return 0;
}
@ -1259,6 +1259,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
assert_return(m->n_containers > 0, -EINVAL);
m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes);
m->containers[m->n_containers].max_attribute = 0;
m->containers[m->n_containers].type_system = NULL;
m->n_containers--;
@ -1266,6 +1267,15 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
return 0;
}
int sd_netlink_message_get_max_attribute(sd_netlink_message *m, uint16_t *ret) {
assert_return(m, -EINVAL);
assert_return(m->sealed, -EINVAL);
assert_return(ret, -EINVAL);
*ret = m->containers[m->n_containers].max_attribute;
return 0;
}
uint32_t message_get_serial(sd_netlink_message *m) {
assert(m);
assert(m->hdr);

View File

@ -50,18 +50,18 @@ static const NLType genl_batadv_types[] = {
[BATADV_ATTR_ALGO_NAME] = { .type = NETLINK_TYPE_STRING },
[BATADV_ATTR_MESH_IFINDEX] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_MESH_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
[BATADV_ATTR_MESH_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_MESH_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_HARD_IFINDEX] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_HARD_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
[BATADV_ATTR_HARD_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_ORIG_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_HARD_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_ORIG_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_TPMETER_RESULT] = { .type = NETLINK_TYPE_U8 },
[BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_TPMETER_BYTES] = { .type = NETLINK_TYPE_U64 },
[BATADV_ATTR_TPMETER_COOKIE] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_PAD] = { .type = NETLINK_TYPE_UNSPEC },
[BATADV_ATTR_ACTIVE] = { .type = NETLINK_TYPE_FLAG },
[BATADV_ATTR_TT_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_TT_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_TT_TTVN] = { .type = NETLINK_TYPE_U8 },
[BATADV_ATTR_TT_LAST_TTVN] = { .type = NETLINK_TYPE_U8 },
[BATADV_ATTR_TT_CRC32] = { .type = NETLINK_TYPE_U32 },
@ -69,19 +69,19 @@ static const NLType genl_batadv_types[] = {
[BATADV_ATTR_TT_FLAGS] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_FLAG_BEST] = { .type = NETLINK_TYPE_FLAG },
[BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_NEIGH_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_NEIGH_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_TQ] = { .type = NETLINK_TYPE_U8 },
[BATADV_ATTR_THROUGHPUT] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_BANDWIDTH_UP] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_ROUTER] = { .size = ETH_ALEN },
[BATADV_ATTR_ROUTER] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_BLA_OWN] = { .type = NETLINK_TYPE_FLAG },
[BATADV_ATTR_BLA_ADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_BLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_BLA_VID] = { .type = NETLINK_TYPE_U16 },
[BATADV_ATTR_BLA_BACKBONE] = { .size = ETH_ALEN },
[BATADV_ATTR_BLA_BACKBONE] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_BLA_CRC] = { .type = NETLINK_TYPE_U16 },
[BATADV_ATTR_DAT_CACHE_IP4ADDRESS] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_DAT_CACHE_HWADDRESS] = { .size = ETH_ALEN },
[BATADV_ATTR_DAT_CACHE_HWADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
[BATADV_ATTR_DAT_CACHE_VID] = { .type = NETLINK_TYPE_U16 },
[BATADV_ATTR_MCAST_FLAGS] = { .type = NETLINK_TYPE_U32 },
[BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NETLINK_TYPE_U32 },
@ -165,8 +165,8 @@ static const NLType genl_macsec_sa_types[] = {
[MACSEC_SA_ATTR_AN] = { .type = NETLINK_TYPE_U8 },
[MACSEC_SA_ATTR_ACTIVE] = { .type = NETLINK_TYPE_U8 },
[MACSEC_SA_ATTR_PN] = { .type = NETLINK_TYPE_U32 },
[MACSEC_SA_ATTR_KEYID] = { .size = MACSEC_KEYID_LEN },
[MACSEC_SA_ATTR_KEY] = { .size = MACSEC_MAX_KEY_LEN },
[MACSEC_SA_ATTR_KEYID] = { .type = NETLINK_TYPE_BINARY, .size = MACSEC_KEYID_LEN },
[MACSEC_SA_ATTR_KEY] = { .type = NETLINK_TYPE_BINARY, .size = MACSEC_MAX_KEY_LEN },
};
DEFINE_TYPE_SYSTEM(genl_macsec_sa);
@ -195,9 +195,9 @@ static const NLType genl_wireguard_allowedip_types[] = {
DEFINE_TYPE_SYSTEM(genl_wireguard_allowedip);
static const NLType genl_wireguard_peer_types[] = {
[WGPEER_A_PUBLIC_KEY] = { .size = WG_KEY_LEN },
[WGPEER_A_PUBLIC_KEY] = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
[WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
[WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN },
[WGPEER_A_PRESHARED_KEY] = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 },
[WGPEER_A_ENDPOINT] = { .type = NETLINK_TYPE_SOCKADDR },
[WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system },
@ -209,7 +209,7 @@ static const NLType genl_wireguard_types[] = {
[WGDEVICE_A_IFINDEX] = { .type = NETLINK_TYPE_U32 },
[WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
[WGDEVICE_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
[WGDEVICE_A_PRIVATE_KEY] = { .size = WG_KEY_LEN },
[WGDEVICE_A_PRIVATE_KEY] = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
[WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 },
[WGDEVICE_A_FWMARK] = { .type = NETLINK_TYPE_U32 },
[WGDEVICE_A_PEERS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system },

File diff suppressed because it is too large Load Diff

View File

@ -515,19 +515,23 @@ static int netdev_create(NetDev *netdev, Link *link, link_netlink_message_handle
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
if (NETDEV_VTABLE(netdev)->fill_message_create) {
r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
if (NETDEV_VTABLE(netdev)->fill_message_create) {
r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m);
if (r < 0)
return r;
}
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
} else {
r = sd_netlink_message_append_string(m, IFLA_INFO_KIND, netdev_kind_to_string(netdev->kind));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_KIND attribute: %m");
}
r = sd_netlink_message_close_container(m);
if (r < 0)

View File

@ -126,6 +126,7 @@ int sd_netlink_message_get_errno(sd_netlink_message *m);
int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type);
int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags);
int sd_netlink_message_is_broadcast(sd_netlink_message *m);
int sd_netlink_message_get_max_attribute(sd_netlink_message *m, uint16_t *ret);
/* rtnl */
int sd_rtnl_message_get_family(sd_netlink_message *m, int *family);

View File

@ -33,6 +33,8 @@ libudevd_core_sources = '''
udev-builtin-hwdb.c
udev-builtin-input_id.c
udev-builtin-keyboard.c
udev-builtin-net_id-netlink.c
udev-builtin-net_id-netlink.h
udev-builtin-net_id.c
udev-builtin-net_setup_link.c
udev-builtin-path_id.c
@ -210,6 +212,10 @@ tests += [
[threads,
libacl]],
[['src/udev/test-udev-builtin-net_id-netlink.c',
'src/udev/udev-builtin-net_id-netlink.c',
'src/udev/udev-builtin-net_id-netlink.h']],
[['src/udev/fido_id/test-fido-id-desc.c',
'src/udev/fido_id/fido_id_desc.c']],
]

View File

@ -37,7 +37,6 @@ struct LinkConfigContext {
LIST_HEAD(LinkConfig, links);
int ethtool_fd;
bool enable_name_policy;
sd_netlink *rtnl;
usec_t network_dirs_ts_usec;
};
@ -78,7 +77,6 @@ LinkConfigContext *link_config_ctx_free(LinkConfigContext *ctx) {
return NULL;
safe_close(ctx->ethtool_fd);
sd_netlink_unref(ctx->rtnl);
link_configs_free(ctx);
return mfree(ctx);
}
@ -239,7 +237,7 @@ bool link_config_should_reload(LinkConfigContext *ctx) {
return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false);
}
int link_config_get(LinkConfigContext *ctx, sd_device *device, LinkConfig **ret) {
int link_config_get(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, LinkConfig **ret) {
unsigned name_assign_type = NET_NAME_UNKNOWN;
struct ether_addr permanent_mac = {};
unsigned short iftype;
@ -249,6 +247,7 @@ int link_config_get(LinkConfigContext *ctx, sd_device *device, LinkConfig **ret)
int ifindex, r;
assert(ctx);
assert(rtnl);
assert(device);
assert(ret);
@ -260,7 +259,7 @@ int link_config_get(LinkConfigContext *ctx, sd_device *device, LinkConfig **ret)
if (r < 0)
return r;
r = rtnl_get_link_info(&ctx->rtnl, ifindex, &iftype, &flags);
r = rtnl_get_link_info(rtnl, ifindex, &iftype, &flags);
if (r < 0)
return r;
@ -606,13 +605,14 @@ static int link_config_apply_alternative_names(sd_netlink **rtnl, const LinkConf
return 0;
}
int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_device *device, const char **ret_name) {
int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_netlink **rtnl, sd_device *device, const char **ret_name) {
const char *new_name;
sd_device_action_t a;
int r;
assert(ctx);
assert(config);
assert(rtnl);
assert(device);
assert(ret_name);
@ -634,7 +634,7 @@ int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_devic
if (r < 0)
return r;
r = link_config_apply_rtnl_settings(&ctx->rtnl, config, device);
r = link_config_apply_rtnl_settings(rtnl, config, device);
if (r < 0)
return r;
@ -650,7 +650,7 @@ int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_devic
return r;
}
r = link_config_apply_alternative_names(&ctx->rtnl, config, device, new_name);
r = link_config_apply_alternative_names(rtnl, config, device, new_name);
if (r < 0)
return r;

View File

@ -2,6 +2,7 @@
#pragma once
#include "sd-device.h"
#include "sd-netlink.h"
#include "condition.h"
#include "conf-parser.h"
@ -77,8 +78,8 @@ int link_load_one(LinkConfigContext *ctx, const char *filename);
int link_config_load(LinkConfigContext *ctx);
bool link_config_should_reload(LinkConfigContext *ctx);
int link_config_get(LinkConfigContext *ctx, sd_device *device, LinkConfig **ret);
int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_device *device, const char **ret_name);
int link_config_get(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, LinkConfig **ret);
int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_netlink **rtnl, sd_device *device, const char **ret_name);
int link_get_driver(LinkConfigContext *ctx, sd_device *device, char **ret);
const char *name_policy_to_string(NamePolicy p) _const_;

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-device.h"
#include "arphrd-list.h"
#include "ether-addr-util.h"
#include "parse-util.h"
#include "tests.h"
#include "udev-builtin-net_id-netlink.h"
static void test_link_info_one(sd_netlink *rtnl, int ifindex) {
_cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
unsigned iftype, iflink;
const char *s;
log_debug("/* %s(ifindex=%i) */", __func__, ifindex);
assert_se(link_info_get(&rtnl, ifindex, &info) >= 0);
assert_se(sd_device_new_from_ifindex(&dev, ifindex) >= 0);
/* check iftype */
log_debug("iftype: %"PRIu16" (%s)", info.iftype, strna(arphrd_to_name(info.iftype)));
assert_se(sd_device_get_sysattr_value(dev, "type", &s) >= 0);
assert_se(safe_atou(s, &iftype) >= 0);
assert_se(iftype == info.iftype);
/* check hardware address */
log_debug("hardware address: %s", HW_ADDR_TO_STR(&info.hw_addr));
assert_se(sd_device_get_sysattr_value(dev, "address", &s) >= 0);
assert_se(streq(s, HW_ADDR_TO_STR(&info.hw_addr)));
/* check ifname */
log_debug("ifname: %s", info.ifname);
assert_se(sd_device_get_sysname(dev, &s) >= 0);
assert_se(streq(s, info.ifname));
/* check iflink */
log_debug("iflink: %"PRIu32, info.iflink);
assert_se(sd_device_get_sysattr_value(dev, "iflink", &s) >= 0);
assert_se(safe_atou(s, &iflink) >= 0);
assert_se(iflink == info.iflink);
/* check phys_port_name */
log_debug("phys_port_name: %s (%s)",
strna(info.phys_port_name),
info.support_phys_port_name ? "supported" : "unsupported");
if (info.support_phys_port_name) {
s = NULL;
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &s);
assert_se(streq_ptr(s, info.phys_port_name));
}
}
static void test_link_info_get(void) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
log_debug("/* %s */", __func__);
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0) >= 0);
assert_se(sd_netlink_message_request_dump(req, true) >= 0);
assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
uint16_t nlmsg_type;
int ifindex;
assert_se(sd_netlink_message_get_type(reply_one, &nlmsg_type) >= 0);
assert_se(nlmsg_type == RTM_NEWLINK);
assert_se(sd_rtnl_message_link_get_ifindex(reply_one, &ifindex) >= 0);
test_link_info_one(rtnl, ifindex);
}
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_link_info_get();
return 0;
}

View File

@ -233,7 +233,7 @@ static int probe_superblocks(blkid_probe pr) {
return blkid_do_safeprobe(pr);
}
static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_blkid(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
const char *devnode, *root_partition = NULL, *data, *name;
_cleanup_(blkid_free_probep) blkid_probe pr = NULL;
bool noraid = false, is_gpt = false;

View File

@ -12,7 +12,7 @@
#include "udev-builtin.h"
#include "util.h"
static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_btrfs(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -1;
int r;

View File

@ -118,7 +118,7 @@ next:
return r;
}
static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
static const struct option options[] = {
{ "filter", required_argument, NULL, 'f' },
{ "device", required_argument, NULL, 'd' },

View File

@ -322,7 +322,7 @@ static bool test_key(sd_device *dev,
return found;
}
static int builtin_input_id(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_input_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
sd_device *pdev;
unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)];

View File

@ -159,7 +159,7 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
return 0;
}
static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_keyboard(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
unsigned release[1024];
unsigned release_count = 0;
_cleanup_close_ int fd = -1;

View File

@ -20,7 +20,7 @@ _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *fi
log_internalv(priority, 0, file, line, fn, format, args);
}
static int builtin_kmod(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_kmod(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
if (!ctx)
return 0;

View File

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "netlink-util.h"
#include "udev-builtin-net_id-netlink.h"
void link_info_clear(LinkInfo *info) {
if (!info)
return;
info->ifname = mfree(info->ifname);
info->phys_port_name = mfree(info->phys_port_name);
}
int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
_cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
uint16_t nlmsg_type;
int r;
assert(rtnl);
assert(ifindex > 0);
assert(ret);
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, ifindex);
if (r < 0)
return r;
r = sd_netlink_call(*rtnl, message, 0, &reply);
if (r == -EINVAL)
return -ENODEV; /* The device does not exist */
if (r < 0)
return r;
r = sd_netlink_message_get_type(reply, &nlmsg_type);
if (r < 0)
return r;
if (nlmsg_type != RTM_NEWLINK)
return -ENXIO;
r = sd_rtnl_message_link_get_ifindex(reply, &info.ifindex);
if (r < 0)
return r;
if (info.ifindex != ifindex)
return -ENXIO;
r = sd_rtnl_message_link_get_type(reply, &info.iftype);
if (r < 0)
return r;
r = netlink_message_read_hw_addr(reply, IFLA_ADDRESS, &info.hw_addr);
if (r < 0 && r != -ENODATA)
return r;
r = sd_netlink_message_read_string_strdup(reply, IFLA_IFNAME, &info.ifname);
if (r < 0)
return r;
r = sd_netlink_message_read_u32(reply, IFLA_LINK, &info.iflink);
if (r == -ENODATA)
info.iflink = info.ifindex;
else if (r < 0)
return r;
r = sd_netlink_message_read_string_strdup(reply, IFLA_PHYS_PORT_NAME, &info.phys_port_name);
if (r == -ENODATA) {
uint16_t max_attr;
r = sd_netlink_message_get_max_attribute(reply, &max_attr);
if (r < 0)
return r;
info.support_phys_port_name = max_attr >= IFLA_PHYS_PORT_NAME;
} else if (r >= 0)
info.support_phys_port_name = true;
else
return r;
*ret = info;
info = LINK_INFO_NULL;
return 0;
}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-netlink.h"
#include "ether-addr-util.h"
typedef struct LinkInfo {
int ifindex;
uint16_t iftype; /* ARPHRD_* */
struct hw_addr_data hw_addr; /* IFLA_ADDRESS */
char *ifname; /* IFLA_IFNAME */
uint32_t iflink; /* IFLA_LINK */
char *phys_port_name; /* IFLA_PHYS_PORT_NAME */
bool support_phys_port_name;
} LinkInfo;
#define LINK_INFO_NULL ((LinkInfo) {})
void link_info_clear(LinkInfo *info);
int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret);

View File

@ -15,10 +15,11 @@
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <stdarg.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/pci_regs.h>
#include "alloc-util.h"
@ -34,12 +35,13 @@
#include "string-util.h"
#include "strv.h"
#include "strxcpyx.h"
#include "udev-builtin-net_id-netlink.h"
#include "udev-builtin.h"
#define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
#define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
enum netname_type{
typedef enum NetNameType {
NET_UNDEF,
NET_PCI,
NET_USB,
@ -49,13 +51,10 @@ enum netname_type{
NET_VIO,
NET_PLATFORM,
NET_NETDEVSIM,
};
} NetNameType;
struct netnames {
enum netname_type type;
uint8_t mac[6];
bool mac_valid;
typedef struct NetNames {
NetNameType type;
sd_device *pcidev;
char pci_slot[ALTIFNAMSIZ];
@ -69,12 +68,7 @@ struct netnames {
char vio_slot[ALTIFNAMSIZ];
char platform_path[ALTIFNAMSIZ];
char netdevsim_path[ALTIFNAMSIZ];
};
struct virtfn_info {
sd_device *physfn_pcidev;
char suffix[ALTIFNAMSIZ];
};
} NetNames;
/* skip intermediate virtio devices */
static sd_device *skip_virtio(sd_device *dev) {
@ -97,47 +91,45 @@ static sd_device *skip_virtio(sd_device *dev) {
return dev;
}
static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn_info *ret) {
static int get_virtfn_info(sd_device *pcidev, sd_device **ret_physfn_pcidev, char **ret_suffix) {
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
const char *physfn_link_file, *syspath;
_cleanup_free_ char *physfn_pci_syspath = NULL;
_cleanup_free_ char *virtfn_pci_syspath = NULL;
struct dirent *dent;
const char *physfn_syspath, *syspath;
_cleanup_closedir_ DIR *dir = NULL;
char suffix[ALTIFNAMSIZ];
struct dirent *dent;
int r;
assert(dev);
assert(names);
assert(ret);
assert(pcidev);
assert(ret_physfn_pcidev);
assert(ret_suffix);
r = sd_device_get_syspath(names->pcidev, &syspath);
if (r < 0)
return r;
/* Check if this is a virtual function. */
physfn_link_file = strjoina(syspath, "/physfn");
r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath, NULL);
r = sd_device_get_syspath(pcidev, &syspath);
if (r < 0)
return r;
/* Get physical function's pci device. */
r = sd_device_new_from_syspath(&physfn_pcidev, physfn_pci_syspath);
physfn_syspath = strjoina(syspath, "/physfn");
r = sd_device_new_from_syspath(&physfn_pcidev, physfn_syspath);
if (r < 0)
return r;
r = sd_device_get_syspath(physfn_pcidev, &physfn_syspath);
if (r < 0)
return r;
/* Find the virtual function number by finding the right virtfn link. */
dir = opendir(physfn_pci_syspath);
dir = opendir(physfn_syspath);
if (!dir)
return -errno;
FOREACH_DIRENT_ALL(dent, dir, break) {
_cleanup_free_ char *virtfn_link_file = NULL;
_cleanup_free_ char *virtfn_link_file = NULL, *virtfn_pci_syspath = NULL;
const char *n;
if (!startswith(dent->d_name, "virtfn"))
n = startswith(dent->d_name, "virtfn");
if (!n)
continue;
virtfn_link_file = path_join(physfn_pci_syspath, dent->d_name);
virtfn_link_file = path_join(physfn_syspath, dent->d_name);
if (!virtfn_link_file)
return -ENOMEM;
@ -145,20 +137,20 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
continue;
if (streq(syspath, virtfn_pci_syspath)) {
if (!snprintf_ok(suffix, sizeof(suffix), "v%s", &dent->d_name[6]))
return -ENOENT;
char *suffix;
break;
}
}
if (isempty(suffix))
return -ENOENT;
ret->physfn_pcidev = TAKE_PTR(physfn_pcidev);
strncpy(ret->suffix, suffix, sizeof(ret->suffix));
suffix = strjoin("v", n);
if (!suffix)
return -ENOMEM;
*ret_physfn_pcidev = TAKE_PTR(physfn_pcidev);
*ret_suffix = suffix;
return 0;
}
}
return -ENOENT;
}
static bool is_valid_onboard_index(unsigned long idx) {
/* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
@ -171,13 +163,17 @@ static bool is_valid_onboard_index(unsigned long idx) {
}
/* retrieve on-board index number and label from firmware */
static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
static int dev_pci_onboard(sd_device *dev, const LinkInfo *info, NetNames *names) {
unsigned long idx, dev_port = 0;
const char *attr, *port_name = NULL;
const char *attr;
size_t l;
char *s;
int r;
assert(dev);
assert(info);
assert(names);
/* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) < 0) {
/* SMBIOS type 41 — Onboard Devices Extended Information */
@ -202,14 +198,12 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
log_device_debug_errno(dev, r, "Failed to parse dev_port, ignoring: %m");
}
/* kernel provided front panel port name for multiple port PCI device */
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
s = names->pci_onboard;
l = sizeof(names->pci_onboard);
l = strpcpyf(&s, l, "o%lu", idx);
if (port_name)
l = strpcpyf(&s, l, "n%s", port_name);
if (!isempty(info->phys_port_name))
/* kernel provided front panel port name for multiple port PCI device */
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
l = strpcpyf(&s, l, "d%lu", dev_port);
if (l == 0)
@ -313,8 +307,8 @@ static int parse_hotplug_slot_from_function_id(sd_device *dev, const char *slots
return 1;
}
static int dev_pci_slot(sd_device *dev, struct netnames *names) {
const char *sysname, *attr, *port_name = NULL, *syspath;
static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
const char *sysname, *attr, *syspath;
_cleanup_(sd_device_unrefp) sd_device *pci = NULL;
_cleanup_closedir_ DIR *dir = NULL;
unsigned domain, bus, slot, func;
@ -325,6 +319,10 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
size_t l;
int r;
assert(dev);
assert(info);
assert(names);
r = sd_device_get_sysname(names->pcidev, &sysname);
if (r < 0)
return r;
@ -363,9 +361,6 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
}
}
/* kernel provided front panel port name for multi-port PCI device */
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
/* compose a name based on the raw kernel's PCI bus, slot numbers */
s = names->pci_path;
l = sizeof(names->pci_path);
@ -374,8 +369,9 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
l = strpcpyf(&s, l, "p%us%u", bus, slot);
if (func > 0 || is_pci_multifunction(names->pcidev))
l = strpcpyf(&s, l, "f%u", func);
if (port_name)
l = strpcpyf(&s, l, "n%s", port_name);
if (!isempty(info->phys_port_name))
/* kernel provided front panel port name for multi-port PCI device */
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
l = strpcpyf(&s, l, "d%lu", dev_port);
if (l == 0)
@ -455,8 +451,8 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
if (func > 0 || is_pci_multifunction(names->pcidev))
l = strpcpyf(&s, l, "f%d", func);
if (port_name)
l = strpcpyf(&s, l, "n%s", port_name);
if (!isempty(info->phys_port_name))
l = strpcpyf(&s, l, "n%s", info->phys_port_name);
else if (dev_port > 0)
l = strpcpyf(&s, l, "d%lu", dev_port);
if (l == 0)
@ -466,7 +462,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
return 0;
}
static int names_vio(sd_device *dev, struct netnames *names) {
static int names_vio(sd_device *dev, NetNames *names) {
sd_device *parent;
unsigned busid, slotid, ethid;
const char *syspath, *subsystem;
@ -503,7 +499,7 @@ static int names_vio(sd_device *dev, struct netnames *names) {
#define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
#define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
static int names_platform(sd_device *dev, struct netnames *names, bool test) {
static int names_platform(sd_device *dev, NetNames *names, bool test) {
sd_device *parent;
char vendor[5];
unsigned model, instance, ethid;
@ -558,14 +554,15 @@ static int names_platform(sd_device *dev, struct netnames *names, bool test) {
return 0;
}
static int names_pci(sd_device *dev, struct netnames *names) {
static int names_pci(sd_device *dev, const LinkInfo *info, NetNames *names) {
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
_cleanup_free_ char *virtfn_suffix = NULL;
sd_device *parent;
struct netnames vf_names = {};
struct virtfn_info vf_info = {};
const char *subsystem;
int r;
assert(dev);
assert(info);
assert(names);
r = sd_device_get_parent(dev, &parent);
@ -589,33 +586,35 @@ static int names_pci(sd_device *dev, struct netnames *names) {
}
if (naming_scheme_has(NAMING_SR_IOV_V) &&
get_virtfn_info(dev, names, &vf_info) >= 0) {
get_virtfn_info(names->pcidev, &physfn_pcidev, &virtfn_suffix) >= 0) {
NetNames vf_names = {};
/* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
vf_names.pcidev = vf_info.physfn_pcidev;
dev_pci_onboard(dev, &vf_names);
dev_pci_slot(dev, &vf_names);
vf_names.pcidev = physfn_pcidev;
dev_pci_onboard(dev, info, &vf_names);
dev_pci_slot(dev, info, &vf_names);
if (vf_names.pci_onboard[0])
if (strlen(vf_names.pci_onboard) + strlen(vf_info.suffix) < sizeof(names->pci_onboard))
if (strlen(vf_names.pci_onboard) + strlen(virtfn_suffix) < sizeof(names->pci_onboard))
strscpyl(names->pci_onboard, sizeof(names->pci_onboard),
vf_names.pci_onboard, vf_info.suffix, NULL);
vf_names.pci_onboard, virtfn_suffix, NULL);
if (vf_names.pci_slot[0])
if (strlen(vf_names.pci_slot) + strlen(vf_info.suffix) < sizeof(names->pci_slot))
if (strlen(vf_names.pci_slot) + strlen(virtfn_suffix) < sizeof(names->pci_slot))
strscpyl(names->pci_slot, sizeof(names->pci_slot),
vf_names.pci_slot, vf_info.suffix, NULL);
vf_names.pci_slot, virtfn_suffix, NULL);
if (vf_names.pci_path[0])
if (strlen(vf_names.pci_path) + strlen(vf_info.suffix) < sizeof(names->pci_path))
if (strlen(vf_names.pci_path) + strlen(virtfn_suffix) < sizeof(names->pci_path))
strscpyl(names->pci_path, sizeof(names->pci_path),
vf_names.pci_path, vf_info.suffix, NULL);
sd_device_unref(vf_info.physfn_pcidev);
vf_names.pci_path, virtfn_suffix, NULL);
} else {
dev_pci_onboard(dev, names);
dev_pci_slot(dev, names);
dev_pci_onboard(dev, info, names);
dev_pci_slot(dev, info, names);
}
return 0;
}
static int names_usb(sd_device *dev, struct netnames *names) {
static int names_usb(sd_device *dev, NetNames *names) {
sd_device *usbdev;
char name[256], *ports, *config, *interf, *s;
const char *sysname;
@ -673,7 +672,7 @@ static int names_usb(sd_device *dev, struct netnames *names) {
return 0;
}
static int names_bcma(sd_device *dev, struct netnames *names) {
static int names_bcma(sd_device *dev, NetNames *names) {
sd_device *bcmadev;
unsigned core;
const char *sysname;
@ -701,7 +700,7 @@ static int names_bcma(sd_device *dev, struct netnames *names) {
return 0;
}
static int names_ccw(sd_device *dev, struct netnames *names) {
static int names_ccw(sd_device *dev, NetNames *names) {
sd_device *cdev;
const char *bus_id, *subsys;
size_t bus_id_len;
@ -759,76 +758,49 @@ static int names_ccw(sd_device *dev, struct netnames *names) {
return 0;
}
static int names_mac(sd_device *dev, struct netnames *names) {
static int names_mac(sd_device *dev, const LinkInfo *info) {
const char *s;
unsigned long i;
unsigned a1, a2, a3, a4, a5, a6;
unsigned i;
int r;
/* Some kinds of devices tend to have hardware addresses
* that are impossible to use in an iface name.
*/
r = sd_device_get_sysattr_value(dev, "type", &s);
if (r < 0)
return r;
assert(dev);
assert(info);
r = safe_atolu_full(s, 10, &i);
if (r < 0)
return r;
switch (i) {
/* The persistent part of a hardware address of an InfiniBand NIC
* is 8 bytes long. We cannot fit this much in an iface name.
*/
case ARPHRD_INFINIBAND:
return -EINVAL;
default:
break;
}
/* The persistent part of a hardware address of an InfiniBand NIC is 8 bytes long. We cannot
* fit this much in an iface name.
* TODO: but it can be used as alternative names?? */
if (info->iftype == ARPHRD_INFINIBAND || info->hw_addr.length != 6)
return -EOPNOTSUPP;
/* check for NET_ADDR_PERM, skip random MAC addresses */
r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
if (r < 0)
return r;
r = safe_atolu(s, &i);
r = safe_atou(s, &i);
if (r < 0)
return r;
if (i != 0)
return 0;
r = sd_device_get_sysattr_value(dev, "address", &s);
if (r < 0)
return r;
if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6)
if (i != NET_ADDR_PERM)
return -EINVAL;
/* skip empty MAC addresses */
if (a1 + a2 + a3 + a4 + a5 + a6 == 0)
return -EINVAL;
names->mac[0] = a1;
names->mac[1] = a2;
names->mac[2] = a3;
names->mac[3] = a4;
names->mac[4] = a5;
names->mac[5] = a6;
names->mac_valid = true;
return 0;
}
static int names_netdevsim(sd_device *dev, struct netnames *names) {
static int names_netdevsim(sd_device *dev, const LinkInfo *info, NetNames *names) {
sd_device *netdevsimdev;
const char *sysname;
unsigned addr;
const char *port_name = NULL;
int r;
bool ok;
if (!naming_scheme_has(NAMING_NETDEVSIM))
return 0;
assert(dev);
assert(info);
assert(names);
if (isempty(info->phys_port_name))
return -EINVAL;
r = sd_device_get_parent_with_subsystem_devtype(dev, "netdevsim", NULL, &netdevsimdev);
if (r < 0)
return r;
@ -839,12 +811,7 @@ static int names_netdevsim(sd_device *dev, struct netnames *names) {
if (sscanf(sysname, "netdevsim%u", &addr) != 1)
return -EINVAL;
r = sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
if (r < 0)
return r;
ok = snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, port_name);
if (!ok)
if (!snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, info->phys_port_name))
return -ENOBUFS;
names->type = NET_NETDEVSIM;
@ -853,36 +820,62 @@ static int names_netdevsim(sd_device *dev, struct netnames *names) {
}
/* IEEE Organizationally Unique Identifier vendor string */
static int ieee_oui(sd_device *dev, struct netnames *names, bool test) {
static int ieee_oui(sd_device *dev, const LinkInfo *info, bool test) {
char str[32];
if (!names->mac_valid)
return -ENOENT;
assert(dev);
assert(info);
if (info->hw_addr.length != 6)
return -EOPNOTSUPP;
/* skip commonly misused 00:00:00 (Xerox) prefix */
if (memcmp(names->mac, "\0\0\0", 3) == 0)
if (info->hw_addr.bytes[0] == 0 &&
info->hw_addr.bytes[1] == 0 &&
info->hw_addr.bytes[2] == 0)
return -EINVAL;
xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X", names->mac[0],
names->mac[1], names->mac[2], names->mac[3], names->mac[4],
names->mac[5]);
udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
return 0;
xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X",
info->hw_addr.bytes[0],
info->hw_addr.bytes[1],
info->hw_addr.bytes[2],
info->hw_addr.bytes[3],
info->hw_addr.bytes[4],
info->hw_addr.bytes[5]);
return udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
}
static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
const char *s, *p, *devtype, *prefix = "en";
struct netnames names = {};
unsigned long i;
int r;
static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
_cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
const char *devtype, *prefix = "en";
NetNames names = {};
int ifindex, r;
r = sd_device_get_ifindex(dev, &ifindex);
if (r < 0)
return r;
r = link_info_get(rtnl, ifindex, &info);
if (r < 0)
return r;
if (!info.support_phys_port_name) {
const char *s;
r = sd_device_get_sysattr_value(dev, "phys_port_name", &s);
if (r >= 0) {
info.phys_port_name = strdup(s);
if (!info.phys_port_name)
return log_oom();
}
}
/* skip stacked devices, like VLANs, ... */
if (info.ifindex != (int) info.iflink)
return 0;
/* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
r = sd_device_get_sysattr_value(dev, "type", &s);
if (r < 0)
return r;
r = safe_atolu_full(s, 10, &i);
if (r < 0)
return r;
switch (i) {
switch (info.iftype) {
case ARPHRD_ETHER:
prefix = "en";
break;
@ -899,16 +892,6 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
return 0;
}
/* skip stacked devices, like VLANs, ... */
r = sd_device_get_sysattr_value(dev, "ifindex", &s);
if (r < 0)
return r;
r = sd_device_get_sysattr_value(dev, "iflink", &p);
if (r < 0)
return r;
if (!streq(s, p))
return 0;
if (sd_device_get_devtype(dev, &devtype) >= 0) {
if (streq("wlan", devtype))
prefix = "wl";
@ -918,16 +901,13 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
r = names_mac(dev, &names);
if (r >= 0 && names.mac_valid) {
if (names_mac(dev, &info) >= 0) {
char str[ALTIFNAMSIZ];
xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix,
names.mac[0], names.mac[1], names.mac[2],
names.mac[3], names.mac[4], names.mac[5]);
xsprintf(str, "%s%s", prefix, HW_ADDR_TO_STR(&info.hw_addr));
udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
ieee_oui(dev, &names, test);
ieee_oui(dev, &info, test);
}
/* get path names for Linux on System z network devices */
@ -958,7 +938,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
}
/* get netdevsim path names */
if (names_netdevsim(dev, &names) >= 0 && names.type == NET_NETDEVSIM) {
if (names_netdevsim(dev, &info, &names) >= 0 && names.type == NET_NETDEVSIM) {
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path))
@ -968,7 +948,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
}
/* get PCI based path names, we compose only PCI based paths */
if (names_pci(dev, &names) < 0)
if (names_pci(dev, &info, &names) < 0)
return 0;
/* plain PCI device */

View File

@ -10,7 +10,7 @@
static LinkConfigContext *ctx = NULL;
static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool test) {
static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, char **argv, bool test) {
_cleanup_free_ char *driver = NULL;
const char *name = NULL;
LinkConfig *link;
@ -26,7 +26,7 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
else
udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver);
r = link_config_get(ctx, dev, &link);
r = link_config_get(ctx, rtnl, dev, &link);
if (r < 0) {
if (r == -ENODEV)
return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it.");
@ -38,7 +38,7 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
r = link_config_apply(ctx, link, dev, &name);
r = link_config_apply(ctx, link, rtnl, dev, &name);
if (r == -ENODEV)
log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
else if (r < 0)

View File

@ -530,7 +530,7 @@ static sd_device *handle_ap(sd_device *parent, char **path) {
return skip_subsystem(parent, "ap");
}
static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_path_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
sd_device *parent;
_cleanup_free_ char *path = NULL;
_cleanup_free_ char *compat_path = NULL;

View File

@ -16,7 +16,7 @@
#include "log.h"
#include "udev-builtin.h"
static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_uaccess(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
const char *path = NULL, *seat;
bool changed_acl = false;
uid_t uid;

View File

@ -224,7 +224,7 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
* 6.) If the device supplies a serial number, this number
* is concatenated with the identification with an underscore '_'.
*/
static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
static int builtin_usb_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
char vendor_str[64] = "";
char vendor_str_enc[256];
const char *vendor_id;

View File

@ -107,7 +107,7 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) {
return _UDEV_BUILTIN_INVALID;
}
int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test) {
int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test) {
_cleanup_strv_free_ char **argv = NULL;
int r;
@ -124,7 +124,7 @@ int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command
/* we need '0' here to reset the internal state */
optind = 0;
return builtins[cmd]->cmd(dev, strv_length(argv), argv, test);
return builtins[cmd]->cmd(dev, rtnl, strv_length(argv), argv, test);
}
int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) {

View File

@ -4,6 +4,7 @@
#include <stdbool.h>
#include "sd-device.h"
#include "sd-netlink.h"
typedef enum {
#if HAVE_BLKID
@ -29,7 +30,7 @@ typedef enum {
typedef struct UdevBuiltin {
const char *name;
int (*cmd)(sd_device *dev, int argc, char *argv[], bool test);
int (*cmd)(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test);
const char *help;
int (*init)(void);
void (*exit)(void);
@ -73,7 +74,7 @@ void udev_builtin_exit(void);
UdevBuiltinCommand udev_builtin_lookup(const char *command);
const char *udev_builtin_name(UdevBuiltinCommand cmd);
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test);
int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test);
void udev_builtin_list(void);
bool udev_builtin_validate(void);
int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val);

View File

@ -1073,7 +1073,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s
if (builtin_cmd != _UDEV_BUILTIN_INVALID) {
log_device_debug(event->dev, "Running built-in command \"%s\"", command);
r = udev_builtin_run(event->dev, builtin_cmd, command, false);
r = udev_builtin_run(event->dev, &event->rtnl, builtin_cmd, command, false);
if (r < 0)
log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
} else {

View File

@ -1829,7 +1829,7 @@ static int udev_rule_apply_token_to_event(
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
log_rule_debug(dev, rules, "Importing properties from results of builtin command '%s'", buf);
r = udev_builtin_run(dev, cmd, buf, false);
r = udev_builtin_run(dev, &event->rtnl, cmd, buf, false);
if (r < 0) {
/* remember failure */
log_rule_debug_errno(dev, rules, r, "Failed to run builtin '%s': %m", buf);

View File

@ -72,6 +72,7 @@ static int parse_argv(int argc, char *argv[]) {
}
int builtin_main(int argc, char *argv[], void *userdata) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
UdevBuiltinCommand cmd;
int r;
@ -97,7 +98,7 @@ int builtin_main(int argc, char *argv[], void *userdata) {
goto finish;
}
r = udev_builtin_run(dev, cmd, arg_command, true);
r = udev_builtin_run(dev, &rtnl, cmd, arg_command, true);
if (r < 0)
log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command);