diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
commit | fc53809803cd2bc2434e312b19a18fa36776da12 (patch) | |
tree | b4b43bd6538f51965ce32856e9c053d0f90919c8 /src/libsystemd/sd-netlink | |
parent | Adding upstream version 255.5. (diff) | |
download | systemd-fc53809803cd2bc2434e312b19a18fa36776da12.tar.xz systemd-fc53809803cd2bc2434e312b19a18fa36776da12.zip |
Adding upstream version 256.upstream/256
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message-rtnl.c | 41 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 29 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types-genl.c | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types-rtnl.c | 13 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-util.c | 421 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-util.h | 56 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/sd-netlink.c | 8 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/test-netlink.c | 14 |
8 files changed, 299 insertions, 284 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-message-rtnl.c b/src/libsystemd/sd-netlink/netlink-message-rtnl.c index 008e802..fb11c7e 100644 --- a/src/libsystemd/sd-netlink/netlink-message-rtnl.c +++ b/src/libsystemd/sd-netlink/netlink-message-rtnl.c @@ -56,6 +56,10 @@ static bool rtnl_message_type_is_mdb(uint16_t type) { return IN_SET(type, RTM_NEWMDB, RTM_DELMDB, RTM_GETMDB); } +static bool rtnl_message_type_is_nsid(uint16_t type) { + return IN_SET(type, RTM_NEWNSID, RTM_DELNSID, RTM_GETNSID); +} + int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { struct rtmsg *rtm; @@ -92,6 +96,20 @@ int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char return 0; } +int sd_rtnl_message_route_set_tos(sd_netlink_message *m, unsigned char tos) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_tos = tos; + + return 0; +} + int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) { struct rtmsg *rtm; @@ -336,7 +354,7 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, return r; if (nlmsg_type == RTM_NEWNEXTHOP) - (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nhm = NLMSG_DATA((*ret)->hdr); @@ -1202,3 +1220,24 @@ int sd_rtnl_message_new_mdb( return 0; } + +int sd_rtnl_message_new_nsid( + sd_netlink *rtnl, + sd_netlink_message **ret, + uint16_t nlmsg_type) { + + struct rtgenmsg *rt; + int r; + + assert_return(rtnl_message_type_is_nsid(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + rt = NLMSG_DATA((*ret)->hdr); + rt->rtgen_family = AF_UNSPEC; + + return 0; +} diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 000a50e..49d000d 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -17,9 +17,6 @@ #define GET_CONTAINER(m, i) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset)) -#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) -#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) - int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) { sd_netlink_message *m; @@ -789,32 +786,6 @@ int sd_netlink_message_read_data(sd_netlink_message *m, uint16_t attr_type, size if (ret_data) { void *data; - data = memdup(attr_data, r); - if (!data) - return -ENOMEM; - - *ret_data = data; - } - - if (ret_size) - *ret_size = r; - - return r; -} - -int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, uint16_t attr_type, size_t *ret_size, void **ret_data) { - void *attr_data; - int r; - - assert_return(m, -EINVAL); - - r = netlink_message_read_internal(m, attr_type, &attr_data, NULL); - if (r < 0) - return r; - - if (ret_data) { - void *data; - data = memdup_suffix0(attr_data, r); if (!data) return -ENOMEM; diff --git a/src/libsystemd/sd-netlink/netlink-types-genl.c b/src/libsystemd/sd-netlink/netlink-types-genl.c index 6fe9adc..226ac86 100644 --- a/src/libsystemd/sd-netlink/netlink-types-genl.c +++ b/src/libsystemd/sd-netlink/netlink-types-genl.c @@ -199,6 +199,7 @@ static const NLAPolicy genl_nl80211_policies[] = { [NL80211_ATTR_SSID] = BUILD_POLICY_WITH_SIZE(BINARY, IEEE80211_MAX_SSID_LEN), [NL80211_ATTR_STATUS_CODE] = BUILD_POLICY(U16), [NL80211_ATTR_4ADDR] = BUILD_POLICY(U8), + [NL80211_ATTR_NETNS_FD] = BUILD_POLICY(U32), }; /***************** genl wireguard type systems *****************/ diff --git a/src/libsystemd/sd-netlink/netlink-types-rtnl.c b/src/libsystemd/sd-netlink/netlink-types-rtnl.c index 0153456..e39a75c 100644 --- a/src/libsystemd/sd-netlink/netlink-types-rtnl.c +++ b/src/libsystemd/sd-netlink/netlink-types-rtnl.c @@ -17,6 +17,7 @@ #include <linux/if_tunnel.h> #include <linux/ip.h> #include <linux/l2tp.h> +#include <linux/net_namespace.h> #include <linux/netlink.h> #include <linux/nexthop.h> #include <linux/nl80211.h> @@ -123,6 +124,7 @@ static const NLAPolicy rtnl_link_info_data_bond_policies[] = { [IFLA_BOND_AD_ACTOR_SYSTEM] = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN), [IFLA_BOND_TLB_DYNAMIC_LB] = BUILD_POLICY(U8), [IFLA_BOND_PEER_NOTIF_DELAY] = BUILD_POLICY(U32), + [IFLA_BOND_MISSED_MAX] = BUILD_POLICY(U8), }; static const NLAPolicy rtnl_link_info_data_bridge_policies[] = { @@ -306,6 +308,7 @@ static const NLAPolicy rtnl_link_info_data_macvlan_policies[] = { [IFLA_MACVLAN_MACADDR_COUNT] = BUILD_POLICY(U32), [IFLA_MACVLAN_BC_QUEUE_LEN] = BUILD_POLICY(U32), [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = BUILD_POLICY(U32), + [IFLA_MACVLAN_BC_CUTOFF] = BUILD_POLICY(S32), }; static const NLAPolicy rtnl_link_info_data_tun_policies[] = { @@ -1185,6 +1188,13 @@ static const NLAPolicy rtnl_mdb_policies[] = { DEFINE_POLICY_SET(rtnl_mdb); +static const NLAPolicy rtnl_nsid_policies[] = { + [NETNSA_FD] = BUILD_POLICY(S32), + [NETNSA_NSID] = BUILD_POLICY(U32), +}; + +DEFINE_POLICY_SET(rtnl_nsid); + static const NLAPolicy rtnl_policies[] = { [RTM_NEWLINK] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)), [RTM_DELLINK] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)), @@ -1220,6 +1230,9 @@ static const NLAPolicy rtnl_policies[] = { [RTM_NEWMDB] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)), [RTM_DELMDB] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)), [RTM_GETMDB] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)), + [RTM_NEWNSID] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nsid, sizeof(struct rtgenmsg)), + [RTM_DELNSID] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nsid, sizeof(struct rtgenmsg)), + [RTM_GETNSID] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nsid, sizeof(struct rtgenmsg)), }; DEFINE_POLICY_SET(rtnl); diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 832159a..9061609 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -11,6 +11,154 @@ #include "process-util.h" #include "strv.h" +static int parse_newlink_message( + sd_netlink_message *message, + char **ret_name, + char ***ret_altnames) { + + _cleanup_strv_free_ char **altnames = NULL; + int r, ifindex; + + assert(message); + + uint16_t type; + r = sd_netlink_message_get_type(message, &type); + if (r < 0) + return r; + if (type != RTM_NEWLINK) + return -EPROTO; + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) + return r; + if (ifindex <= 0) + return -EPROTO; + + if (ret_altnames) { + r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &altnames); + if (r < 0 && r != -ENODATA) + return r; + } + + if (ret_name) { + r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, ret_name); + if (r < 0) + return r; + } + + if (ret_altnames) + *ret_altnames = TAKE_PTR(altnames); + + return ifindex; +} + +int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + int r; + + assert(ifindex > 0); + + /* This is similar to if_indextoname(), but also optionally provides alternative names. */ + + if (!rtnl) + rtnl = &our_rtnl; + 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 < 0) + return r; + + return parse_newlink_message(reply, ret_name, ret_altnames); +} + +int rtnl_resolve_ifname_full( + sd_netlink **rtnl, + ResolveInterfaceNameFlag flags, + const char *name, + char **ret_name, + char ***ret_altnames) { + + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + int r; + + assert(name); + assert(flags > 0); + + /* This is similar to if_nametoindex(), but also resolves alternative names and decimal formatted + * ifindex too. Returns ifindex, and optionally provides the main interface name and alternative + * names.*/ + + if (!rtnl) + rtnl = &our_rtnl; + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + /* First, use IFLA_IFNAME */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_MAIN) && ifname_valid(name)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, &reply); + if (r >= 0) + return parse_newlink_message(reply, ret_name, ret_altnames); + if (r != -ENODEV) + return r; + } + + /* Next, try IFLA_ALT_IFNAME */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_ALTERNATIVE) && + ifname_valid_full(name, IFNAME_VALID_ALTERNATIVE)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(message, IFLA_ALT_IFNAME, name); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, &reply); + if (r >= 0) + return parse_newlink_message(reply, ret_name, ret_altnames); + /* The kernels older than 76c9ac0ee878f6693d398d3a95ccaf85e1f597a6 (v5.5) return -EINVAL. */ + if (!IN_SET(r, -ENODEV, -EINVAL)) + return r; + } + + /* Finally, assume the string is a decimal formatted ifindex. */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_NUMERIC)) { + int ifindex; + + ifindex = parse_ifindex(name); + if (ifindex <= 0) + return -ENODEV; + + return rtnl_get_ifname_full(rtnl, ifindex, ret_name, ret_altnames); + } + + return -ENODEV; +} + static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; @@ -20,6 +168,13 @@ static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { assert(name); /* Assign the requested name. */ + + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); if (r < 0) return r; @@ -31,6 +186,37 @@ static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { return sd_netlink_call(*rtnl, message, 0, NULL); } +int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_name) { + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + int r, ifindex; + + assert(orig_name); + assert(new_name); + + /* This does not check alternative names. Callers must check the requested name is not used as an + * alternative name. */ + + if (streq(orig_name, new_name)) + return 0; + + if (!ifname_valid(new_name)) + return -EINVAL; + + if (!rtnl) + rtnl = &our_rtnl; + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + ifindex = rtnl_resolve_ifname(rtnl, orig_name); + if (ifindex < 0) + return ifindex; + + return set_link_name(rtnl, ifindex, new_name); +} + int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const *alternative_names) { _cleanup_strv_free_ char **original_altnames = NULL, **new_altnames = NULL; bool altname_deleted = false; @@ -204,38 +390,6 @@ int rtnl_set_link_properties( return 0; } -int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; - _cleanup_strv_free_ char **names = NULL; - 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 < 0) - return r; - - r = sd_netlink_message_read_strv(reply, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names); - if (r < 0 && r != -ENODATA) - return r; - - *ret = TAKE_PTR(names); - - return 0; -} - static int rtnl_update_link_alternative_names( sd_netlink **rtnl, uint16_t nlmsg_type, @@ -336,92 +490,6 @@ int rtnl_set_link_alternative_names_by_ifname( return 0; } -int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) { - _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; - int r, ifindex; - - assert(name); - - /* This returns ifindex and the main interface name. */ - - if (!ifname_valid_full(name, IFNAME_VALID_ALTERNATIVE)) - return -EINVAL; - - if (!rtnl) - rtnl = &our_rtnl; - if (!*rtnl) { - r = sd_netlink_open(rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); - if (r < 0) - return r; - - r = sd_netlink_message_append_string(message, IFLA_ALT_IFNAME, name); - if (r < 0) - return r; - - r = sd_netlink_call(*rtnl, message, 0, &reply); - if (r == -EINVAL) - return -ENODEV; /* The device doesn't exist */ - if (r < 0) - return r; - - r = sd_rtnl_message_link_get_ifindex(reply, &ifindex); - if (r < 0) - return r; - assert(ifindex > 0); - - if (ret) { - r = sd_netlink_message_read_string_strdup(reply, IFLA_IFNAME, ret); - if (r < 0) - return r; - } - - return ifindex; -} - -int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name) { - int r; - - /* Like if_nametoindex, but resolves "alternative names" too. */ - - assert(name); - - r = if_nametoindex(name); - if (r > 0) - return r; - - return rtnl_resolve_link_alternative_name(rtnl, name, NULL); -} - -int rtnl_resolve_interface(sd_netlink **rtnl, const char *name) { - int r; - - /* Like rtnl_resolve_ifname, but resolves interface numbers too. */ - - assert(name); - - r = parse_ifindex(name); - if (r > 0) - return r; - assert(r < 0); - - return rtnl_resolve_ifname(rtnl, name); -} - -int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name) { - int r; - - r = rtnl_resolve_interface(rtnl, name); - if (r < 0) - return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name); - return r; -} - int rtnl_get_link_info( sd_netlink **rtnl, int ifindex, @@ -441,7 +509,7 @@ int rtnl_get_link_info( assert(rtnl); assert(ifindex > 0); - if (!ret_iftype && !ret_flags) + if (!ret_iftype && !ret_flags && !ret_kind && !ret_hw_addr && !ret_permanent_hw_addr) return 0; if (!*rtnl) { @@ -575,121 +643,6 @@ int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void return 0; } -MultipathRoute *multipath_route_free(MultipathRoute *m) { - if (!m) - return NULL; - - free(m->ifname); - - return mfree(m); -} - -int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret) { - _cleanup_(multipath_route_freep) MultipathRoute *n = NULL; - _cleanup_free_ char *ifname = NULL; - - assert(m); - assert(ret); - - if (m->ifname) { - ifname = strdup(m->ifname); - if (!ifname) - return -ENOMEM; - } - - n = new(MultipathRoute, 1); - if (!n) - return -ENOMEM; - - *n = (MultipathRoute) { - .gateway = m->gateway, - .weight = m->weight, - .ifindex = m->ifindex, - .ifname = TAKE_PTR(ifname), - }; - - *ret = TAKE_PTR(n); - - return 0; -} - -int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) { - _cleanup_ordered_set_free_free_ OrderedSet *set = NULL; - int r; - - assert(rtnh); - assert(IN_SET(family, AF_INET, AF_INET6)); - - if (size < sizeof(struct rtnexthop)) - return -EBADMSG; - - for (; size >= sizeof(struct rtnexthop); ) { - _cleanup_(multipath_route_freep) MultipathRoute *m = NULL; - - if (NLMSG_ALIGN(rtnh->rtnh_len) > size) - return -EBADMSG; - - if (rtnh->rtnh_len < sizeof(struct rtnexthop)) - return -EBADMSG; - - m = new(MultipathRoute, 1); - if (!m) - return -ENOMEM; - - *m = (MultipathRoute) { - .ifindex = rtnh->rtnh_ifindex, - .weight = rtnh->rtnh_hops, - }; - - if (rtnh->rtnh_len > sizeof(struct rtnexthop)) { - size_t len = rtnh->rtnh_len - sizeof(struct rtnexthop); - - for (struct rtattr *attr = RTNH_DATA(rtnh); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { - if (attr->rta_type == RTA_GATEWAY) { - if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(family))) - return -EBADMSG; - - m->gateway.family = family; - memcpy(&m->gateway.address, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(family)); - break; - } else if (attr->rta_type == RTA_VIA) { - uint16_t gw_family; - - if (family != AF_INET) - return -EINVAL; - - if (attr->rta_len < RTA_LENGTH(sizeof(uint16_t))) - return -EBADMSG; - - gw_family = *(uint16_t *) RTA_DATA(attr); - - if (gw_family != AF_INET6) - return -EBADMSG; - - if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family))) - return -EBADMSG; - - memcpy(&m->gateway, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family)); - break; - } - } - } - - r = ordered_set_ensure_put(&set, NULL, m); - if (r < 0) - return r; - - TAKE_PTR(m); - - size -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - - if (ret) - *ret = TAKE_PTR(set); - return 0; -} - bool netlink_pid_changed(sd_netlink *nl) { /* We don't support people creating an nl connection and * keeping it around over a fork(). Let's complain. */ diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index 369f5d5..4ba64f0 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -10,24 +10,32 @@ #include "ordered-set.h" #include "socket-util.h" +#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) +#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) + /* See struct rtvia in rtnetlink.h */ typedef struct RouteVia { uint16_t family; union in_addr_union address; } _packed_ RouteVia; -typedef struct MultipathRoute { - RouteVia gateway; - uint32_t weight; - int ifindex; - char *ifname; -} MultipathRoute; +int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames); -MultipathRoute *multipath_route_free(MultipathRoute *m); -DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free); +typedef enum ResolveInterfaceNameFlag { + RESOLVE_IFNAME_MAIN = 1 << 0, /* resolve main interface name */ + RESOLVE_IFNAME_ALTERNATIVE = 1 << 1, /* resolve alternative name */ + RESOLVE_IFNAME_NUMERIC = 1 << 2, /* resolve decimal formatted ifindex */ + _RESOLVE_IFNAME_ALL = RESOLVE_IFNAME_MAIN | RESOLVE_IFNAME_ALTERNATIVE | RESOLVE_IFNAME_NUMERIC, +} ResolveInterfaceNameFlag; -int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret); +int rtnl_resolve_ifname_full( + sd_netlink **rtnl, + ResolveInterfaceNameFlag flags, + const char *name, + char **ret_name, + char ***ret_altnames); +int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_name); int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const* alternative_names); static inline int rtnl_append_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names) { return rtnl_set_link_name(rtnl, ifindex, NULL, alternative_names); @@ -43,14 +51,32 @@ int rtnl_set_link_properties( uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments); -int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret); +static inline int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) { + return rtnl_get_ifname_full(rtnl, ifindex, NULL, ret); +} int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names); int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char* const *alternative_names); int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names); -int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret); -int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name); -int rtnl_resolve_interface(sd_netlink **rtnl, const char *name); -int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name); +static inline int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) { + return rtnl_resolve_ifname_full(rtnl, RESOLVE_IFNAME_ALTERNATIVE, name, ret, NULL); +} +static inline int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name) { + return rtnl_resolve_ifname_full(rtnl, RESOLVE_IFNAME_MAIN | RESOLVE_IFNAME_ALTERNATIVE, name, NULL, NULL); +} +static inline int rtnl_resolve_interface(sd_netlink **rtnl, const char *name) { + return rtnl_resolve_ifname_full(rtnl, _RESOLVE_IFNAME_ALL, name, NULL, NULL); +} +static inline int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name) { + int r; + + assert(name); + + r = rtnl_resolve_interface(rtnl, name); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name); + return r; +} + int rtnl_get_link_info( sd_netlink **rtnl, int ifindex, @@ -103,8 +129,6 @@ int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short typ void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length); int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length); -int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret); - void netlink_seal_message(sd_netlink *nl, sd_netlink_message *m); size_t netlink_get_reply_callback_count(sd_netlink *nl); diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c index b6730b7..b347ee6 100644 --- a/src/libsystemd/sd-netlink/sd-netlink.c +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -176,7 +176,7 @@ static int dispatch_rqueue(sd_netlink *nl, sd_netlink_message **ret) { assert(nl); assert(ret); - if (ordered_set_size(nl->rqueue) <= 0) { + if (ordered_set_isempty(nl->rqueue)) { /* Try to read a new message */ r = socket_read_message(nl); if (r == -ENOBUFS) /* FIXME: ignore buffer overruns for now */ @@ -443,7 +443,7 @@ int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) { assert_return(nl, -EINVAL); assert_return(!netlink_pid_changed(nl), -ECHILD); - if (ordered_set_size(nl->rqueue) > 0) + if (!ordered_set_isempty(nl->rqueue)) return 0; r = netlink_poll(nl, false, timeout_usec); @@ -623,7 +623,7 @@ int sd_netlink_get_events(sd_netlink *nl) { assert_return(nl, -EINVAL); assert_return(!netlink_pid_changed(nl), -ECHILD); - return ordered_set_size(nl->rqueue) == 0 ? POLLIN : 0; + return ordered_set_isempty(nl->rqueue) ? POLLIN : 0; } int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout_usec) { @@ -633,7 +633,7 @@ int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout_usec) { assert_return(timeout_usec, -EINVAL); assert_return(!netlink_pid_changed(nl), -ECHILD); - if (ordered_set_size(nl->rqueue) > 0) { + if (!ordered_set_isempty(nl->rqueue)) { *timeout_usec = 0; return 1; } diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index 13aedc4..cf19c48 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> #include <netinet/ether.h> #include <netinet/in.h> @@ -681,6 +682,19 @@ TEST(rtnl_set_link_name) { _cleanup_free_ char *resolved = NULL; assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved) == ifindex); assert_se(streq_ptr(resolved, "test-shortname")); + resolved = mfree(resolved); + + assert_se(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname") >= 0); + assert_se(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname2") >= 0); + assert_se(rtnl_rename_link(NULL, "test-shortname2", "test-shortname3") >= 0); + + assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved) == ifindex); + assert_se(streq_ptr(resolved, "test-shortname3")); + resolved = mfree(resolved); + + assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", &resolved) == ifindex); + assert_se(streq_ptr(resolved, "test-shortname3")); + resolved = mfree(resolved); } DEFINE_TEST_MAIN(LOG_DEBUG); |