git: 3f6bf6a033b1 - main - netlink: add an optional post-process hook to the message parsers.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 15 May 2023 11:37:22 UTC
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");