17e5bf684SAlexander V. Chernikov /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 37e5bf684SAlexander V. Chernikov * 47e5bf684SAlexander V. Chernikov * Copyright (c) 2021 Ng Peng Nam Sean 57e5bf684SAlexander V. Chernikov * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org> 67e5bf684SAlexander V. Chernikov * 77e5bf684SAlexander V. Chernikov * Redistribution and use in source and binary forms, with or without 87e5bf684SAlexander V. Chernikov * modification, are permitted provided that the following conditions 97e5bf684SAlexander V. Chernikov * are met: 107e5bf684SAlexander V. Chernikov * 1. Redistributions of source code must retain the above copyright 117e5bf684SAlexander V. Chernikov * notice, this list of conditions and the following disclaimer. 127e5bf684SAlexander V. Chernikov * 2. Redistributions in binary form must reproduce the above copyright 137e5bf684SAlexander V. Chernikov * notice, this list of conditions and the following disclaimer in the 147e5bf684SAlexander V. Chernikov * documentation and/or other materials provided with the distribution. 157e5bf684SAlexander V. Chernikov * 167e5bf684SAlexander V. Chernikov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 177e5bf684SAlexander V. Chernikov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187e5bf684SAlexander V. Chernikov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197e5bf684SAlexander V. Chernikov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 207e5bf684SAlexander V. Chernikov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217e5bf684SAlexander V. Chernikov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227e5bf684SAlexander V. Chernikov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237e5bf684SAlexander V. Chernikov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247e5bf684SAlexander V. Chernikov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257e5bf684SAlexander V. Chernikov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267e5bf684SAlexander V. Chernikov * SUCH DAMAGE. 277e5bf684SAlexander V. Chernikov */ 287e5bf684SAlexander V. Chernikov #ifndef _NETLINK_NETLINK_VAR_H_ 297e5bf684SAlexander V. Chernikov #define _NETLINK_NETLINK_VAR_H_ 307e5bf684SAlexander V. Chernikov 31dddafa8dSAlexander V. Chernikov #ifdef _KERNEL 32dddafa8dSAlexander V. Chernikov 337e5bf684SAlexander V. Chernikov #include <sys/ck.h> 347e5bf684SAlexander V. Chernikov #include <sys/epoch.h> 357e5bf684SAlexander V. Chernikov #include <sys/sysctl.h> 367e5bf684SAlexander V. Chernikov #include <sys/taskqueue.h> 377e5bf684SAlexander V. Chernikov #include <net/vnet.h> 387e5bf684SAlexander V. Chernikov 397e5bf684SAlexander V. Chernikov #define NLSNDQ 65536 /* Default socket sendspace */ 407e5bf684SAlexander V. Chernikov #define NLRCVQ 65536 /* Default socket recvspace */ 417e5bf684SAlexander V. Chernikov 42d1871547SAlexander V. Chernikov #define NLMBUFSIZE 2048 /* External storage size for Netlink mbufs */ 43d1871547SAlexander V. Chernikov 447e5bf684SAlexander V. Chernikov struct ucred; 457e5bf684SAlexander V. Chernikov 46660bd40aSGleb Smirnoff struct nl_buf { 47660bd40aSGleb Smirnoff TAILQ_ENTRY(nl_buf) tailq; 48660bd40aSGleb Smirnoff u_int buflen; 49660bd40aSGleb Smirnoff u_int datalen; 50660bd40aSGleb Smirnoff u_int offset; 51660bd40aSGleb Smirnoff char data[]; 52660bd40aSGleb Smirnoff }; 53660bd40aSGleb Smirnoff 544dfd380eSAlexander V. Chernikov #define NLP_MAX_GROUPS 128 554dfd380eSAlexander V. Chernikov 567e5bf684SAlexander V. Chernikov struct nlpcb { 577e5bf684SAlexander V. Chernikov struct socket *nl_socket; 584dfd380eSAlexander V. Chernikov uint64_t nl_groups[NLP_MAX_GROUPS / 64]; 597e5bf684SAlexander V. Chernikov uint32_t nl_port; 607e5bf684SAlexander V. Chernikov uint32_t nl_flags; 617e5bf684SAlexander V. Chernikov uint32_t nl_process_id; 627e5bf684SAlexander V. Chernikov int nl_proto; 637e5bf684SAlexander V. Chernikov bool nl_bound; 647e5bf684SAlexander V. Chernikov bool nl_task_pending; 657e5bf684SAlexander V. Chernikov bool nl_tx_blocked; /* No new requests accepted */ 667e5bf684SAlexander V. Chernikov bool nl_linux; /* true if running under compat */ 6704f75b98SAlexander V. Chernikov bool nl_unconstrained_vnet; /* true if running under VNET jail (or without jail) */ 6830d7e724SAlexander V. Chernikov bool nl_need_thread_setup; 697e5bf684SAlexander V. Chernikov struct taskqueue *nl_taskqueue; 707e5bf684SAlexander V. Chernikov struct task nl_task; 717e5bf684SAlexander V. Chernikov struct ucred *nl_cred; /* Copy of nl_socket->so_cred */ 727e5bf684SAlexander V. Chernikov uint64_t nl_dropped_bytes; 737e5bf684SAlexander V. Chernikov uint64_t nl_dropped_messages; 747e5bf684SAlexander V. Chernikov CK_LIST_ENTRY(nlpcb) nl_next; 757e5bf684SAlexander V. Chernikov CK_LIST_ENTRY(nlpcb) nl_port_next; 767e5bf684SAlexander V. Chernikov volatile u_int nl_refcount; 777e5bf684SAlexander V. Chernikov struct mtx nl_lock; 787e5bf684SAlexander V. Chernikov struct epoch_context nl_epoch_ctx; 797e5bf684SAlexander V. Chernikov }; 807e5bf684SAlexander V. Chernikov #define sotonlpcb(so) ((struct nlpcb *)(so)->so_pcb) 817e5bf684SAlexander V. Chernikov 827e5bf684SAlexander V. Chernikov #define NLP_LOCK_INIT(_nlp) mtx_init(&((_nlp)->nl_lock), "nlp mtx", NULL, MTX_DEF) 837e5bf684SAlexander V. Chernikov #define NLP_LOCK_DESTROY(_nlp) mtx_destroy(&((_nlp)->nl_lock)) 847e5bf684SAlexander V. Chernikov #define NLP_LOCK(_nlp) mtx_lock(&((_nlp)->nl_lock)) 857e5bf684SAlexander V. Chernikov #define NLP_UNLOCK(_nlp) mtx_unlock(&((_nlp)->nl_lock)) 867e5bf684SAlexander V. Chernikov 877e5bf684SAlexander V. Chernikov #define ALIGNED_NL_SZ(_data) roundup2((((struct nlmsghdr *)(_data))->nlmsg_len), 16) 887e5bf684SAlexander V. Chernikov 897e5bf684SAlexander V. Chernikov /* nl_flags */ 907e5bf684SAlexander V. Chernikov #define NLF_CAP_ACK 0x01 /* Do not send message body with errmsg */ 917e5bf684SAlexander V. Chernikov #define NLF_EXT_ACK 0x02 /* Allow including extended TLVs in ack */ 927e5bf684SAlexander V. Chernikov #define NLF_STRICT 0x04 /* Perform strict header checks */ 9330d7e724SAlexander V. Chernikov #define NLF_MSG_INFO 0x08 /* Send caller info along with the notifications */ 947e5bf684SAlexander V. Chernikov 957e5bf684SAlexander V. Chernikov SYSCTL_DECL(_net_netlink); 9619e43c16SAlexander V. Chernikov SYSCTL_DECL(_net_netlink_debug); 977e5bf684SAlexander V. Chernikov 987e5bf684SAlexander V. Chernikov struct nl_control { 997e5bf684SAlexander V. Chernikov CK_LIST_HEAD(nl_pid_head, nlpcb) ctl_port_head; 1007e5bf684SAlexander V. Chernikov CK_LIST_HEAD(nlpcb_head, nlpcb) ctl_pcb_head; 1017e5bf684SAlexander V. Chernikov CK_LIST_ENTRY(nl_control) ctl_next; 1027e5bf684SAlexander V. Chernikov struct rmlock ctl_lock; 1037e5bf684SAlexander V. Chernikov }; 1047e5bf684SAlexander V. Chernikov VNET_DECLARE(struct nl_control *, nl_ctl); 1057e5bf684SAlexander V. Chernikov #define V_nl_ctl VNET(nl_ctl) 1067e5bf684SAlexander V. Chernikov 1077e5bf684SAlexander V. Chernikov 1087e5bf684SAlexander V. Chernikov struct sockaddr_nl; 1097e5bf684SAlexander V. Chernikov struct sockaddr; 1107e5bf684SAlexander V. Chernikov struct nlmsghdr; 1117e5bf684SAlexander V. Chernikov 1127e5bf684SAlexander V. Chernikov /* netlink_module.c */ 1137e5bf684SAlexander V. Chernikov struct nl_control *vnet_nl_ctl_init(void); 1147e5bf684SAlexander V. Chernikov 1157e5bf684SAlexander V. Chernikov int nl_verify_proto(int proto); 1167e5bf684SAlexander V. Chernikov const char *nl_get_proto_name(int proto); 1177e5bf684SAlexander V. Chernikov 1187e5bf684SAlexander V. Chernikov extern int netlink_unloading; 1197e5bf684SAlexander V. Chernikov 1207e5bf684SAlexander V. Chernikov struct nl_proto_handler { 1217e5bf684SAlexander V. Chernikov nl_handler_f cb; 1227e5bf684SAlexander V. Chernikov const char *proto_name; 1237e5bf684SAlexander V. Chernikov }; 1247e5bf684SAlexander V. Chernikov extern struct nl_proto_handler *nl_handlers; 1257e5bf684SAlexander V. Chernikov 1267e5bf684SAlexander V. Chernikov /* netlink_domain.c */ 12717083b94SGleb Smirnoff bool nl_send_group(struct nl_writer *); 12830d7e724SAlexander V. Chernikov void nl_osd_register(void); 12930d7e724SAlexander V. Chernikov void nl_osd_unregister(void); 13030d7e724SAlexander V. Chernikov void nl_set_thread_nlp(struct thread *td, struct nlpcb *nlp); 1317e5bf684SAlexander V. Chernikov 1327e5bf684SAlexander V. Chernikov /* netlink_io.c */ 13309fa78d4SGleb Smirnoff bool nl_send(struct nl_writer *, struct nlpcb *); 1347e5bf684SAlexander V. Chernikov void nlmsg_ack(struct nlpcb *nlp, int error, struct nlmsghdr *nlmsg, 1357e5bf684SAlexander V. Chernikov struct nl_pstate *npt); 1367e5bf684SAlexander V. Chernikov void nl_on_transmit(struct nlpcb *nlp); 1377e5bf684SAlexander V. Chernikov 1387e5bf684SAlexander V. Chernikov void nl_taskqueue_handler(void *_arg, int pending); 139660bd40aSGleb Smirnoff void nl_schedule_taskqueue(struct nlpcb *nlp); 1407e5bf684SAlexander V. Chernikov void nl_process_receive_locked(struct nlpcb *nlp); 14130d7e724SAlexander V. Chernikov void nl_set_source_metadata(struct mbuf *m, int num_messages); 14217083b94SGleb Smirnoff struct nl_buf *nl_buf_alloc(size_t len, int mflag); 14317083b94SGleb Smirnoff void nl_buf_free(struct nl_buf *nb); 144d1871547SAlexander V. Chernikov 14519e43c16SAlexander V. Chernikov /* netlink_generic.c */ 14619e43c16SAlexander V. Chernikov struct genl_family { 14719e43c16SAlexander V. Chernikov const char *family_name; 14819e43c16SAlexander V. Chernikov uint16_t family_hdrsize; 14919e43c16SAlexander V. Chernikov uint16_t family_id; 15019e43c16SAlexander V. Chernikov uint16_t family_version; 15119e43c16SAlexander V. Chernikov uint16_t family_attr_max; 15219e43c16SAlexander V. Chernikov uint16_t family_cmd_size; 15319e43c16SAlexander V. Chernikov uint16_t family_num_groups; 15419e43c16SAlexander V. Chernikov struct genl_cmd *family_cmds; 15519e43c16SAlexander V. Chernikov }; 15619e43c16SAlexander V. Chernikov 15719e43c16SAlexander V. Chernikov struct genl_group { 15819e43c16SAlexander V. Chernikov struct genl_family *group_family; 15919e43c16SAlexander V. Chernikov const char *group_name; 16019e43c16SAlexander V. Chernikov }; 16119e43c16SAlexander V. Chernikov 16219e43c16SAlexander V. Chernikov struct genl_family *genl_get_family(uint32_t family_id); 16319e43c16SAlexander V. Chernikov struct genl_group *genl_get_group(uint32_t group_id); 16419e43c16SAlexander V. Chernikov 16519e43c16SAlexander V. Chernikov #define MAX_FAMILIES 20 16619e43c16SAlexander V. Chernikov #define MAX_GROUPS 64 16719e43c16SAlexander V. Chernikov 16819e43c16SAlexander V. Chernikov #define MIN_GROUP_NUM 48 16919e43c16SAlexander V. Chernikov 17019e43c16SAlexander V. Chernikov #define CTRL_FAMILY_NAME "nlctrl" 17119e43c16SAlexander V. Chernikov 172089104e0SAlexander V. Chernikov struct ifnet; 173089104e0SAlexander V. Chernikov struct nl_parsed_link; 174089104e0SAlexander V. Chernikov struct nlattr_bmask; 175089104e0SAlexander V. Chernikov struct nl_pstate; 176089104e0SAlexander V. Chernikov 17719e43c16SAlexander V. Chernikov /* Function map */ 17819e43c16SAlexander V. Chernikov struct nl_function_wrapper { 17919e43c16SAlexander V. Chernikov bool (*nlmsg_add)(struct nl_writer *nw, uint32_t portid, uint32_t seq, uint16_t type, 18019e43c16SAlexander V. Chernikov uint16_t flags, uint32_t len); 18119e43c16SAlexander V. Chernikov bool (*nlmsg_refill_buffer)(struct nl_writer *nw, int required_len); 18219e43c16SAlexander V. Chernikov bool (*nlmsg_flush)(struct nl_writer *nw); 18319e43c16SAlexander V. Chernikov bool (*nlmsg_end)(struct nl_writer *nw); 18419e43c16SAlexander V. Chernikov void (*nlmsg_abort)(struct nl_writer *nw); 18519e43c16SAlexander V. Chernikov void (*nlmsg_ignore_limit)(struct nl_writer *nw); 18619e43c16SAlexander V. Chernikov bool (*nlmsg_get_unicast_writer)(struct nl_writer *nw, int size, struct nlpcb *nlp); 18719e43c16SAlexander V. Chernikov bool (*nlmsg_get_group_writer)(struct nl_writer *nw, int size, int protocol, int group_id); 18819e43c16SAlexander V. Chernikov bool (*nlmsg_get_chain_writer)(struct nl_writer *nw, int size, struct mbuf **pm); 18919e43c16SAlexander V. Chernikov bool (*nlmsg_end_dump)(struct nl_writer *nw, int error, struct nlmsghdr *hdr); 190089104e0SAlexander V. Chernikov int (*nl_modify_ifp_generic)(struct ifnet *ifp, struct nl_parsed_link *lattrs, 191089104e0SAlexander V. Chernikov const struct nlattr_bmask *bm, struct nl_pstate *npt); 192089104e0SAlexander V. Chernikov void (*nl_store_ifp_cookie)(struct nl_pstate *npt, struct ifnet *ifp); 19330d7e724SAlexander V. Chernikov struct nlpcb * (*nl_get_thread_nlp)(struct thread *td); 19419e43c16SAlexander V. Chernikov }; 19519e43c16SAlexander V. Chernikov void nl_set_functions(const struct nl_function_wrapper *nl); 19619e43c16SAlexander V. Chernikov 197089104e0SAlexander V. Chernikov 198089104e0SAlexander V. Chernikov 1997e5bf684SAlexander V. Chernikov #endif 200dddafa8dSAlexander V. Chernikov #endif 201