git: 3c851dc19bbd - main - netlink: provide original interface lladdr in the interface dump.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 10 May 2023 09:57:52 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=3c851dc19bbde2056a9367cc43e935f9a35925a4

commit 3c851dc19bbde2056a9367cc43e935f9a35925a4
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-05-10 09:49:34 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-05-10 09:57:01 +0000

    netlink: provide original interface lladdr in the interface dump.
    
    * Store lladdr in the FreeBSD-specific IFLAF_ORIG_HWADDR attr
    * Do not export empty IFLA_ADDRESS for interfaces w/o lladdrs.
    
    MFC after:      2 weeks
---
 sys/netlink/netlink_snl_route_parsers.h |  9 ++++++++-
 sys/netlink/route/iface.c               | 25 +++++++++++++++++++++++--
 sys/netlink/route/interface.h           |  9 +++++++++
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h
index a4877a4d7939..75ba6d461731 100644
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -202,10 +202,16 @@ struct snl_parsed_link {
 	char				*ifla_ifalias;
 	uint32_t			ifla_promiscuity;
 	struct rtnl_link_stats64	*ifla_stats64;
+	struct nlattr			*iflaf_orig_hwaddr;
 };
 
 #define	_IN(_field)	offsetof(struct ifinfomsg, _field)
 #define	_OUT(_field)	offsetof(struct snl_parsed_link, _field)
+static const struct snl_attr_parser _nla_p_link_fbsd[] = {
+	{ .type = IFLAF_ORIG_HWADDR, .off = _OUT(iflaf_orig_hwaddr), .cb = snl_attr_dup_nla },
+};
+SNL_DECLARE_ATTR_PARSER(_link_fbsd_parser, _nla_p_link_fbsd);
+
 static const struct snl_attr_parser _nla_p_link[] = {
 	{ .type = IFLA_ADDRESS, .off = _OUT(ifla_address), .cb = snl_attr_dup_nla },
 	{ .type = IFLA_BROADCAST, .off = _OUT(ifla_broadcast), .cb = snl_attr_dup_nla },
@@ -216,6 +222,7 @@ static const struct snl_attr_parser _nla_p_link[] = {
 	{ .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = snl_attr_dup_struct },
 	{ .type = IFLA_PROMISCUITY, .off = _OUT(ifla_promiscuity), .cb = snl_attr_get_uint32 },
 	{ .type = IFLA_CARRIER, .off = _OUT(ifla_carrier), .cb = snl_attr_get_uint8 },
+	{ .type = IFLA_FREEBSD, .arg = &_link_fbsd_parser, .cb = snl_attr_get_nested },
 };
 static const struct snl_field_parser _fp_p_link[] = {
 	{.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
@@ -394,7 +401,7 @@ SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, struct nhmsg, _fp_p_nh, _nla_p_nh, _cb_
 
 static const struct snl_hdr_parser *snl_all_route_parsers[] = {
 	&_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser,
-	&snl_rtm_link_parser, &snl_rtm_link_parser_simple,
+	&_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple,
 	&_neigh_fbsd_parser, &snl_rtm_neigh_parser,
 	&_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser,
 };
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index edcf8b635f50..aaed11e637a2 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -194,6 +194,17 @@ get_operstate(struct ifnet *ifp, struct if_state *pstate)
 	}
 }
 
+static void
+get_hwaddr(struct nl_writer *nw, struct ifnet *ifp)
+{
+	struct ifreq ifr = {};
+
+	if (if_gethwaddr(ifp, &ifr) == 0) {
+		nlattr_add(nw, IFLAF_ORIG_HWADDR, if_getaddrlen(ifp),
+		    ifr.ifr_addr.sa_data);
+	}
+}
+
 static unsigned
 ifp_flags_to_netlink(const struct ifnet *ifp)
 {
@@ -281,8 +292,10 @@ dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
         nlattr_add_u8(nw, IFLA_PROTO_DOWN, val);
         nlattr_add_u8(nw, IFLA_LINKMODE, val);
 */
-        if ((ifp->if_addr != NULL)) {
-                dump_sa(nw, IFLA_ADDRESS, ifp->if_addr->ifa_addr);
+        if (if_getaddrlen(ifp) != 0) {
+		struct ifaddr *ifa = if_getifaddr(ifp);
+
+                dump_sa(nw, IFLA_ADDRESS, ifa->ifa_addr);
         }
 
         if ((ifp->if_broadcastaddr != NULL)) {
@@ -300,6 +313,14 @@ dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
 	if (ifp->if_description != NULL)
 		nlattr_add_string(nw, IFLA_IFALIAS, ifp->if_description);
 
+	/* Store FreeBSD-specific attributes */
+	int off = nlattr_add_nested(nw, IFLA_FREEBSD);
+	if (off != 0) {
+		get_hwaddr(nw, ifp);
+
+		nlattr_set_len(nw, off);
+	}
+
 	get_stats(nw, ifp);
 
 	uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0;
diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h
index ec0e1e246a07..c78a0be60a21 100644
--- a/sys/netlink/route/interface.h
+++ b/sys/netlink/route/interface.h
@@ -142,10 +142,19 @@ enum {
 	IFLA_DEVLINK_PORT,
 	IFLA_GSO_IPV4_MAX_SIZE,
 	IFLA_GRO_IPV4_MAX_SIZE,
+	IFLA_FREEBSD,
 	__IFLA_MAX
 };
 #define IFLA_MAX (__IFLA_MAX - 1)
 
+enum {
+	IFLAF_UNSPEC		= 0,
+	IFLAF_ORIG_IFNAME	= 1,	/* string, original interface name at creation */
+	IFLAF_ORIG_HWADDR	= 2,	/* binary, original hardware address */
+	__IFLAF_MAX
+};
+#define IFLAF_MAX (__IFLAF_MAX - 1)
+
 /*
  * Attributes that can be used as filters:
  *  IFLA_IFNAME, IFLA_GROUP, IFLA_ALT_IFNAME