xref: /freebsd/sys/netlink/ktest_netlink_message_writer.c (revision 17083b94a91563aba15ba03d1c74796a35bb1c26)
1c1839039SAlexander V. Chernikov /*-
2c1839039SAlexander V. Chernikov  * SPDX-License-Identifier: BSD-2-Clause
3c1839039SAlexander V. Chernikov  *
4c1839039SAlexander V. Chernikov  * Copyright (c) 2023 Alexander V. Chernikov
5c1839039SAlexander V. Chernikov  *
6c1839039SAlexander V. Chernikov  * Redistribution and use in source and binary forms, with or without
7c1839039SAlexander V. Chernikov  * modification, are permitted provided that the following conditions
8c1839039SAlexander V. Chernikov  * are met:
9c1839039SAlexander V. Chernikov  * 1. Redistributions of source code must retain the above copyright
10c1839039SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer.
11c1839039SAlexander V. Chernikov  * 2. Redistributions in binary form must reproduce the above copyright
12c1839039SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer in the
13c1839039SAlexander V. Chernikov  *    documentation and/or other materials provided with the distribution.
14c1839039SAlexander V. Chernikov  *
15c1839039SAlexander V. Chernikov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c1839039SAlexander V. Chernikov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c1839039SAlexander V. Chernikov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c1839039SAlexander V. Chernikov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c1839039SAlexander V. Chernikov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c1839039SAlexander V. Chernikov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c1839039SAlexander V. Chernikov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c1839039SAlexander V. Chernikov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c1839039SAlexander V. Chernikov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c1839039SAlexander V. Chernikov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c1839039SAlexander V. Chernikov  * SUCH DAMAGE.
26c1839039SAlexander V. Chernikov  */
27c1839039SAlexander V. Chernikov 
28c1839039SAlexander V. Chernikov #include <tests/ktest.h>
29c1839039SAlexander V. Chernikov #include <sys/cdefs.h>
30c1839039SAlexander V. Chernikov #include <sys/systm.h>
31c1839039SAlexander V. Chernikov #include <sys/malloc.h>
32c1839039SAlexander V. Chernikov #include <netlink/netlink.h>
33c1839039SAlexander V. Chernikov #include <netlink/netlink_ctl.h>
34*17083b94SGleb Smirnoff #include <netlink/netlink_var.h>
35c1839039SAlexander V. Chernikov #include <netlink/netlink_message_writer.h>
36c1839039SAlexander V. Chernikov 
37c1839039SAlexander V. Chernikov #define KTEST_CALLER
38c1839039SAlexander V. Chernikov #include <netlink/ktest_netlink_message_writer.h>
39c1839039SAlexander V. Chernikov 
40c1839039SAlexander V. Chernikov #ifdef INVARIANTS
41c1839039SAlexander V. Chernikov 
42*17083b94SGleb Smirnoff struct test_nlbuf_attrs {
43c1839039SAlexander V. Chernikov 	uint32_t	size;
44c1839039SAlexander V. Chernikov 	uint32_t	expected_avail;
45c1839039SAlexander V. Chernikov 	int		waitok;
46c1839039SAlexander V. Chernikov };
47c1839039SAlexander V. Chernikov 
48*17083b94SGleb Smirnoff #define	_OUT(_field)	offsetof(struct test_nlbuf_attrs, _field)
49*17083b94SGleb Smirnoff static const struct nlattr_parser nla_p_nlbuf_w[] = {
50c1839039SAlexander V. Chernikov 	{ .type = 1, .off = _OUT(size), .cb = nlattr_get_uint32 },
51c1839039SAlexander V. Chernikov 	{ .type = 2, .off = _OUT(expected_avail), .cb = nlattr_get_uint32 },
52*17083b94SGleb Smirnoff 	{ .type = 3, .off = _OUT(waitok), .cb = nlattr_get_uint32 },
53c1839039SAlexander V. Chernikov };
54c1839039SAlexander V. Chernikov #undef _OUT
55*17083b94SGleb Smirnoff NL_DECLARE_ATTR_PARSER(nlbuf_w_parser, nla_p_nlbuf_w);
56c1839039SAlexander V. Chernikov 
57c1839039SAlexander V. Chernikov static int
test_nlbuf_parser(struct ktest_test_context * ctx,struct nlattr * nla)58*17083b94SGleb Smirnoff test_nlbuf_parser(struct ktest_test_context *ctx, struct nlattr *nla)
59c1839039SAlexander V. Chernikov {
60*17083b94SGleb Smirnoff 	struct test_nlbuf_attrs *attrs = npt_alloc(ctx->npt, sizeof(*attrs));
61c1839039SAlexander V. Chernikov 
62c1839039SAlexander V. Chernikov 	ctx->arg = attrs;
63c1839039SAlexander V. Chernikov 	if (attrs != NULL)
64*17083b94SGleb Smirnoff 		return (nl_parse_nested(nla, &nlbuf_w_parser, ctx->npt, attrs));
65c1839039SAlexander V. Chernikov 	return (ENOMEM);
66c1839039SAlexander V. Chernikov }
67c1839039SAlexander V. Chernikov 
68c1839039SAlexander V. Chernikov static int
test_nlbuf_writer_allocation(struct ktest_test_context * ctx)69*17083b94SGleb Smirnoff test_nlbuf_writer_allocation(struct ktest_test_context *ctx)
70c1839039SAlexander V. Chernikov {
71*17083b94SGleb Smirnoff 	struct test_nlbuf_attrs *attrs = ctx->arg;
72c1839039SAlexander V. Chernikov 	struct nl_writer nw = {};
73*17083b94SGleb Smirnoff 	u_int alloc_len;
74*17083b94SGleb Smirnoff 	bool ret;
75c1839039SAlexander V. Chernikov 
76*17083b94SGleb Smirnoff 	ret = nlmsg_get_buf_wrapper(&nw, attrs->size, attrs->waitok);
77c1839039SAlexander V. Chernikov 	if (!ret)
78c1839039SAlexander V. Chernikov 		return (EINVAL);
79c1839039SAlexander V. Chernikov 
80*17083b94SGleb Smirnoff 	alloc_len = nw.buf->buflen;
81c1839039SAlexander V. Chernikov 	KTEST_LOG(ctx, "requested %u, allocated %d", attrs->size, alloc_len);
82c1839039SAlexander V. Chernikov 
83c1839039SAlexander V. Chernikov 	/* Mark enomem to avoid reallocation */
84c1839039SAlexander V. Chernikov 	nw.enomem = true;
85c1839039SAlexander V. Chernikov 
86c1839039SAlexander V. Chernikov 	if (nlmsg_reserve_data(&nw, alloc_len, void *) == NULL) {
87c1839039SAlexander V. Chernikov 		KTEST_LOG(ctx, "unable to get %d bytes from the writer", alloc_len);
88c1839039SAlexander V. Chernikov 		return (EINVAL);
89c1839039SAlexander V. Chernikov 	}
90c1839039SAlexander V. Chernikov 
91*17083b94SGleb Smirnoff 	nl_buf_free(nw.buf);
92c1839039SAlexander V. Chernikov 
93c1839039SAlexander V. Chernikov 	if (alloc_len < attrs->expected_avail) {
94c1839039SAlexander V. Chernikov 		KTEST_LOG(ctx, "alloc_len %d, expected %u",
95c1839039SAlexander V. Chernikov 		    alloc_len, attrs->expected_avail);
96c1839039SAlexander V. Chernikov 		return (EINVAL);
97c1839039SAlexander V. Chernikov 	}
98c1839039SAlexander V. Chernikov 
99c1839039SAlexander V. Chernikov 	return (0);
100c1839039SAlexander V. Chernikov }
101c1839039SAlexander V. Chernikov #endif
102c1839039SAlexander V. Chernikov 
103c1839039SAlexander V. Chernikov static const struct ktest_test_info tests[] = {
104c1839039SAlexander V. Chernikov #ifdef INVARIANTS
105c1839039SAlexander V. Chernikov 	{
106*17083b94SGleb Smirnoff 		.name = "test_nlbuf_writer_allocation",
107*17083b94SGleb Smirnoff 		.desc = "test different buffer sizes in the netlink writer",
108*17083b94SGleb Smirnoff 		.func = &test_nlbuf_writer_allocation,
109*17083b94SGleb Smirnoff 		.parse = &test_nlbuf_parser,
110c1839039SAlexander V. Chernikov 	},
111c1839039SAlexander V. Chernikov #endif
112c1839039SAlexander V. Chernikov };
113c1839039SAlexander V. Chernikov KTEST_MODULE_DECLARE(ktest_netlink_message_writer, tests);
114