Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 May 2023 11:37:22 GMT
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 3f6bf6a033b1 - main - netlink: add an optional post-process hook to the message parsers.
Message-ID:  <202305151137.34FBbM66062179@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by melifaro:

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

commit 3f6bf6a033b156fe8a716cc0cc2278270504343c
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-05-15 11:33:10 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-05-15 11:33:10 +0000

    netlink: add an optional post-process hook to the message parsers.
    
    It is primarily used for adding scopeid to the IPv6 link-local
     sockaddrs. Having proper sockaddrs after parsing minimises the
     possibility of human mistake when using the parsing.
    
    MFC after: 2 weeks
---
 sys/netlink/netlink_message_parser.h | 39 ++++++++++++++------------
 sys/netlink/route/neigh.c            | 32 ++++++++++++++++------
 sys/netlink/route/nexthop.c          | 24 +++++++++++++++-
 sys/netlink/route/rt.c               | 53 ++++++++++++++++++------------------
 4 files changed, 95 insertions(+), 53 deletions(-)

diff --git a/sys/netlink/netlink_message_parser.h b/sys/netlink/netlink_message_parser.h
index 5e10ea569829..0934057ac49f 100644
--- a/sys/netlink/netlink_message_parser.h
+++ b/sys/netlink/netlink_message_parser.h
@@ -110,6 +110,7 @@ struct nlattr_parser {
 };
 
 typedef bool strict_parser_f(void *hdr, struct nl_pstate *npt);
