From nobody Sat May 27 11:14:13 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4QSzh620vbz4WtbJ; Sat, 27 May 2023 11:14:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4QSzh61Yv4z3vRc; Sat, 27 May 2023 11:14:14 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1685186054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XTbs8uABdZjBbNBj2X3lk4w/1aSXt4y0WWInutg1/vw=; b=Kys/KTayNw04bGA+8vQr3+ph2Qjku5pOTkqFJkaAAEMs43OFx9sMTteXgioQIS/8RqEr0u SKUfbr96s5QwPBCvVjk+MR9H/ze4nCUYg+HIuDc7C87HzCU0BguuMOGU1fUhgoz5c+vuHp 6CPswmg3Vq0lC7BCc4Nq/6uWnDLKYC16dOMCYx8CDjPGYkSa63wUXnZpkl7WLLYCVf0gUD 6yOVdkf2iL6+V3ZMoSIjTjfHAyYJJ44wCgY35+adZEreLo/djQ21vatuk3XB8UuD+Ky2UE VR/cTdP3nSDVxG6DVVlnA3N49joynPlXaxpBKzUn8StcBk+iG54cyfRqxwzlsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1685186054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XTbs8uABdZjBbNBj2X3lk4w/1aSXt4y0WWInutg1/vw=; b=kbngg8MZi2bv7rn/OowJHVNYmVf6LXhYY3TjNJDMns/hhRYB2uFGuXZQAiLDSG2oivhFBk 5ZUffLpMrdXU2W/JdvTLwpp2dXffD9GAINHfYFL2wBCI2pc2vZS+x3ZlL+vOHF/87sdTa1 yCCRgaqMxcyi/NpU5D5xvHfFzE8hhTo2BC4K36nZoGI/CxeVe4YfUMV2bng0miMM1wvg6P N3ZsOq4UIlUQBf0e108tszQbfex5GKc/Am3LqVF/8aBCElLmitbRsep1KFfeAeUkNdqIPn oDiLpL4TQWIm9YM1VZb9Qlk5vIKKNDqPapqVQrhAE00SWlh8+uex3loQYkuGPA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1685186054; a=rsa-sha256; cv=none; b=RfCtgc/PmCtDVHqoKCNrfouhWyWAaWSRdfXVXaZ9/VNQMXGpDdhvYC+/Nl2S0ftQQNUBEO qZMLfULIdKiLiKo2nkbgQ/k/VjWxm3Sd6bqxLsgDE717WGa9LZRU2wtiCoddaudXTDffRO ZWEFh+l+MYpmaGwh/GuLvtY1t51BLJRa2Hu8cNkiujYrlI+/CQmGkzhsPhWErRh6etKc25 6aMl77bv7wCPFv1PDFdnm+HQnWUMzT+JaDgNPdUIA/fI1AEBFRjxuvDiA/NWvrnC6jswy1 TV7IHb0vZ2zUoGlWCCFr3W3JboR2wHb75q+bPUfmMcnuCPUuDKlW1o4WAlZkSQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4QSzh60dF5zmbL; Sat, 27 May 2023 11:14:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 34RBED9t007213; Sat, 27 May 2023 11:14:13 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 34RBED8O007212; Sat, 27 May 2023 11:14:13 GMT (envelope-from git) Date: Sat, 27 May 2023 11:14:13 GMT Message-Id: <202305271114.34RBED8O007212@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Alexander V. Chernikov" Subject: git: 5f19f790b392 - main - netlink: add snl(3) support for parsing unknown-size arrays List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: melifaro X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 5f19f790b3923354871ce049b84c7807ecb0cad5 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=5f19f790b3923354871ce049b84c7807ecb0cad5 commit 5f19f790b3923354871ce049b84c7807ecb0cad5 Author: Alexander V. Chernikov AuthorDate: 2023-05-27 11:09:01 +0000 Commit: Alexander V. Chernikov CommitDate: 2023-05-27 11:13:14 +0000 netlink: add snl(3) support for parsing unknown-size arrays Reviewed by: bapt Differential Review: https://reviews.freebsd.org/D40282 MFC after: 2 weeks --- sys/netlink/netlink_snl.h | 122 ++++++++++++++++++++++++++------ sys/netlink/netlink_snl_route_parsers.h | 19 +++-- 2 files changed, 116 insertions(+), 25 deletions(-) diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h index 5844994b5e47..6d97c1afd4ee 100644 --- a/sys/netlink/netlink_snl.h +++ b/sys/netlink/netlink_snl.h @@ -149,33 +149,40 @@ 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; + uint16_t in_hdr_size; /* Input header size */ + uint16_t out_size; /* Output structure size */ + uint16_t fp_size; /* Number of items in field parser */ + uint16_t np_size; /* Number of items in attribute parser */ 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_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_EXT(_name, _sz_h_in, _sz_out, _fp, _np, _cb) \ +static const struct snl_hdr_parser _name = { \ + .in_hdr_size = _sz_h_in, \ + .out_size = _sz_out, \ + .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_PARSER(_name, _t, _fp, _np) \ + SNL_DECLARE_PARSER_EXT(_name, sizeof(_t), 0, _fp, _np, NULL) -#define SNL_DECLARE_ATTR_PARSER(_name, _np) \ -static const struct snl_hdr_parser _name = { \ - .np = &((_np)[0]), \ - .np_size = NL_ARRAY_LEN(_np), \ +#define SNL_DECLARE_ATTR_PARSER_EXT(_name, _sz_out, _np, _cb) \ +static const struct snl_hdr_parser _name = { \ + .out_size = _sz_out, \ + .np = &((_np)[0]), \ + .np_size = NL_ARRAY_LEN(_np), \ + .cb_post = _cb, \ } +#define SNL_DECLARE_ATTR_PARSER(_name, _np) \ + SNL_DECLARE_ATTR_PARSER_EXT(_name, 0, _np, NULL) + static inline void * snl_allocz(struct snl_state *ss, int len) @@ -471,11 +478,13 @@ static inline bool snl_parse_header(struct snl_state *ss, void *hdr, int len, const struct snl_hdr_parser *parser, void *target) { + struct nlattr *nla_head; + /* Extract fields first (if any) */ - snl_parse_fields(ss, hdr, parser->hdr_off, parser->fp, parser->fp_size, target); + snl_parse_fields(ss, hdr, parser->in_hdr_size, parser->fp, parser->fp_size, target); - struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + parser->hdr_off); - bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->hdr_off, + nla_head = (struct nlattr *)(void *)((char *)hdr + parser->in_hdr_size); + bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->in_hdr_size, parser->np, parser->np_size, target); if (result && parser->cb_post != NULL) @@ -642,6 +651,78 @@ snl_attr_get_nested(struct snl_state *ss, struct nlattr *nla, const void *arg, v return (snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), p, target)); } +struct snl_parray { + uint32_t count; + void **items; +}; + +static inline bool +snl_attr_get_parray_sz(struct snl_state *ss, struct nlattr *container_nla, + uint32_t start_size, const void *arg, void *target) +{ + const struct snl_hdr_parser *p = (const struct snl_hdr_parser *)arg; + struct snl_parray *array = target; + struct nlattr *nla; + uint32_t count = 0, size = start_size; + + if (p->out_size == 0) + return (false); + + array->items = snl_allocz(ss, size * sizeof(void *)); + if (array->items == NULL) + return (false); + + /* + * If the provided parser is an attribute parser, assume that each + * nla in the container nla is the container nla itself and parse + * the contents of this nla. + * Otherwise, run the parser on raw data, assuming the header of this + * data has u16 field with total size in the beginning. + */ + uint32_t data_off = 0; + + if (p->in_hdr_size == 0) + data_off = sizeof(struct nlattr); + + NLA_FOREACH(nla, NLA_DATA(container_nla), NLA_DATA_LEN(container_nla)) { + void *item = snl_allocz(ss, p->out_size); + + if (item == NULL) + return (false); + + void *data = (char *)(void *)nla + data_off; + int data_len = nla->nla_len - data_off; + + if (!(snl_parse_header(ss, data, data_len, p, item))) + return (false); + + if (count == size) { + uint32_t new_size = size * 2; + void **new_array = snl_allocz(ss, new_size *sizeof(void *)); + + memcpy(new_array, array->items, size * sizeof(void *)); + array->items = new_array; + size = new_size; + } + array->items[count++] = item; + } + array->count = count; + + return (true); +} + +/* + * Parses and stores the unknown-size array. + * Assumes each array item is a container and the NLAs in the container are parsable + * by the parser provided in @arg. + * Assumes @target is struct snl_parray + */ +static inline bool +snl_attr_get_parray(struct snl_state *ss, struct nlattr *nla, const void *arg, void *target) +{ + return (snl_attr_get_parray_sz(ss, nla, 8, arg, target)); +} + static inline bool snl_attr_get_nla(struct snl_state *ss __unused, struct nlattr *nla, const void *arg __unused, void *target) @@ -878,6 +959,7 @@ snl_realloc_msg_buffer(struct snl_writer *nw, size_t sz) memcpy(new_base, nw->base, nw->offset); if (nw->hdr != NULL) { int hdr_off = (char *)(nw->hdr) - nw->base; + nw->hdr = (struct nlmsghdr *)(void *)((char *)new_base + hdr_off); } nw->base = new_base; diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h index c76e1cd6440a..0ab338cbe6e8 100644 --- a/sys/netlink/netlink_snl_route_parsers.h +++ b/sys/netlink/netlink_snl_route_parsers.h @@ -85,7 +85,9 @@ _cb_p_mp_nh(struct snl_state *ss __unused, void *_target) } #undef _IN #undef _OUT -SNL_DECLARE_PARSER_EXT(_mpath_nh_parser, struct rtnexthop, _fp_p_mp_nh, _nla_p_mp_nh, _cb_p_mp_nh); +SNL_DECLARE_PARSER_EXT(_mpath_nh_parser, sizeof(struct rtnexthop), + sizeof(struct rta_mpath_nh), _fp_p_mp_nh, _nla_p_mp_nh, + _cb_p_mp_nh); struct rta_mpath { int num_nhops; @@ -185,7 +187,9 @@ _cb_p_route(struct snl_state *ss __unused, void *_target) } #undef _IN #undef _OUT -SNL_DECLARE_PARSER_EXT(snl_rtm_route_parser, struct rtmsg, _fp_p_route, _nla_p_route, _cb_p_route); +SNL_DECLARE_PARSER_EXT(snl_rtm_route_parser, sizeof(struct rtmsg), + sizeof(struct snl_parsed_route), _fp_p_route, _nla_p_route, + _cb_p_route); /* RTM_LINK message parser */ struct snl_parsed_link { @@ -299,7 +303,9 @@ _cb_p_neigh(struct snl_state *ss __unused, void *_target) } #undef _IN #undef _OUT -SNL_DECLARE_PARSER_EXT(snl_rtm_neigh_parser, struct ndmsg, _fp_p_neigh_s, _nla_p_neigh_s, _cb_p_neigh); +SNL_DECLARE_PARSER_EXT(snl_rtm_neigh_parser, sizeof(struct ndmsg), + sizeof(struct snl_parsed_neigh), _fp_p_neigh_s, _nla_p_neigh_s, + _cb_p_neigh); struct snl_parsed_addr { uint8_t ifa_family; @@ -347,7 +353,9 @@ _cb_p_addr(struct snl_state *ss __unused, void *_target) } #undef _IN #undef _OUT -SNL_DECLARE_PARSER_EXT(snl_rtm_addr_parser, struct ifaddrmsg, _fp_p_addr_s, _nla_p_addr_s, _cb_p_addr); +SNL_DECLARE_PARSER_EXT(snl_rtm_addr_parser, sizeof(struct ifaddrmsg), + sizeof(struct snl_parsed_addr), _fp_p_addr_s, _nla_p_addr_s, + _cb_p_addr); struct snl_parsed_nhop { uint32_t nha_id; @@ -397,7 +405,8 @@ _cb_p_nh(struct snl_state *ss __unused, void *_target) } #undef _IN #undef _OUT -SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, struct nhmsg, _fp_p_nh, _nla_p_nh, _cb_p_nh); +SNL_DECLARE_PARSER_EXT(snl_nhmsg_parser, sizeof(struct nhmsg), + sizeof(struct snl_parsed_nhop), _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,