The branch main has been updated by melifaro:

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

commit 3f6bf6a033b156fe8a716cc0cc2278270504343c
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-05-15 11:33:10 +0000
Commit:     Alexander V. Chernikov <melif...@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");

Reply via email to