aboutsummaryrefslogtreecommitdiff
path: root/sys/netlink/netlink_domain.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-04-28 12:44:04 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-04-28 13:54:54 +0000
commit30d7e724db0c9805c9cafdd70a33f546df168d8c (patch)
treef44993e126d8a419dd444e2493b541e0efc8436b /sys/netlink/netlink_domain.c
parent9e79038c502433f077b4d3b5bb1c0838329f1ebc (diff)
Diffstat (limited to 'sys/netlink/netlink_domain.c')
-rw-r--r--sys/netlink/netlink_domain.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index 8b0d09ac0b66..9cc2a5073fdd 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -38,6 +38,7 @@
#include <sys/domain.h>
#include <sys/jail.h>
#include <sys/mbuf.h>
+#include <sys/osd.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/ck.h>
@@ -84,6 +85,38 @@ SYSCTL_OID(_net_netlink, OID_AUTO, nl_maxsockbuf,
sysctl_handle_nl_maxsockbuf, "LU",
"Maximum Netlink socket buffer size");
+
+static unsigned int osd_slot_id = 0;
+
+void
+nl_osd_register(void)
+{
+ osd_slot_id = osd_register(OSD_THREAD, NULL, NULL);
+}
+
+void
+nl_osd_unregister(void)
+{
+ osd_deregister(OSD_THREAD, osd_slot_id);
+}
+
+struct nlpcb *
+_nl_get_thread_nlp(struct thread *td)
+{
+ return (osd_get(OSD_THREAD, &td->td_osd, osd_slot_id));
+}
+
+void
+nl_set_thread_nlp(struct thread *td, struct nlpcb *nlp)
+{
+ NLP_LOG(LOG_DEBUG2, nlp, "Set thread %p nlp to %p (slot %u)", td, nlp, osd_slot_id);
+ if (osd_set(OSD_THREAD, &td->td_osd, osd_slot_id, nlp) == 0)
+ return;
+ /* Failed, need to realloc */
+ void **rsv = osd_reserve(osd_slot_id);
+ osd_set_reserved(OSD_THREAD, &td->td_osd, osd_slot_id, rsv, nlp);
+}
+
/*
* Looks up a nlpcb struct based on the @portid. Need to claim nlsock_mtx.
* Returns nlpcb pointer if present else NULL
@@ -144,6 +177,15 @@ nl_get_groups_compat(struct nlpcb *nlp)
return (groups_mask);
}
+static void
+nl_send_one_group(struct mbuf *m, struct nlpcb *nlp, int num_messages,
+ int io_flags)
+{
+ if (__predict_false(nlp->nl_flags & NLF_MSG_INFO))
+ nl_add_msg_info(m);
+ nl_send_one(m, nlp, num_messages, io_flags);
+}
+
/*
* Broadcasts message @m to the protocol @proto group specified by @group_id
*/
@@ -180,7 +222,8 @@ nl_send_group(struct mbuf *m, int num_messages, int proto, int group_id)
struct mbuf *m_copy;
m_copy = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (m_copy != NULL)
- nl_send_one(m_copy, nlp_last, num_messages, io_flags);
+ nl_send_one_group(m_copy, nlp_last,
+ num_messages, io_flags);
else {
NLP_LOCK(nlp_last);
if (nlp_last->nl_socket != NULL)
@@ -192,7 +235,7 @@ nl_send_group(struct mbuf *m, int num_messages, int proto, int group_id)
}
}
if (nlp_last != NULL)
- nl_send_one(m, nlp_last, num_messages, io_flags);
+ nl_send_one_group(m, nlp_last, num_messages, io_flags);
else
m_freem(m);
@@ -296,6 +339,7 @@ nl_pru_attach(struct socket *so, int proto, struct thread *td)
nlp->nl_linux = is_linux;
nlp->nl_active = true;
nlp->nl_unconstrained_vnet = !jailed_without_vnet(so->so_cred);
+ nlp->nl_need_thread_setup = true;
NLP_LOCK_INIT(nlp);
refcount_init(&nlp->nl_refcount, 1);
nl_init_io(nlp);
@@ -589,6 +633,8 @@ nl_getoptflag(int sopt_name)
return (NLF_EXT_ACK);
case NETLINK_GET_STRICT_CHK:
return (NLF_STRICT);
+ case NETLINK_MSG_INFO:
+ return (NLF_MSG_INFO);
}
return (0);
@@ -630,12 +676,18 @@ nl_ctloutput(struct socket *so, struct sockopt *sopt)
case NETLINK_CAP_ACK:
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
+ case NETLINK_MSG_INFO:
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
if (error != 0)
break;
flag = nl_getoptflag(sopt->sopt_name);
+ if ((flag == NLF_MSG_INFO) && nlp->nl_linux) {
+ error = EINVAL;
+ break;
+ }
+
NLCTL_WLOCK(ctl);
if (optval != 0)
nlp->nl_flags |= flag;
@@ -658,6 +710,7 @@ nl_ctloutput(struct socket *so, struct sockopt *sopt)
case NETLINK_CAP_ACK:
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
+ case NETLINK_MSG_INFO:
NLCTL_RLOCK(ctl);
optval = (nlp->nl_flags & nl_getoptflag(sopt->sopt_name)) != 0;
NLCTL_RUNLOCK(ctl);