From nobody Mon Dec 04 10:24:29 2023 X-Original-To: dev-commits-src-branches@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 4SkKXY4J2Sz53CKP; Mon, 4 Dec 2023 10:24:29 +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 4SkKXY2tWKz4MhN; Mon, 4 Dec 2023 10:24:29 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701685469; 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=iMh3bkADqA3eu/TplmaM1QWKEHnU6TJXFBTDtpOuAq4=; b=avdsw9JT+2+lWZgRiCGn6mxUfe6wHnLeUILG0yAk5fSedMg62Z6FjSLq9+VHMLtxr1kgQM M2H5yodTz6vcn8N4HrShqRg18rwDKd6GxGnSL0EKqDVyK3nZRbQOFunqHvpdULV5lus2Ne DOF0omGagLlt8uBY2UCWg1/DhLSFQDBA7Wz4MPTzL7/gaB3zDkJDR1x7Bep1FDvsiLLId+ I2ezbi9B4SqJpzh6OAvb4s9/v4lXmHnvFID19ZzYTfnh3gGEk+PpRQoGuH/htPVB/Z6gEh jqZdic5bzIy6f0n4Fr8dmF4730ZFVAT1n2LoYHyKefWxqC8p509EFyJ7XrUSYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701685469; 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=iMh3bkADqA3eu/TplmaM1QWKEHnU6TJXFBTDtpOuAq4=; b=rRoewqlJx6X1YGBE77HrsN6HDZaLx8IalBdWGMlsx5oZA6J3IEGSCs1w+e841C5t16TUMZ Om5YfDPI5XcYTWsa/4jWc7LMd94b2h23vSumL+s+f9ZR9ykK2b53sbevLTMr4eTXZU+BKl 6oMgSv/RkQE2rui8gWBxbfS9MUp0IQO9bRTdL4WDU/i4vcPfbGvlBl0sw0YrqIJP3MZn4P zZpIdapRlr+2sXpjGs6QHSHLIZZ9j9+F9xZWJOhBkS8LPLH2ggLtDJVfyQWsObeH8TXM2S ULwdd3nZHCXgw//OSTu2K5g2+o+6q3dtmubaoOHb9QHcHzPJfyskONxrFZbYmA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1701685469; a=rsa-sha256; cv=none; b=vrP/JD8yF3aldhtqzprCzaJEYDizbredaBaBa83hSIRSyt/pWjQsLFSc/9wUkj3jWzS2V7 BylMaUL+766L14IUr9WhDVJDG9/HIIQdGrgL6is4C58UuJQhT2ha5X4a1Q57nIFu9p5xTB FzSCctmmrGkhn5uKifoBDLbwveHvF9hKuGkUlcjQyVrgJjUH7eoW01iq/BEo39D8s9TkS+ 74BaoxCAChGWJ68wFDVbOxVlx0JqMcFH37dGf8v+HoVeBeM0WDS8m6f5PYgkymTZfQN5VS +RwFcEREOKDV0BIu4FKxKFcE741Zd6sY5T4XLMa1xGglwI3yodDk1eqBQtcp0g== 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 4SkKXY1p6Kz7Dl; Mon, 4 Dec 2023 10:24:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3B4AOTF4092488; Mon, 4 Dec 2023 10:24:29 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3B4AOTX6092485; Mon, 4 Dec 2023 10:24:29 GMT (envelope-from git) Date: Mon, 4 Dec 2023 10:24:29 GMT Message-Id: <202312041024.3B4AOTX6092485@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Baptiste Daroussin Subject: git: a501d357eb45 - stable/14 - genl: add a monitor subcommand List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bapt X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: a501d357eb45e6b66057fa78a6447ddb1cc1de65 Auto-Submitted: auto-generated The branch stable/14 has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=a501d357eb45e6b66057fa78a6447ddb1cc1de65 commit a501d357eb45e6b66057fa78a6447ddb1cc1de65 Author: Baptiste Daroussin AuthorDate: 2023-10-05 10:51:02 +0000 Commit: Baptiste Daroussin CommitDate: 2023-12-04 10:21:33 +0000 genl: add a monitor subcommand usage: $ genl monitor this subcommand allows to monitor the message from a multicast group of a given family when received. If it knows how to parse the messages received it will dump the decoded version, otherwise it will just inform a new message has been received So far it only knows how to parse nlctrl notify messages, but the plan to allow to make the parsing extensible via lua scripts Differential Revision: https://reviews.freebsd.org/D40372 (cherry picked from commit e19b2ef976d326d34b17331c5071d9e687d0d5d5) --- usr.bin/genl/genl.1 | 27 ++++++++-- usr.bin/genl/genl.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 158 insertions(+), 10 deletions(-) diff --git a/usr.bin/genl/genl.1 b/usr.bin/genl/genl.1 index 44ce4feaea48..b3d66298eb00 100644 --- a/usr.bin/genl/genl.1 +++ b/usr.bin/genl/genl.1 @@ -24,23 +24,44 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 20, 2023 +.Dd Oct 5, 2023 .Dt GENL 1 .Os .Sh NAME .Nm genl -.Nd "generic netlink list" +.Nd "generic netlink" .Sh SYNOPSIS .Nm +.Pp +.Nm Cm list +.Pp +.Nm Cm monitor Ao family Ac Ao multicast group Ac .Sh DESCRIPTION +The .Nm -lists all available generic netlink protocols, and presents its details: +utility is design to provide access to the user to generic netlink +protocols. +.Pp +The following commands are available: +.Bl -tag -ident +.It Cm list Po default Pc +Lists all available generic netlink protocols, and presents its details: .Bl -tag -width "multicast groups" .It operations Id of the operation if any and associated capabilities .It multicast groups If of the available multicast group if any and it associated name .El +.It Cm monitor Ao family Ac Ao multicast group Ac +Connect to the +.Ar family +protocol and subscribe to the +.Ar mulicast group +then print the received messages in a readable format if the protocol is known. +So far only +.Qq nlctrl +is known. +.El .Sh SEE ALSO .Xr genetlink 4 , .Xr netlink 4 diff --git a/usr.bin/genl/genl.c b/usr.bin/genl/genl.c index 8e8e18a7f8e2..e3acb872a39e 100644 --- a/usr.bin/genl/genl.c +++ b/usr.bin/genl/genl.c @@ -27,18 +27,41 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include #include +static int monitor_mcast(int argc, char **argv); +static int list_families(int argc, char **argv); +static void parser_nlctrl_notify(struct snl_state *ss, struct nlmsghdr *hdr); +static void parser_fallback(struct snl_state *ss, struct nlmsghdr *hdr); + +static struct commands { + const char *name; + const char *usage; + int (*cmd)(int argc, char **argv); +} cmds[] = { + { "monitor", "monitor ", monitor_mcast }, + { "list", "list", list_families }, +}; + +static struct mcast_parsers { + const char *family; + void (*parser)(struct snl_state *ss, struct nlmsghdr *hdr); +} mcast_parsers [] = { + { "nlctrl", parser_nlctrl_notify }, +}; + struct genl_ctrl_op { uint32_t id; uint32_t flags; @@ -131,6 +154,13 @@ dump_mcast_groups( struct snl_genl_ctrl_mcast_groups *mcast_groups) mcast_groups->groups[i]->mcast_grp_name); } +static void +usage(void) +{ + fprintf(stderr, "Usage: %s\n", getprogname()); + for (size_t i = 0; i < nitems(cmds); i++) + fprintf(stderr, " %s %s\n", getprogname(), cmds[i].usage); +} static void dump_family(struct genl_family *family) @@ -143,8 +173,87 @@ dump_family(struct genl_family *family) dump_mcast_groups(&family->mcast_groups); } +void +parser_nlctrl_notify(struct snl_state *ss, struct nlmsghdr *hdr) +{ + struct genl_family family = {}; + + if (snl_parse_nlmsg(ss, hdr, &genl_family_parser, + &family)) + dump_family(&family); +} + +void +parser_fallback(struct snl_state *ss __unused, struct nlmsghdr *hdr __unused) +{ + printf("New unknown message\n"); +} + +int +monitor_mcast(int argc __unused, char **argv) +{ + struct snl_state ss; + struct nlmsghdr *hdr; + struct _getfamily_attrs attrs; + struct pollfd pfd; + bool found = false; + void (*parser)(struct snl_state *ss, struct nlmsghdr *hdr); + + parser = parser_fallback; + + if (!snl_init(&ss, NETLINK_GENERIC)) + err(EXIT_FAILURE, "snl_init()"); + + if (argc != 2) { + usage(); + return (EXIT_FAILURE); + } + if (!snl_get_genl_family_info(&ss, argv[0], &attrs)) + errx(EXIT_FAILURE, "Unknown family '%s'", argv[0]); + for (uint32_t i = 0; i < attrs.mcast_groups.num_groups; i++) { + if (strcmp(attrs.mcast_groups.groups[i]->mcast_grp_name, + argv[1]) == 0) { + found = true; + if (setsockopt(ss.fd, SOL_NETLINK, + NETLINK_ADD_MEMBERSHIP, + (void *)&attrs.mcast_groups.groups[i]->mcast_grp_id, + sizeof(attrs.mcast_groups.groups[i]->mcast_grp_id)) + == -1) + err(EXIT_FAILURE, "Cannot subscribe to command " + "notify"); + break; + } + } + if (!found) + errx(EXIT_FAILURE, "No such multicat group '%s'" + " in family '%s'", argv[1], argv[0]); + for (size_t i= 0; i < nitems(mcast_parsers); i++) { + if (strcmp(mcast_parsers[i].family, argv[0]) == 0) { + parser = mcast_parsers[i].parser; + break; + } + } + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = ss.fd; + pfd.events = POLLIN | POLLERR; + while (true) { + pfd.revents = 0; + if (poll(&pfd, 1, -1) == -1) { + if (errno == EINTR) + continue; + err(EXIT_FAILURE, "poll()"); + } + hdr = snl_read_message(&ss); + if (hdr != NULL && hdr->nlmsg_type != NLMSG_ERROR) + parser(&ss, hdr); + + } + + return (EXIT_SUCCESS); +} + int -main(int argc, char **argv __unused) +list_families(int argc, char **argv __unused) { struct snl_state ss; struct snl_writer nw; @@ -152,16 +261,16 @@ main(int argc, char **argv __unused) struct snl_errmsg_data e = {}; uint32_t seq_id; - if (argc > 1) - errx(EXIT_FAILURE, "usage: genl does not accept any argument"); - if (modfind("netlink") == -1) - err(EXIT_FAILURE, "require netlink module to be loaded"); - + if (argc != 0) { + usage(); + return (EXIT_FAILURE); + } if (!snl_init(&ss, NETLINK_GENERIC)) err(EXIT_FAILURE, "snl_init()"); snl_init_writer(&ss, &nw); - hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY); + hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL, + CTRL_CMD_GETFAMILY); if ((hdr = snl_finalize_msg(&nw)) == NULL) err(EXIT_FAILURE, "snl_finalize_msg"); seq_id = hdr->nlmsg_seq; @@ -179,3 +288,21 @@ main(int argc, char **argv __unused) return (EXIT_SUCCESS); } + +int +main(int argc, char **argv) +{ + if (modfind("netlink") == -1) + err(EXIT_FAILURE, "require netlink module to be loaded"); + + if (argc == 1) + return (list_families(0, NULL)); + + for (size_t i = 0; i < nitems(cmds); i++) { + if (strcmp(argv[1], cmds[i].name) == 0) + return (cmds[i].cmd(argc - 2, argv + 2)); + } + usage(); + + return (EXIT_FAILURE); +}