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");