From nobody Thu Oct 5 10:54:42 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 4S1T365SL8z4wHq7; Thu, 5 Oct 2023 10:54:42 +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 4S1T364wCLz3SGl; Thu, 5 Oct 2023 10:54:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696503282; 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=Xy0zBtFfrI9wHSwbD7ssVzolNKn4eHuuO9Q0FiY8rLk=; b=VCCXRWGsxL6Aqzy4xeoTRmuLToCPmabEaN7Rq+HwluaJ+fQ3JD4qYu1CFDYFEBlTB9hZlA gfm5KYWhZqPFVvw1N7ASkXtOeY9oPMdgF5kloxJbHXShmif/kKFNlqR7iaEsH3iJiCRFOd rrN8wvNH60DqcEH/IDGWzsXF0seD/uXgD4PwEx5gXo9qrQnqdVDZj0bV5hMOIUDf34t5Ys 4nLqsoj5OvlVQv1+QERoBMRfdGyD5dEdLjHFWYa+v+FsSPEIkOCfrOO+fnmfRtScozhMWm 2gjxSODoQdzbT+olF4Sd0ZtHwlaVP/HQCjYDUQBtq5asLHIXHFndtI8eD35UYA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1696503282; a=rsa-sha256; cv=none; b=tWecsbiug4RX9W+YpuwPhX/Fta5WOkD9HvKOYlZp+NxqZM0pMH//tRpjER8RsqBdJr7Fan HqztyU+06NqRdeysijrpDhH4NkATJkb8DguWe3x/Lb/OayNx3/JVlGl2LrVePXeOP7mENv Y7gqcGMG9VHdWD7rR489bZbszdRkSGbhpEAvUH2djy2EVGA0w+57PiaY0/Tw60hUHAQZv3 GtaUpBK4F4wgwZLGTpVnYagyCxXjb0HAHhGiS3XZSjTHf6JSBIFhL3hzflrQHP5IKadDMI T22LkEnQF7iq+nPaEe7EFB9HfPxG5x8VAH6cH6q5IRNbEBgY4pvipEqD8A4XBg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696503282; 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=Xy0zBtFfrI9wHSwbD7ssVzolNKn4eHuuO9Q0FiY8rLk=; b=xnIkmCtDaq3vGGk3PwdiTdxE2cfSD26SDXQ+qFl8HeDTYrgfawUdnNM6mHJWE9dbUYICHy Ad3hxA1cnceKyEOQzJU+HH2Qs7SvGQ02d/7MmLejfi0UWeUALzjQH/QHe5Le5ctcyWCClg vDKEd12pIvzdqcCK/EVi1fvA8YVBXh+FrMLBOVPJGAnCbs+cwcg9VJMm6TImYGeTb4AZLb Xk/eU4KMXzxfqCRMl4JOzpgN6ZVqRlFrMjTgWksimf4XqU0FXtVxb7UMy5vJF4rprwtI/Q 96FIOBlmCac5cU9JZvm3vimJFvBEKu3pBX78lbthEpsBoEmhiKHo0i+SxzkAxw== 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 4S1T363sV5z1HQR; Thu, 5 Oct 2023 10:54:42 +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 395Asgj8043923; Thu, 5 Oct 2023 10:54:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 395AsgBC043920; Thu, 5 Oct 2023 10:54:42 GMT (envelope-from git) Date: Thu, 5 Oct 2023 10:54:42 GMT Message-Id: <202310051054.395AsgBC043920@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Baptiste Daroussin Subject: git: e19b2ef976d3 - main - genl: add a monitor subcommand 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: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e19b2ef976d326d34b17331c5071d9e687d0d5d5 Auto-Submitted: auto-generated The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=e19b2ef976d326d34b17331c5071d9e687d0d5d5 commit e19b2ef976d326d34b17331c5071d9e687d0d5d5 Author: Baptiste Daroussin AuthorDate: 2023-10-05 10:51:02 +0000 Commit: Baptiste Daroussin CommitDate: 2023-10-05 10:53:47 +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 --- 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); +}