+typedef bool post_parser_f(void *parsed_attrs, struct nl_pstate *npt);
 
 struct nlhdr_parser {
 	int				nl_hdr_off; /* aligned netlink header size */
@@ -118,27 +119,26 @@ struct nlhdr_parser {
 	int				np_size;
 	const struct nlfield_parser	*fp; /* array of header field parsers */
 	const struct nlattr_parser	*np; /* array of attribute parsers */
-	strict_parser_f			*sp; /* Parser function */
+	strict_parser_f			*sp; /* Pre-parse strict validation function */
+	post_parser_f			*post_parse;
 };
 
-#define	NL_DECLARE_PARSER(_name, _t, _fp, _np)		\
-static const struct nlhdr_parser _name = {		\
-	.nl_hdr_off = sizeof(_t),			\
-	.fp = &((_fp)[0]),				\
-	.np = &((_np)[0]),				\
-	.fp_size = NL_ARRAY_LEN(_fp),			\
-	.np_size = NL_ARRAY_LEN(_np),			\
+#define	NL_DECLARE_PARSER_EXT(_name, _t, _sp, _fp, _np, _pp)	\
+static const struct nlhdr_parser _name = {			\
+	.nl_hdr_off = sizeof(_t),				\
+	.fp = &((_fp)[0]),					\
+	.np = &((_np)[0]),					\
+	.fp_size = NL_ARRAY_LEN(_fp),				\
+	.np_size = NL_ARRAY_LEN(_np),				\
+	.sp = _sp,						\
+	.post_parse = _pp,					\
 }
 
-#define	NL_DECLARE_STRICT_PARSER(_name, _t, _sp, _fp, _np)\
-static const struct nlhdr_parser _name = {		\
-	.nl_hdr_off = sizeof(_t),			\
-	.fp = &((_fp)[0]),				\
-	.np = &((_np)[0]),				\
-	.fp_size = NL_ARRAY_LEN(_fp),			\
-	.np_size = NL_ARRAY_LEN(_np),			\
-	.sp = _sp,					\
-}
+#define	NL_DECLARE_PARSER(_name, _t, _fp, _np)			\
+	NL_DECLARE_PARSER_EXT(_name, _t, NULL, _fp, _np, NULL)
+
+#define	NL_DECLARE_STRICT_PARSER(_name, _t, _sp, _fp, _np)	\
+	NL_DECLARE_PARSER_EXT(_name, _t, _sp, _fp, _np, NULL)
 
 #define	NL_DECLARE_ARR_PARSER(_name, _t, _o, _fp, _np)	\
 static const struct nlhdr_parser _name = {		\
@@ -252,6 +252,11 @@ nl_parse_header(void *hdr, int len, const struct nlhdr_parser *parser,
 	error = nl_parse_attrs_raw(nla_head, len - parser->nl_hdr_off, parser->np,
 	    parser->np_size, npt, target);
 
+	if (parser->post_parse != NULL && error == 0) {
+		if (!parser->post_parse(target, npt))
+			return (EINVAL);
+	}
+
 	return (error);
 }
 
diff --git a/sys/netlink/route/neigh.c b/sys/netlink/route/neigh.c
index a79400ef77ca..74a162bb9464 100644
--- a/sys/netlink/route/neigh.c
+++ b/sys/netlink/route/neigh.c
@@ -279,14 +279,6 @@ get_lle(struct netlink_walkargs *wa, struct ifnet *ifp, int family, struct socka
 	if (llt == NULL)
 		return (ESRCH);
 
-#ifdef INET6
-	if (dst->sa_family == AF_INET6) {
-		struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
-
-		if (IN6_IS_SCOPE_LINKLOCAL(&dst6->sin6_addr))
-			in6_set_unicast_scopeid(&dst6->sin6_addr, ifp->if_index);
-	}
-#endif
 	struct llentry *lle = lla_lookup(llt, LLE_UNLOCKED, dst);
 	if (lle == NULL)
 		return (ESRCH);
@@ -297,6 +289,19 @@ get_lle(struct netlink_walkargs *wa, struct ifnet *ifp, int family, struct socka
 	return (dump_lle(llt, lle, wa));
 }
 
+static void
+set_scope6(struct sockaddr *sa, struct ifnet *ifp)
+{
+#ifdef INET6
+	if (sa != NULL && sa->sa_family == AF_INET6 && ifp != NULL) {
+		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+
+		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+			in6_set_unicast_scopeid(&sa6->sin6_addr, if_getindex(ifp));
+	}
+#endif
+}
+
 struct nl_parsed_neigh {
 	struct sockaddr	*nda_dst;
 	struct ifnet	*nda_ifp;
@@ -330,7 +335,16 @@ static const struct nlattr_parser nla_p_neigh[] = {
 };
 #undef _IN
 #undef _OUT
-NL_DECLARE_PARSER(ndmsg_parser, struct ndmsg, nlf_p_neigh, nla_p_neigh);
+
+static bool
+post_p_neigh(void *_attrs, struct nl_pstate *npt __unused)
+{
+	struct nl_parsed_neigh *attrs = (struct nl_parsed_neigh *)_attrs;
+
+	set_scope6(attrs->nda_dst, attrs->nda_ifp);
+	return (true);
+}
+NL_DECLARE_PARSER_EXT(ndmsg_parser, struct ndmsg, NULL, nlf_p_neigh, nla_p_neigh, post_p_neigh);
 
 
 /*
diff --git a/sys/netlink/route/nexthop.c b/sys/netlink/route/nexthop.c
index 7bfbdce9f706..d1652cfb1508 100644
--- a/sys/netlink/route/nexthop.c
+++ b/sys/netlink/route/nexthop.c
@@ -678,6 +678,19 @@ nlattr_get_nhg(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void
 	return (error);
 }
 
+static void
+set_scope6(struct sockaddr *sa, struct ifnet *ifp)
+{
+#ifdef INET6
+	if (sa != NULL && sa->sa_family == AF_INET6 && ifp != NULL) {
+		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+
+		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+			in6_set_unicast_scopeid(&sa6->sin6_addr, if_getindex(ifp));
+	}
+#endif
+}
+
 struct nl_parsed_nhop {
 	uint32_t	nha_id;
 	uint8_t		nha_blackhole;
@@ -721,7 +734,16 @@ static const struct nlattr_parser nla_p_nh[] = {
 };
 #undef _IN
 #undef _OUT
-NL_DECLARE_PARSER(nhmsg_parser, struct nhmsg, nlf_p_nh, nla_p_nh);
+
+static bool
+post_p_nh(void *_attrs, struct nl_pstate *npt)
+{
+	struct nl_parsed_nhop *attrs = (struct nl_parsed_nhop *)_attrs;
+
+	set_scope6(attrs->nha_gw, attrs->nha_oif);
+	return (true);
+}
+NL_DECLARE_PARSER_EXT(nhmsg_parser, struct nhmsg, NULL, nlf_p_nh, nla_p_nh, post_p_nh);
 
 static bool
 eligible_nhg(const struct nhop_object *nh)
diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c
index 348d180607e7..e194b8f009c1 100644
--- a/sys/netlink/route/rt.c
+++ b/sys/netlink/route/rt.c
@@ -349,7 +349,6 @@ family_to_group(int family)
 	return (0);
 }
 
-
 static void
 report_operation(uint32_t fibnum, struct rib_cmd_info *rc,
     struct nlpcb *nlp, struct nlmsghdr *hdr)
@@ -384,6 +383,19 @@ report_operation(uint32_t fibnum, struct rib_cmd_info *rc,
 	rtsock_callback_p->route_f(fibnum, rc);
 }
 
+static void
+set_scope6(struct sockaddr *sa, struct ifnet *ifp)
+{
+#ifdef INET6
+	if (sa != NULL && sa->sa_family == AF_INET6 && ifp != NULL) {
+		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+
+		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+			in6_set_unicast_scopeid(&sa6->sin6_addr, if_getindex(ifp));
+	}
+#endif
+}
+
 struct rta_mpath_nh {
 	struct sockaddr	*gw;
 	struct ifnet	*ifp;
@@ -404,26 +416,16 @@ const static struct nlfield_parser nlf_p_rtnh[] = {
 };
 #undef _IN
 #undef _OUT
-NL_DECLARE_PARSER(mpath_parser, struct rtnexthop, nlf_p_rtnh, nla_p_rtnh);
 
-static void
-set_scope6(struct sockaddr *sa, struct ifnet *ifp)
+static bool
+post_p_rtnh(void *_attrs, struct nl_pstate *npt __unused)
 {
-#ifdef INET6
-	if (sa != NULL && sa->sa_family == AF_INET6 && ifp != NULL) {
-		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+	struct rta_mpath_nh *attrs = (struct rta_mpath_nh *)_attrs;
 
-		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
-			in6_set_unicast_scopeid(&sa6->sin6_addr, ifp->if_index);
-	}
-#endif
-}
-
-static void
-post_p_mpath(struct rta_mpath_nh *mpnh)
-{
-	set_scope6(mpnh->gw, mpnh->ifp);
+	set_scope6(attrs->gw, attrs->ifp);
+	return (true);
 }
+NL_DECLARE_PARSER_EXT(mpath_parser, struct rtnexthop, NULL, nlf_p_rtnh, nla_p_rtnh, post_p_rtnh);
 
 struct rta_mpath {
 	int num_nhops;
@@ -451,7 +453,6 @@ nlattr_get_multipath(struct nlattr *nla, struct nl_pstate *npt, const void *arg,
 			    mp->num_nhops - 1);
 			return (error);
 		}
-		post_p_mpath(mpnh);
 
 		int len = NL_ITEM_ALIGN(rtnh->rtnh_len);
 		data_len -= len;
@@ -513,14 +514,17 @@ static const struct nlfield_parser nlf_p_rtmsg[] = {
 };
 #undef _IN
 #undef _OUT
-NL_DECLARE_PARSER(rtm_parser, struct rtmsg, nlf_p_rtmsg, nla_p_rtmsg);
 
-static void
-post_p_rtmsg(struct nl_parsed_route *r)
+static bool
+post_p_rtmsg(void *_attrs, struct nl_pstate *npt __unused)
 {
-	set_scope6(r->rta_dst, r->rta_oif);
-	set_scope6(r->rta_gw, r->rta_oif);
+	struct nl_parsed_route *attrs = (struct nl_parsed_route *)_attrs;
+
+	set_scope6(attrs->rta_dst, attrs->rta_oif);
+	set_scope6(attrs->rta_gw, attrs->rta_oif);
+	return (true);
 }
+NL_DECLARE_PARSER_EXT(rtm_parser, struct rtmsg, NULL, nlf_p_rtmsg, nla_p_rtmsg, post_p_rtmsg);
 
 struct netlink_walkargs {
 	struct nl_writer *nw;
@@ -926,7 +930,6 @@ rtnl_handle_newroute(struct nlmsghdr *hdr, struct nlpcb *nlp,
 	error = nl_parse_nlmsg(hdr, &rtm_parser, npt, &attrs);
 	if (error != 0)
 		return (error);
-	post_p_rtmsg(&attrs);
 
 	/* Check if we have enough data */
 	if (attrs.rta_dst == NULL) {
@@ -991,7 +994,6 @@ rtnl_handle_delroute(struct nlmsghdr *hdr, struct nlpcb *nlp,
 	error = nl_parse_nlmsg(hdr, &rtm_parser, npt, &attrs);
 	if (error != 0)
 		return (error);
-	post_p_rtmsg(&attrs);
 
 	if (attrs.rta_dst == NULL) {
 		NLMSG_REPORT_ERR_MSG(npt, "RTA_DST is not set");
@@ -1019,7 +1021,6 @@ rtnl_handle_getroute(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *
 	error = nl_parse_nlmsg(hdr, &rtm_parser, npt, &attrs);
 	if (error != 0)
 		return (error);
-	post_p_rtmsg(&attrs);
 
 	if (attrs.rta_table >= V_rt_numfibs) {
 		NLMSG_REPORT_ERR_MSG(npt, "invalid fib");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305151137.34FBbM66062179>