The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=88bd9ef618d62171fa9e192f2c3c91e9becdc555

commit 88bd9ef618d62171fa9e192f2c3c91e9becdc555
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-05-09 14:55:47 +0000
Commit:     Alexander V. Chernikov <melif...@freebsd.org>
CommitDate: 2023-05-09 14:55:47 +0000

    netlink: automatically fill sin6_scope_id in the default snl(3) parsers.
    
    Add the optional post-parse hook to the snl(3) parser declaration.
    Use this hook to automatically add the interface indexes to the
     link-local sockaddrs.
    
    MFC after:      2 weeks
---
 sys/netlink/netlink_snl.h               | 12 +++++-
 sys/netlink/netlink_snl_route_parsers.h | 73 +++++++++++++++++++++++++++++----
 2 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
index 83892c156273..1bf8a9cf07c8 100644
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -146,23 +146,30 @@ struct snl_attr_parser {
        };
 };
 
+typedef bool snl_parse_post_f(struct snl_state *ss, void *target);
+
 struct snl_hdr_parser {
        int                     hdr_off; /* aligned header size */
        int                     fp_size;
        int                     np_size;
        const struct snl_field_parser   *fp; /* array of header field parsers */
        const struct snl_attr_parser    *np; /* array of attribute parsers */
+       snl_parse_post_f                *cb_post; /* post-parse callback */
 };
 
-#define        SNL_DECLARE_PARSER(_name, _t, _fp, _np)         \
+#define        SNL_DECLARE_PARSER_EXT(_name, _t, _fp, _np, _cb)        \
 static const struct snl_hdr_parser _name = {           \
        .hdr_off = sizeof(_t),                          \
        .fp = &((_fp)[0]),                              \
        .np = &((_np)[0]),                              \
        .fp_size = NL_ARRAY_LEN(_fp),                   \
        .np_size = NL_ARRAY_LEN(_np),                   \
+       .cb_post = _cb,                                 \
 }
 
+#define        SNL_DECLARE_PARSER(_name, _t, _fp, _np)         \
+       SNL_DECLARE_PARSER_EXT(_name, _t, _fp, _np, NULL)
+
 #define        SNL_DECLARE_ATTR_PARSER(_name, _np)             \
 static const struct snl_hdr_parser _name = {           \
        .np = &((_np)[0]),                              \
@@ -471,6 +478,9 @@ snl_parse_header(struct snl_state *ss, void *hdr, int len,
        bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->hdr_off,
            parser->np, parser->np_size, target);
 
+       if (result && parser->cb_post != NULL)
+               result = parser->cb_post(ss, target);
+
        return (result);
 }
 
diff --git a/sys/netlink/netlink_snl_route_parsers.h 
b/sys/netlink/netlink_snl_route_parsers.h
index 1afbe3feeeb9..6332f9f9e0d9 100644
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -33,6 +33,17 @@
 
 /* TODO: this file should be generated automatically */
 
