From 3e08786f37d9a962decf5457a1b5b3860eaa5ee5 Mon Sep 17 00:00:00 2001 From: Antonio Prcela Date: Tue, 10 Sep 2024 19:22:03 +0200 Subject: [PATCH] route: add support for getting permanent mac address of link. --- doc/route.txt | 11 +++++++++++ include/netlink/route/link.h | 2 ++ lib/route/link.c | 36 ++++++++++++++++++++++++++++++++++++ lib/route/nl-route.h | 1 + libnl-route-3.sym | 6 ++++++ 5 files changed, 56 insertions(+) diff --git a/doc/route.txt b/doc/route.txt index cd3ea8f31..5fe049a91 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -394,6 +394,17 @@ void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr); struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link); ----- +[[link_attr_permaddr]] +==== Permanent address +The permanent link layer address (e.g. MAC address). + +[source,c] +----- +#include + +struct nl_addr *rtnl_link_get_perm_addr(struct rtnl_link *link); +----- + [[link_attr_broadcast]] ==== Broadcast Address The link layer broadcast address diff --git a/include/netlink/route/link.h b/include/netlink/route/link.h index add464be9..3717bba7e 100644 --- a/include/netlink/route/link.h +++ b/include/netlink/route/link.h @@ -183,6 +183,8 @@ extern unsigned int rtnl_link_get_arptype(struct rtnl_link *); extern void rtnl_link_set_addr(struct rtnl_link *, struct nl_addr *); extern struct nl_addr *rtnl_link_get_addr(struct rtnl_link *); +extern struct nl_addr *rtnl_link_get_perm_addr(struct rtnl_link *); + extern void rtnl_link_set_broadcast(struct rtnl_link *, struct nl_addr *); extern struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *); diff --git a/lib/route/link.c b/lib/route/link.c index 2603bc87e..8f132a034 100644 --- a/lib/route/link.c +++ b/lib/route/link.c @@ -73,6 +73,7 @@ #define LINK_ATTR_GSO_MAX_SEGS ((uint64_t) 1 << 37) #define LINK_ATTR_GSO_MAX_SIZE ((uint64_t) 1 << 38) #define LINK_ATTR_LINKINFO_SLAVE_KIND ((uint64_t) 1 << 39) +#define LINK_ATTR_PERMANENT_ADDR ((uint64_t) 1 << 40) static struct nl_cache_ops rtnl_link_ops; static struct nl_object_ops link_obj_ops; @@ -271,6 +272,7 @@ static void link_free_data(struct nl_object *c) nl_addr_put(link->l_addr); nl_addr_put(link->l_bcast); + nl_addr_put(link->l_paddr); free(link->l_ifalias); free(link->l_info_kind); @@ -294,6 +296,7 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) dst->l_addr = NULL; dst->l_bcast = NULL; + dst->l_paddr = NULL; dst->l_info_kind = NULL; dst->l_info_slave_kind = NULL; dst->l_info_ops = NULL; @@ -313,6 +316,10 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src) if (!(dst->l_bcast = nl_addr_clone(src->l_bcast))) return -NLE_NOMEM; + if (src->l_paddr) + if (!(dst->l_paddr = nl_addr_clone(src->l_paddr))) + return -NLE_NOMEM; + if (src->l_ifalias) if (!(dst->l_ifalias = strdup(src->l_ifalias))) return -NLE_NOMEM; @@ -514,6 +521,15 @@ int rtnl_link_info_parse(struct rtnl_link *link, struct nlattr **tb) link->ce_mask |= LINK_ATTR_ADDR; } + if (tb[IFLA_PERM_ADDRESS]) { + link->l_paddr = nl_addr_alloc_attr(tb[IFLA_PERM_ADDRESS], AF_UNSPEC); + if (link->l_paddr == NULL) + return -NLE_NOMEM; + nl_addr_set_family(link->l_paddr, + nl_addr_guess_family(link->l_paddr)); + link->ce_mask |= LINK_ATTR_PERMANENT_ADDR; + } + if (tb[IFLA_BROADCAST]) { link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST], AF_UNSPEC); @@ -863,6 +879,9 @@ static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p) if (link->l_addr && !nl_addr_iszero(link->l_addr)) nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf))); + if (link->l_paddr && !nl_addr_iszero(link->l_paddr)) + nl_dump(p, "permanent address %s ", nl_addr2str(link->l_paddr, buf, sizeof(buf))); + if (link->ce_mask & LINK_ATTR_MASTER) { if (cache) { _nl_auto_rtnl_link struct rtnl_link *master = rtnl_link_get(cache, link->l_master); @@ -1130,6 +1149,7 @@ static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b, diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name)); diff |= _DIFF(LINK_ATTR_ADDR, nl_addr_cmp(a->l_addr, b->l_addr)); diff |= _DIFF(LINK_ATTR_BRD, nl_addr_cmp(a->l_bcast, b->l_bcast)); + diff |= _DIFF(LINK_ATTR_PERMANENT_ADDR, nl_addr_cmp(a->l_paddr, b->l_paddr)); diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias)); diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf); diff |= _DIFF(LINK_ATTR_PROMISCUITY, @@ -1565,6 +1585,9 @@ int rtnl_link_fill_info(struct nl_msg *msg, struct rtnl_link *link) if (link->ce_mask & LINK_ATTR_NS_PID) NLA_PUT_U32(msg, IFLA_NET_NS_PID, link->l_ns_pid); + if (link->ce_mask & LINK_ATTR_PERMANENT_ADDR) + NLA_PUT_ADDR(msg, IFLA_PERM_ADDRESS, link->l_paddr); + return 0; nla_put_failure: @@ -2024,6 +2047,19 @@ struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link) return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL; } +/** + * Return permanent link layer adress of link object + * @arg link Link object + * + * @copydoc pointer_lifetime_warning + * @route_doc{link_attr_permaddr, Permanent Link Layer Address} + * @return Permanent link layer address or NULL if not set. + */ +struct nl_addr *rtnl_link_get_perm_addr(struct rtnl_link *link) +{ + return link->ce_mask & LINK_ATTR_PERMANENT_ADDR ? link->l_paddr : NULL; +} + /** * Set link layer broadcast address of link object * @arg link Link object diff --git a/lib/route/nl-route.h b/lib/route/nl-route.h index 3b7679bfa..53d8b9f0c 100644 --- a/lib/route/nl-route.h +++ b/lib/route/nl-route.h @@ -43,6 +43,7 @@ struct rtnl_link { uint32_t l_master; struct nl_addr *l_addr; struct nl_addr *l_bcast; + struct nl_addr *l_paddr; char l_qdisc[IFQDISCSIZ]; struct rtnl_link_map l_map; uint64_t l_stats[RTNL_LINK_STATS_MAX + 1]; diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 9cb21f74e..3ce71e29c 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1331,4 +1331,10 @@ global: rtnl_route_get_nhid; rtnl_route_nh_identical; rtnl_route_set_nhid; + rtnl_link_get_perm_addr; } libnl_3_9; + +libnl_3_11 { +global: + rtnl_link_get_perm_addr; +} libnl_3_10;