From nobody Tue May 30 11:37:10 2023 X-Original-To: dev-commits-src-main@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 4QVr3B5PrKz4XLlW; Tue, 30 May 2023 11:37:10 +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 4QVr3B4w1zz45Rk; Tue, 30 May 2023 11:37:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1685446630; 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=xQcB/kVWFwL9YByPrJFGGq3Kg7BhGXIj9c8PJ/3xS2w=; b=WubrqXCgFQdcNR7mc93v+M6lkTIXWMYyynSHmn0aNOlongXwvTE8UfZSbicItwkkwyNoRc WLI/jRIkTdeHYVWL6y7WbuUsSMMkh94FFI22WZxFUqNR3Fo7sjJW+mq/naJXr2QOalyQf+ RJd9YGzXs1r23ymxkLjk8g0BKLPh58K+zeXSkfZIsvBreRHQOxDSgn56jM84lg2N0E78Wj dW+j02QQV8QHjqcN9wCqeKVmNVVHWpRBGPAB+1gNWA7zJK6OmozsDiNuPk5piolD7gH4EY WVLIsmWIelnlye1qQFt7ukIj4t320bOBptUo+dlULX/Q9U6AVfeI+NcNwIafRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1685446630; 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=xQcB/kVWFwL9YByPrJFGGq3Kg7BhGXIj9c8PJ/3xS2w=; b=Iv5vf7YB/YKccp2C6vcqKkpfY1Ua5li2CvA7PR7KY3JRFH9BO1yNcrJPqeyHNj9CwrgREm BOJg47jriVfPkkme+CHTcTi4F4rbS5RlYVhLulO5c1gQX2h16yNnotG8PMxp0NRIARsJ7v 0pPA+EWybYAWW9yExtkTE1JoC0QCDaATAGgvSvOj+QQZYd9oi/3NZuM0eT9fPKs3Gd90hK zIfCGxp66L+C/m0Tr5BSgRJeZVND5XjaGqmDz21sjAv0etVi7ouk6cNQc0a2NuH/XtzJCh otiyKR7aZPd7Gg6PnDgAaV2fReG7W0/0X1Dd9Yjx+IMLd/+dYxM7jzDymgw7Mw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1685446630; a=rsa-sha256; cv=none; b=g84PbJsNCnLofK5uKBKHzl7FPBiIujvZUVmN+8xOP7w2GhyRaHfvfk5SPRdAysVugbi/72 FAYp9gEJNfZX41NraMQKUXd6zlQKIXTDg5ULRqdwbQRAZKME9EgV76ThGQ7dNs1wgT+VH9 FjI63nwjHhGOAT0VpPHQmo6Z/TYB+nFHvL2fG+JL1h9A/Im0KCY6P6bxFEt4S5i2dhLNWj 2ebA3g0XNpNjKhzHkos1E9pvVhYivOXGOBfxLeEsojMlY0LnHb1XqnxJExmh/+hUPi5Bcw zgpIzxTjCFQMbssXCWYG4KrGosgH1Ng7o0z/km+a+Kwv1fti3Yk4SCwV34WmcQ== 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 4QVr3B3tLLzs2Q; Tue, 30 May 2023 11:37:10 +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 34UBbA8C068838; Tue, 30 May 2023 11:37:10 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 34UBbAc6068837; Tue, 30 May 2023 11:37:10 GMT (envelope-from git) Date: Tue, 30 May 2023 11:37:10 GMT Message-Id: <202305301137.34UBbAc6068837@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: cb1fc924d2c0 - main - genl: add new command to list genetlink(4) List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: cb1fc924d2c0b87ad27e3741aabf641d35797e2e Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=cb1fc924d2c0b87ad27e3741aabf641d35797e2e commit cb1fc924d2c0b87ad27e3741aabf641d35797e2e Author: Baptiste Daroussin AuthorDate: 2023-05-30 11:31:04 +0000 Commit: Baptiste Daroussin CommitDate: 2023-05-30 11:36:43 +0000 genl: add new command to list genetlink(4) This commands list genetlink protocols and its operations and capabilities Name: nlctrl ID: 0x10, Version: 00, header size: 2, max attributes: 10 supported operations: - ID: 0x3, Capabilities: 0xe (can modify; can get/dump; has policy) multicast groups: - ID: 0x30, Name: notify Name: carp ID: 0x11, Version: 00, header size: 2, max attributes: 2 supported operations: - ID: 0x1, Capabilities: 0xe (can modify; can get/dump; has policy) - ID: 0x2, Capabilities: 0xb (requires admin permission; can modify; has policy) Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D40330 --- share/mk/src.opts.mk | 1 + tools/build/mk/OptionalObsoleteFiles.inc | 5 + tools/build/options/WITHOUT_NETLINK | 4 + tools/build/options/WITH_NETLINK | 4 + usr.bin/Makefile | 1 + usr.bin/genl/Makefile | 3 + usr.bin/genl/genl.1 | 46 ++++++++ usr.bin/genl/genl.c | 181 +++++++++++++++++++++++++++++++ 8 files changed, 245 insertions(+) diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index f828bdc0151b..7b67a55f34b4 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -145,6 +145,7 @@ __DEFAULT_YES_OPTIONS = \ MLX5TOOL \ NETCAT \ NETGRAPH \ + NETLINK \ NETLINK_SUPPORT \ NLS_CATALOGS \ NS_CACHING \ diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 9c7e40ee563a..20654515cfd1 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -5639,6 +5639,11 @@ OLD_FILES+=var/yp/Makefile.dist OLD_DIRS+=var/yp .endif +.if ${MK_NETLINK} == no +OLD_FILES+=usr.bin/genl +OLD_FILES+=usr/share/man/man1/genl.1.gz +.endif + .if ${MK_NLS} == no OLD_DIRS+=usr/share/nls/ OLD_DIRS+=usr/share/nls/C diff --git a/tools/build/options/WITHOUT_NETLINK b/tools/build/options/WITHOUT_NETLINK new file mode 100644 index 000000000000..3ff4b66f1900 --- /dev/null +++ b/tools/build/options/WITHOUT_NETLINK @@ -0,0 +1,4 @@ +.\" $FreeBSD$ +Do not build +.Xr genl 1 +utility. diff --git a/tools/build/options/WITH_NETLINK b/tools/build/options/WITH_NETLINK new file mode 100644 index 000000000000..321e9856b2b5 --- /dev/null +++ b/tools/build/options/WITH_NETLINK @@ -0,0 +1,4 @@ +.\" $FreeBSD$ +Build the +.Xr genl 1 +utility. diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 19988d35c7ba..e027eaf81f24 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -235,6 +235,7 @@ SUBDIR.${MK_MAIL}+= msgs SUBDIR.${MK_MAKE}+= bmake SUBDIR.${MK_MAN_UTILS}+= man SUBDIR.${MK_NETCAT}+= nc +SUBDIR.${MK_NETLINK}+= genl SUBDIR.${MK_NIS}+= ypcat SUBDIR.${MK_NIS}+= ypmatch SUBDIR.${MK_NIS}+= ypwhich diff --git a/usr.bin/genl/Makefile b/usr.bin/genl/Makefile new file mode 100644 index 000000000000..15e60300de02 --- /dev/null +++ b/usr.bin/genl/Makefile @@ -0,0 +1,3 @@ +PROG= genl + +.include diff --git a/usr.bin/genl/genl.1 b/usr.bin/genl/genl.1 new file mode 100644 index 000000000000..44ce4feaea48 --- /dev/null +++ b/usr.bin/genl/genl.1 @@ -0,0 +1,46 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD +.\" +.\" Copyright (c) 2023 Baptiste Daroussin +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd May 20, 2023 +.Dt GENL 1 +.Os +.Sh NAME +.Nm genl +.Nd "generic netlink list" +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm +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 +.Sh SEE ALSO +.Xr genetlink 4 , +.Xr netlink 4 diff --git a/usr.bin/genl/genl.c b/usr.bin/genl/genl.c new file mode 100644 index 000000000000..8e8e18a7f8e2 --- /dev/null +++ b/usr.bin/genl/genl.c @@ -0,0 +1,181 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2023 Baptiste Daroussin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions~ + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct genl_ctrl_op { + uint32_t id; + uint32_t flags; +}; + +struct genl_ctrl_ops { + uint32_t num_ops; + struct genl_ctrl_op **ops; +}; + +#define _OUT(_field) offsetof(struct genl_ctrl_op, _field) +static struct snl_attr_parser _nla_p_getops[] = { + { .type = CTRL_ATTR_OP_ID, .off = _OUT(id), .cb = snl_attr_get_uint32}, + { .type = CTRL_ATTR_OP_FLAGS, .off = _OUT(flags), .cb = snl_attr_get_uint32 }, +}; +#undef _OUT +SNL_DECLARE_ATTR_PARSER_EXT(genl_ctrl_op_parser, + sizeof(struct genl_ctrl_op), + _nla_p_getops, NULL); + +struct genl_family { + uint16_t id; + char *name; + uint32_t version; + uint32_t hdrsize; + uint32_t max_attr; + struct snl_genl_ctrl_mcast_groups mcast_groups; + struct genl_ctrl_ops ops; +}; + +#define _OUT(_field) offsetof(struct genl_family, _field) +static struct snl_attr_parser _nla_p_getfamily[] = { + { .type = CTRL_ATTR_FAMILY_ID , .off = _OUT(id), .cb = snl_attr_get_uint16 }, + { .type = CTRL_ATTR_FAMILY_NAME, .off = _OUT(name), .cb = snl_attr_get_string }, + { .type = CTRL_ATTR_VERSION, .off = _OUT(version), .cb = snl_attr_get_uint32 }, + { .type = CTRL_ATTR_VERSION, .off = _OUT(hdrsize), .cb = snl_attr_get_uint32 }, + { .type = CTRL_ATTR_MAXATTR, .off = _OUT(max_attr), .cb = snl_attr_get_uint32 }, + { + .type = CTRL_ATTR_OPS, + .off = _OUT(ops), + .cb = snl_attr_get_parray, + .arg = &genl_ctrl_op_parser, + }, + { + .type = CTRL_ATTR_MCAST_GROUPS, + .off = _OUT(mcast_groups), + .cb = snl_attr_get_parray, + .arg = &_genl_ctrl_mc_parser, + }, +}; +#undef _OUT +SNL_DECLARE_GENL_PARSER(genl_family_parser, _nla_p_getfamily); + +static struct op_capability { + uint32_t flag; + const char *str; +} op_caps[] = { + { GENL_ADMIN_PERM, "requires admin permission" }, + { GENL_CMD_CAP_DO, "can modify" }, + { GENL_CMD_CAP_DUMP, "can get/dump" }, + { GENL_CMD_CAP_HASPOL, "has policy" }, +}; + +static void +dump_operations(struct genl_ctrl_ops *ops) +{ + if (ops->num_ops == 0) + return; + printf("\tsupported operations: \n"); + for (uint32_t i = 0; i < ops->num_ops; i++) { + printf("\t - ID: %#02x, Capabilities: %#02x (", + ops->ops[i]->id, + ops->ops[i]->flags); + for (size_t j = 0; j < nitems(op_caps); j++) + if ((ops->ops[i]->flags & op_caps[j].flag) == op_caps[j].flag) + printf("%s; ", op_caps[j].str); + printf("\b\b)\n"); + } +} + +static void +dump_mcast_groups( struct snl_genl_ctrl_mcast_groups *mcast_groups) +{ + if (mcast_groups->num_groups == 0) + return; + printf("\tmulticast groups: \n"); + for (uint32_t i = 0; i < mcast_groups->num_groups; i++) + printf("\t - ID: %#02x, Name: %s\n", + mcast_groups->groups[i]->mcast_grp_id, + mcast_groups->groups[i]->mcast_grp_name); +} + + +static void +dump_family(struct genl_family *family) +{ + printf("Name: %s\n\tID: %#02hx, Version: %#02x, " + "header size: %d, max attributes: %d\n", + family->name, family->id, family->version, + family->hdrsize, family->max_attr); + dump_operations(&family->ops); + dump_mcast_groups(&family->mcast_groups); +} + +int +main(int argc, char **argv __unused) +{ + struct snl_state ss; + struct snl_writer nw; + struct nlmsghdr *hdr; + 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 (!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); + if ((hdr = snl_finalize_msg(&nw)) == NULL) + err(EXIT_FAILURE, "snl_finalize_msg"); + seq_id = hdr->nlmsg_seq; + if (!snl_send_message(&ss, hdr)) + err(EXIT_FAILURE, "snl_send_message"); + + while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { + if (e.error != 0) { + err(EXIT_FAILURE, "Error reading generic netlink"); + } + struct genl_family family = {}; + if (snl_parse_nlmsg(&ss, hdr, &genl_family_parser, &family)) + dump_family(&family); + } + + return (EXIT_SUCCESS); +}