+static inline void
+finalize_sockaddr(struct sockaddr *sa, uint32_t ifindex)
+{
+       if (sa != NULL && sa->sa_family == AF_INET6) {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+               if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+                       sin6->sin6_scope_id = ifindex;
+       }
+}
+
 /* RTM_<NEW|DEL|GET>ROUTE message parser */
 
 struct rta_mpath_nh {
@@ -63,9 +74,18 @@ static const struct snl_field_parser _fp_p_mp_nh[] = {
        { .off_in = _IN(rtnh_hops), .off_out = _OUT(rtnh_weight), .cb = 
snl_field_get_uint8 },
        { .off_in = _IN(rtnh_ifindex), .off_out = _OUT(ifindex), .cb = 
snl_field_get_uint32 },
 };
+
+static inline bool
+_cb_p_mp_nh(struct snl_state *ss, void *_target)
+{
+       struct rta_mpath_nh *target = _target;
+
+       finalize_sockaddr(target->gw, target->ifindex);
+       return (true);
+}
 #undef _IN
 #undef _OUT
-SNL_DECLARE_PARSER(_mpath_nh_parser, struct rtnexthop, _fp_p_mp_nh, 
_nla_p_mp_nh);
+SNL_DECLARE_PARSER_EXT(_mpath_nh_parser, struct rtnexthop, _fp_p_mp_nh, 
_nla_p_mp_nh, _cb_p_mp_nh);
 
 struct rta_mpath {
        int num_nhops;
@@ -153,9 +173,19 @@ static const struct snl_field_parser _fp_p_route[] = {
        {.off_in = _IN(rtm_protocol), .off_out = _OUT(rtm_protocol), .cb = 
snl_field_get_uint8 },
        {.off_in = _IN(rtm_dst_len), .off_out = _OUT(rtm_dst_len), .cb = 
snl_field_get_uint8 },
 };
+
+static inline bool
+_cb_p_route(struct snl_state *ss, void *_target)
+{
+       struct snl_parsed_route *target = _target;
+
+       finalize_sockaddr(target->rta_dst, target->rta_oif);
+       finalize_sockaddr(target->rta_gw, target->rta_oif);
+       return (true);
+}
 #undef _IN
 #undef _OUT
-SNL_DECLARE_PARSER(snl_rtm_route_parser, struct rtmsg, _fp_p_route, 
_nla_p_route);
+SNL_DECLARE_PARSER_EXT(snl_rtm_route_parser, struct rtmsg, _fp_p_route, 
_nla_p_route, _cb_p_route);
 
 /* RTM_<NEW|DEL|GET>LINK message parser */
 struct snl_parsed_link {
@@ -251,9 +281,18 @@ static struct snl_field_parser _fp_p_neigh_s[] = {
        {.off_in = _IN(ndm_state), .off_out = _OUT(ndm_state), .cb = 
snl_field_get_uint16 },
        {.off_in = _IN(ndm_ifindex), .off_out = _OUT(nda_ifindex), .cb = 
snl_field_get_uint32 },
 };
+
+static inline bool
+_cb_p_neigh(struct snl_state *ss, void *_target)
+{
+       struct snl_parsed_neigh *target = _target;
+
+       finalize_sockaddr(target->nda_dst, target->nda_ifindex);
+       return (true);
+}
 #undef _IN
 #undef _OUT
-SNL_DECLARE_PARSER(snl_rtm_neigh_parser, struct ndmsg, _fp_p_neigh_s, 
_nla_p_neigh_s);
+SNL_DECLARE_PARSER_EXT(snl_rtm_neigh_parser, struct ndmsg, _fp_p_neigh_s, 
_nla_p_neigh_s, _cb_p_neigh);
 
 struct snl_parsed_addr {
        uint8_t         ifa_family;
@@ -267,21 +306,30 @@ struct snl_parsed_addr {
 
 #define        _IN(_field)     offsetof(struct ifaddrmsg, _field)
 #define        _OUT(_field)    offsetof(struct snl_parsed_addr, _field)
-static struct snl_attr_parser _nla_p_addr_s[] = {
+static const struct snl_attr_parser _nla_p_addr_s[] = {
        { .type = IFA_ADDRESS, .off = _OUT(ifa_address), .cb = snl_attr_get_ip 
},
        { .type = IFA_LOCAL, .off = _OUT(ifa_local), .cb = snl_attr_get_ip },
        { .type = IFA_LABEL, .off = _OUT(ifa_label), .cb = snl_attr_dup_string 
},
        { .type = IFA_BROADCAST, .off = _OUT(ifa_broadcast), .cb = 
snl_attr_get_ip },
 };
-static struct snl_field_parser _fp_p_addr_s[] = {
+static const struct snl_field_parser _fp_p_addr_s[] = {
        {.off_in = _IN(ifa_family), .off_out = _OUT(ifa_family), .cb = 
snl_field_get_uint8 },
        {.off_in = _IN(ifa_prefixlen), .off_out = _OUT(ifa_prefixlen), .cb = 
snl_field_get_uint8 },
        {.off_in = _IN(ifa_index), .off_out = _OUT(ifa_index), .cb = 
snl_field_get_uint32 },
 };
+
+static inline bool
+_cb_p_addr(struct snl_state *ss, void *_target)
+{
+       struct snl_parsed_addr *target = _target;
+
+       finalize_sockaddr(target->ifa_address, target->ifa_index);
+       finalize_sockaddr(target->ifa_local, target->ifa_index);
+       return (true);
+}
 #undef _IN
 #undef _OUT
-SNL_DECLARE_PARSER(snl_rtm_addr_parser, struct ifaddrmsg, _fp_p_addr_s, 
_nla_p_addr_s);
-
+SNL_DECLARE_PARSER_EXT(snl_rtm_addr_parser, struct ifaddrmsg, _fp_p_addr_s, 
_nla_p_addr_s, _cb_p_addr);
 
 struct snl_parsed_nhop {
        uint32_t        nha_id;
@@ -320,9 +368,18 @@ static const struct snl_attr_parser _nla_p_nh[] = {
        { .type = NHA_GATEWAY, .off = _OUT(nha_gw), .cb = snl_attr_get_ip },
        { .type = NHA_FREEBSD, .arg = &_nh_fbsd_parser, .cb = 
snl_attr_get_nested },
 };
+
+static inline bool
+_cb_p_nh(struct snl_state *ss, void *_target)
+{
+       struct snl_parsed_nhop *target = _target;
+
+       finalize_sockaddr(target->nha_gw, target->nha_oif);
+       return (true);
+}
 #undef _IN
 #undef _OUT
-SNL_DECLARE_PARSER(snl_nhmsg_parser, struct nhmsg, _fp_p_nh, _nla_p_nh);
+SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, struct nhmsg, _fp_p_nh, _nla_p_nh, 
_cb_p_nh);
 
 static const struct snl_hdr_parser *snl_all_route_parsers[] = {
        &_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, 
&snl_rtm_route_parser,

Reply via email to