xref: /freebsd-src/sys/netlink/netlink_glue.c (revision 0fda4ffd69054217096dd1a40355d97be9a8ab94)
1d3a49f62SAlexander V. Chernikov /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d3a49f62SAlexander V. Chernikov  *
4d3a49f62SAlexander V. Chernikov  * Copyright (c) 2023 Alexander V. Chernikov <melifaro@FreeBSD.org>
5d3a49f62SAlexander V. Chernikov  *
6d3a49f62SAlexander V. Chernikov  * Redistribution and use in source and binary forms, with or without
7d3a49f62SAlexander V. Chernikov  * modification, are permitted provided that the following conditions
8d3a49f62SAlexander V. Chernikov  * are met:
9d3a49f62SAlexander V. Chernikov  * 1. Redistributions of source code must retain the above copyright
10d3a49f62SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer.
11d3a49f62SAlexander V. Chernikov  * 2. Redistributions in binary form must reproduce the above copyright
12d3a49f62SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer in the
13d3a49f62SAlexander V. Chernikov  *    documentation and/or other materials provided with the distribution.
14d3a49f62SAlexander V. Chernikov  *
15d3a49f62SAlexander V. Chernikov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d3a49f62SAlexander V. Chernikov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d3a49f62SAlexander V. Chernikov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d3a49f62SAlexander V. Chernikov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d3a49f62SAlexander V. Chernikov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d3a49f62SAlexander V. Chernikov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d3a49f62SAlexander V. Chernikov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d3a49f62SAlexander V. Chernikov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23d3a49f62SAlexander V. Chernikov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d3a49f62SAlexander V. Chernikov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d3a49f62SAlexander V. Chernikov  * SUCH DAMAGE.
26d3a49f62SAlexander V. Chernikov  */
27d3a49f62SAlexander V. Chernikov 
28d3a49f62SAlexander V. Chernikov #include <sys/param.h>
29d3a49f62SAlexander V. Chernikov #include <sys/kernel.h>
30d3a49f62SAlexander V. Chernikov #include <sys/malloc.h>
31d3a49f62SAlexander V. Chernikov #include <sys/lock.h>
32d3a49f62SAlexander V. Chernikov #include <sys/rmlock.h>
33d3a49f62SAlexander V. Chernikov #include <sys/domain.h>
34d3a49f62SAlexander V. Chernikov #include <sys/mbuf.h>
35d3a49f62SAlexander V. Chernikov #include <sys/protosw.h>
36d3a49f62SAlexander V. Chernikov #include <sys/proc.h>
37d3a49f62SAlexander V. Chernikov #include <sys/ck.h>
38d3a49f62SAlexander V. Chernikov #include <sys/socket.h>
39d3a49f62SAlexander V. Chernikov #include <sys/socketvar.h>
40d3a49f62SAlexander V. Chernikov #include <sys/sysent.h>
41d3a49f62SAlexander V. Chernikov #include <sys/syslog.h>
42d3a49f62SAlexander V. Chernikov #include <sys/priv.h> /* priv_check */
43d3a49f62SAlexander V. Chernikov 
44d3a49f62SAlexander V. Chernikov #include <net/route.h>
45d3a49f62SAlexander V. Chernikov #include <net/route/route_ctl.h>
46d3a49f62SAlexander V. Chernikov 
47d3a49f62SAlexander V. Chernikov #include <netlink/netlink.h>
48d3a49f62SAlexander V. Chernikov #include <netlink/netlink_ctl.h>
49d3a49f62SAlexander V. Chernikov #include <netlink/netlink_var.h>
50a1db1097SAlexander V. Chernikov #include <netlink/route/route_var.h>
51d3a49f62SAlexander V. Chernikov 
52d3a49f62SAlexander V. Chernikov /* Standard bits: built-in the kernel */
5320010b86SEd Maste SYSCTL_NODE(_net, OID_AUTO, netlink, CTLFLAG_RD, 0,
5420010b86SEd Maste     "RFC3549 Netlink network state socket family");
5520010b86SEd Maste SYSCTL_NODE(_net_netlink, OID_AUTO, debug, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
5620010b86SEd Maste     "Netlink per-subsystem debug levels");
57d3a49f62SAlexander V. Chernikov 
58d3a49f62SAlexander V. Chernikov MALLOC_DEFINE(M_NETLINK, "netlink", "Memory used for netlink packets");
59d3a49f62SAlexander V. Chernikov 
60d3a49f62SAlexander V. Chernikov /* Netlink-related callbacks needed to glue rtsock, netlink and linuxolator */
61d3a49f62SAlexander V. Chernikov static void
62d3a49f62SAlexander V. Chernikov ignore_route_event(uint32_t fibnum, const struct rib_cmd_info *rc)
63d3a49f62SAlexander V. Chernikov {
64d3a49f62SAlexander V. Chernikov }
65d3a49f62SAlexander V. Chernikov 
66d3a49f62SAlexander V. Chernikov static void
67d3a49f62SAlexander V. Chernikov ignore_ifmsg_event(struct ifnet *ifp, int if_flags_mask)
68d3a49f62SAlexander V. Chernikov {
69d3a49f62SAlexander V. Chernikov }
70d3a49f62SAlexander V. Chernikov 
71d3a49f62SAlexander V. Chernikov static struct rtbridge ignore_cb = {
72d3a49f62SAlexander V. Chernikov 	.route_f = ignore_route_event,
73d3a49f62SAlexander V. Chernikov 	.ifmsg_f = ignore_ifmsg_event,
74d3a49f62SAlexander V. Chernikov };
75d3a49f62SAlexander V. Chernikov 
76d3a49f62SAlexander V. Chernikov void *linux_netlink_p = NULL; /* Callback pointer for Linux translator functions */
77d3a49f62SAlexander V. Chernikov struct rtbridge *rtsock_callback_p = &ignore_cb;
78d3a49f62SAlexander V. Chernikov struct rtbridge *netlink_callback_p = &ignore_cb;
79d3a49f62SAlexander V. Chernikov 
80d3a49f62SAlexander V. Chernikov 
81d3a49f62SAlexander V. Chernikov /*
82d3a49f62SAlexander V. Chernikov  * nlp accessors.
83d3a49f62SAlexander V. Chernikov  * TODO: move to a separate file once the number grows.
84d3a49f62SAlexander V. Chernikov  */
85d3a49f62SAlexander V. Chernikov bool
86d3a49f62SAlexander V. Chernikov nlp_has_priv(struct nlpcb *nlp, int priv)
87d3a49f62SAlexander V. Chernikov {
88d3a49f62SAlexander V. Chernikov 	return (priv_check_cred(nlp->nl_cred, priv) == 0);
89d3a49f62SAlexander V. Chernikov }
90d3a49f62SAlexander V. Chernikov 
91d3a49f62SAlexander V. Chernikov struct ucred *
92d3a49f62SAlexander V. Chernikov nlp_get_cred(struct nlpcb *nlp)
93d3a49f62SAlexander V. Chernikov {
94d3a49f62SAlexander V. Chernikov 	return (nlp->nl_cred);
95d3a49f62SAlexander V. Chernikov }
96d3a49f62SAlexander V. Chernikov 
97d3a49f62SAlexander V. Chernikov uint32_t
98d3a49f62SAlexander V. Chernikov nlp_get_pid(const struct nlpcb *nlp)
99d3a49f62SAlexander V. Chernikov {
100d3a49f62SAlexander V. Chernikov 	return (nlp->nl_process_id);
101d3a49f62SAlexander V. Chernikov }
102d3a49f62SAlexander V. Chernikov 
103d3a49f62SAlexander V. Chernikov bool
104d3a49f62SAlexander V. Chernikov nlp_unconstrained_vnet(const struct nlpcb *nlp)
105d3a49f62SAlexander V. Chernikov {
106d3a49f62SAlexander V. Chernikov 	return (nlp->nl_unconstrained_vnet);
107d3a49f62SAlexander V. Chernikov }
108d3a49f62SAlexander V. Chernikov 
109d3a49f62SAlexander V. Chernikov #ifndef NETLINK
110d3a49f62SAlexander V. Chernikov /* Stub implementations for the loadable functions */
111d3a49f62SAlexander V. Chernikov 
112d3a49f62SAlexander V. Chernikov static bool
113a034c0aeSGleb Smirnoff nl_writer_unicast_stub(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
114a034c0aeSGleb Smirnoff     bool waitok)
115d3a49f62SAlexander V. Chernikov {
116d3a49f62SAlexander V. Chernikov 	return (get_stub_writer(nw));
117d3a49f62SAlexander V. Chernikov }
118d3a49f62SAlexander V. Chernikov 
119d3a49f62SAlexander V. Chernikov static bool
120a034c0aeSGleb Smirnoff nl_writer_group_stub(struct nl_writer *nw, size_t size, uint16_t protocol,
121*0fda4ffdSGleb Smirnoff     uint16_t group_id, int priv, bool waitok)
122d3a49f62SAlexander V. Chernikov {
123d3a49f62SAlexander V. Chernikov 	return (get_stub_writer(nw));
124d3a49f62SAlexander V. Chernikov }
125d3a49f62SAlexander V. Chernikov 
126d3a49f62SAlexander V. Chernikov static bool
127d3a49f62SAlexander V. Chernikov nlmsg_flush_stub(struct nl_writer *nw __unused)
128d3a49f62SAlexander V. Chernikov {
129d3a49f62SAlexander V. Chernikov 	return (false);
130d3a49f62SAlexander V. Chernikov }
131d3a49f62SAlexander V. Chernikov 
132d3a49f62SAlexander V. Chernikov static void
133d3a49f62SAlexander V. Chernikov nlmsg_ignore_limit_stub(struct nl_writer *nw __unused)
134d3a49f62SAlexander V. Chernikov {
135d3a49f62SAlexander V. Chernikov }
136d3a49f62SAlexander V. Chernikov 
137d3a49f62SAlexander V. Chernikov static bool
138f1c6edbaSGleb Smirnoff nlmsg_refill_buffer_stub(struct nl_writer *nw __unused,
139f1c6edbaSGleb Smirnoff     size_t required_len __unused)
140d3a49f62SAlexander V. Chernikov {
141d3a49f62SAlexander V. Chernikov 	return (false);
142d3a49f62SAlexander V. Chernikov }
143d3a49f62SAlexander V. Chernikov 
144d3a49f62SAlexander V. Chernikov static bool
145d3a49f62SAlexander V. Chernikov nlmsg_add_stub(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type,
146d3a49f62SAlexander V. Chernikov     uint16_t flags, uint32_t len)
147d3a49f62SAlexander V. Chernikov {
148d3a49f62SAlexander V. Chernikov 	return (false);
149d3a49f62SAlexander V. Chernikov }
150d3a49f62SAlexander V. Chernikov 
151d3a49f62SAlexander V. Chernikov static bool
152d3a49f62SAlexander V. Chernikov nlmsg_end_stub(struct nl_writer *nw __unused)
153d3a49f62SAlexander V. Chernikov {
154d3a49f62SAlexander V. Chernikov 	return (false);
155d3a49f62SAlexander V. Chernikov }
156d3a49f62SAlexander V. Chernikov 
157d3a49f62SAlexander V. Chernikov static void
158d3a49f62SAlexander V. Chernikov nlmsg_abort_stub(struct nl_writer *nw __unused)
159d3a49f62SAlexander V. Chernikov {
160d3a49f62SAlexander V. Chernikov }
161d3a49f62SAlexander V. Chernikov 
162d3a49f62SAlexander V. Chernikov static bool
163d3a49f62SAlexander V. Chernikov nlmsg_end_dump_stub(struct nl_writer *nw, int error, struct nlmsghdr *hdr)
164d3a49f62SAlexander V. Chernikov {
165d3a49f62SAlexander V. Chernikov 	return (false);
166d3a49f62SAlexander V. Chernikov }
167d3a49f62SAlexander V. Chernikov 
168089104e0SAlexander V. Chernikov static int
169089104e0SAlexander V. Chernikov nl_modify_ifp_generic_stub(struct ifnet *ifp __unused,
170089104e0SAlexander V. Chernikov     struct nl_parsed_link *lattrs __unused, const struct nlattr_bmask *bm __unused,
171089104e0SAlexander V. Chernikov     struct nl_pstate *npt __unused)
172089104e0SAlexander V. Chernikov {
173089104e0SAlexander V. Chernikov 	return (ENOTSUP);
174089104e0SAlexander V. Chernikov }
175089104e0SAlexander V. Chernikov 
176089104e0SAlexander V. Chernikov static void
177089104e0SAlexander V. Chernikov nl_store_ifp_cookie_stub(struct nl_pstate *npt __unused, struct ifnet *ifp __unused)
178089104e0SAlexander V. Chernikov {
179089104e0SAlexander V. Chernikov }
180089104e0SAlexander V. Chernikov 
18130d7e724SAlexander V. Chernikov static struct nlpcb *
18230d7e724SAlexander V. Chernikov nl_get_thread_nlp_stub(struct thread *td __unused)
18330d7e724SAlexander V. Chernikov {
18430d7e724SAlexander V. Chernikov 	return (NULL);
18530d7e724SAlexander V. Chernikov }
18630d7e724SAlexander V. Chernikov 
187d3a49f62SAlexander V. Chernikov const static struct nl_function_wrapper nl_stub = {
188d3a49f62SAlexander V. Chernikov 	.nlmsg_add = nlmsg_add_stub,
189d3a49f62SAlexander V. Chernikov 	.nlmsg_refill_buffer = nlmsg_refill_buffer_stub,
190d3a49f62SAlexander V. Chernikov 	.nlmsg_flush = nlmsg_flush_stub,
191d3a49f62SAlexander V. Chernikov 	.nlmsg_end = nlmsg_end_stub,
192d3a49f62SAlexander V. Chernikov 	.nlmsg_abort = nlmsg_abort_stub,
193d3a49f62SAlexander V. Chernikov 	.nlmsg_ignore_limit = nlmsg_ignore_limit_stub,
194a034c0aeSGleb Smirnoff 	.nl_writer_unicast = nl_writer_unicast_stub,
195a034c0aeSGleb Smirnoff 	.nl_writer_group = nl_writer_group_stub,
196d3a49f62SAlexander V. Chernikov 	.nlmsg_end_dump = nlmsg_end_dump_stub,
197089104e0SAlexander V. Chernikov 	.nl_modify_ifp_generic = nl_modify_ifp_generic_stub,
198089104e0SAlexander V. Chernikov 	.nl_store_ifp_cookie = nl_store_ifp_cookie_stub,
19930d7e724SAlexander V. Chernikov 	.nl_get_thread_nlp = nl_get_thread_nlp_stub,
200d3a49f62SAlexander V. Chernikov };
201d3a49f62SAlexander V. Chernikov 
202d3a49f62SAlexander V. Chernikov /*
203d3a49f62SAlexander V. Chernikov  * If the kernel is compiled with netlink as a module,
204d3a49f62SAlexander V. Chernikov  *  provide a way to introduce non-stub functioms
205d3a49f62SAlexander V. Chernikov  */
206d3a49f62SAlexander V. Chernikov static const struct nl_function_wrapper *_nl = &nl_stub;
207d3a49f62SAlexander V. Chernikov 
208d3a49f62SAlexander V. Chernikov void
209d3a49f62SAlexander V. Chernikov nl_set_functions(const struct nl_function_wrapper *nl)
210d3a49f62SAlexander V. Chernikov {
211d3a49f62SAlexander V. Chernikov 	_nl = (nl != NULL) ? nl : &nl_stub;
212d3a49f62SAlexander V. Chernikov }
213d3a49f62SAlexander V. Chernikov 
214d3a49f62SAlexander V. Chernikov /* Function wrappers */
215d3a49f62SAlexander V. Chernikov bool
216a034c0aeSGleb Smirnoff nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
217a034c0aeSGleb Smirnoff     bool waitok)
218d3a49f62SAlexander V. Chernikov {
219a034c0aeSGleb Smirnoff 	return (_nl->nl_writer_unicast(nw, size, nlp, waitok));
220d3a49f62SAlexander V. Chernikov }
221d3a49f62SAlexander V. Chernikov 
222d3a49f62SAlexander V. Chernikov bool
223a034c0aeSGleb Smirnoff nl_writer_group(struct nl_writer *nw, size_t size, uint16_t protocol,
224*0fda4ffdSGleb Smirnoff     uint16_t group_id, int priv, bool waitok)
225d3a49f62SAlexander V. Chernikov {
226*0fda4ffdSGleb Smirnoff 	return (_nl->nl_writer_group(nw, size, protocol, group_id, priv,
227*0fda4ffdSGleb Smirnoff 	    waitok));
228d3a49f62SAlexander V. Chernikov }
229d3a49f62SAlexander V. Chernikov 
230d3a49f62SAlexander V. Chernikov bool
231d3a49f62SAlexander V. Chernikov nlmsg_flush(struct nl_writer *nw)
232d3a49f62SAlexander V. Chernikov {
233d3a49f62SAlexander V. Chernikov 	return (_nl->nlmsg_flush(nw));
234d3a49f62SAlexander V. Chernikov }
235d3a49f62SAlexander V. Chernikov 
236d3a49f62SAlexander V. Chernikov void nlmsg_ignore_limit(struct nl_writer *nw)
237d3a49f62SAlexander V. Chernikov {
238d3a49f62SAlexander V. Chernikov 	_nl->nlmsg_ignore_limit(nw);
239d3a49f62SAlexander V. Chernikov }
240d3a49f62SAlexander V. Chernikov 
241d3a49f62SAlexander V. Chernikov bool
242f1c6edbaSGleb Smirnoff nlmsg_refill_buffer(struct nl_writer *nw, size_t required_len)
243d3a49f62SAlexander V. Chernikov {
244d3a49f62SAlexander V. Chernikov 	return (_nl->nlmsg_refill_buffer(nw, required_len));
245d3a49f62SAlexander V. Chernikov }
246d3a49f62SAlexander V. Chernikov 
247d3a49f62SAlexander V. Chernikov bool
248d3a49f62SAlexander V. Chernikov nlmsg_add(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type,
249d3a49f62SAlexander V. Chernikov     uint16_t flags, uint32_t len)
250d3a49f62SAlexander V. Chernikov {
251d3a49f62SAlexander V. Chernikov 	return (_nl->nlmsg_add(nw, portid, seq, type, flags, len));
252d3a49f62SAlexander V. Chernikov }
253d3a49f62SAlexander V. Chernikov 
254d3a49f62SAlexander V. Chernikov bool
255d3a49f62SAlexander V. Chernikov nlmsg_end(struct nl_writer *nw)
256d3a49f62SAlexander V. Chernikov {
257d3a49f62SAlexander V. Chernikov 	return (_nl->nlmsg_end(nw));
258d3a49f62SAlexander V. Chernikov }
259d3a49f62SAlexander V. Chernikov 
260d3a49f62SAlexander V. Chernikov void
261d3a49f62SAlexander V. Chernikov nlmsg_abort(struct nl_writer *nw)
262d3a49f62SAlexander V. Chernikov {
263d3a49f62SAlexander V. Chernikov 	_nl->nlmsg_abort(nw);
264d3a49f62SAlexander V. Chernikov }
265d3a49f62SAlexander V. Chernikov 
266d3a49f62SAlexander V. Chernikov bool
267d3a49f62SAlexander V. Chernikov nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr)
268d3a49f62SAlexander V. Chernikov {
269d3a49f62SAlexander V. Chernikov 	return (_nl->nlmsg_end_dump(nw, error, hdr));
270d3a49f62SAlexander V. Chernikov }
271089104e0SAlexander V. Chernikov 
272089104e0SAlexander V. Chernikov int
273089104e0SAlexander V. Chernikov nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs,
274089104e0SAlexander V. Chernikov     const struct nlattr_bmask *bm , struct nl_pstate *npt)
275089104e0SAlexander V. Chernikov {
276a1db1097SAlexander V. Chernikov 	return (_nl->nl_modify_ifp_generic(ifp, lattrs, bm, npt));
277089104e0SAlexander V. Chernikov }
278089104e0SAlexander V. Chernikov 
279a1db1097SAlexander V. Chernikov void
280a1db1097SAlexander V. Chernikov nl_store_ifp_cookie(struct nl_pstate *npt, struct ifnet *ifp)
281089104e0SAlexander V. Chernikov {
282089104e0SAlexander V. Chernikov 	return (_nl->nl_store_ifp_cookie(npt, ifp));
283089104e0SAlexander V. Chernikov }
284089104e0SAlexander V. Chernikov 
28530d7e724SAlexander V. Chernikov struct nlpcb *
28630d7e724SAlexander V. Chernikov nl_get_thread_nlp(struct thread *td)
28730d7e724SAlexander V. Chernikov {
28830d7e724SAlexander V. Chernikov 	return (_nl->nl_get_thread_nlp(td));
28930d7e724SAlexander V. Chernikov }
29030d7e724SAlexander V. Chernikov 
291d3a49f62SAlexander V. Chernikov #endif /* !NETLINK */
292d3a49f62SAlexander V. Chernikov 
293