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