Page MenuHomeFreeBSD

D39391.id119781.diff
No OneTemporary

D39391.id119781.diff

diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -405,9 +405,8 @@
snprintf(buf + sz, bufsize - sz, "/%d", plen);
}
-
static int
-print_line_prefix(const char *cmd, const char *name)
+print_line_prefix(struct nlmsghdr *hdr, const char *cmd, const char *name)
{
struct timespec tp;
struct tm tm;
@@ -417,7 +416,8 @@
localtime_r(&tp.tv_sec, &tm);
strftime(buf, sizeof(buf), "%T", &tm);
- int len = printf("%s.%03ld %s %s ", buf, tp.tv_nsec / 1000000, cmd, name);
+ int len = printf("%s.%03ld PID %4u %s %s ", buf, tp.tv_nsec / 1000000,
+ hdr->nlmsg_pid, cmd, name);
return (len);
}
@@ -480,7 +480,7 @@
// 20:19:41.333 add route 10.0.0.0/24 gw 10.0.0.1 ifp vtnet0 mtu 1500 table inet.0
const char *cmd = get_action_name(hdr, RTM_NEWROUTE);
- int len = print_line_prefix(cmd, "route");
+ int len = print_line_prefix(hdr, cmd, "route");
char buf[128];
print_prefix(h, buf, sizeof(buf), r.rta_dst, r.rtm_dst_len);
@@ -545,7 +545,7 @@
// 20:19:41.333 add iface#3 vtnet0 admin UP oper UP mtu 1500 table inet.0
const char *cmd = get_action_name(hdr, RTM_NEWLINK);
- print_line_prefix(cmd, "iface");
+ print_line_prefix(hdr, cmd, "iface");
printf("iface#%u %s ", l.ifi_index, l.ifla_ifname);
printf("admin %s ", (l.ifi_flags & IFF_UP) ? "UP" : "DOWN");
@@ -568,7 +568,7 @@
// add addr 192.168.1.1/24 iface vtnet0
const char *cmd = get_action_name(hdr, RTM_NEWADDR);
- print_line_prefix(cmd, "addr");
+ print_line_prefix(hdr, cmd, "addr");
char buf[128];
struct sockaddr *addr = attrs.ifa_local ? attrs.ifa_local : attrs.ifa_address;
@@ -617,7 +617,7 @@
// add addr 192.168.1.1 state %s lladdr %s iface vtnet0
const char *cmd = get_action_name(hdr, RTM_NEWNEIGH);
- print_line_prefix(cmd, "neigh");
+ print_line_prefix(hdr, cmd, "neigh");
char buf[128];
print_prefix(h, buf, sizeof(buf), attrs.nda_dst, -1);
@@ -719,6 +719,10 @@
#endif
};
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+ setsockopt(ss_event.fd, SOL_NETLINK, NETLINK_MONITOR, &optval, optlen);
+
for (unsigned int i = 0; i < NL_ARRAY_LEN(groups); i++) {
int error;
int optval = groups[i];
diff --git a/sys/netlink/netlink.h b/sys/netlink/netlink.h
--- a/sys/netlink/netlink.h
+++ b/sys/netlink/netlink.h
@@ -89,6 +89,7 @@
#define NETLINK_EXT_ACK 11 /* Ack support for receiving additional TLVs in ack */
#define NETLINK_GET_STRICT_CHK 12 /* Strict header checking */
+#define NETLINK_MONITOR 257 /* Receive originator nl_pid in the notifications */
/*
* RFC 3549, 2.3.2 Netlink Message Header
diff --git a/sys/netlink/netlink_ctl.h b/sys/netlink/netlink_ctl.h
--- a/sys/netlink/netlink_ctl.h
+++ b/sys/netlink/netlink_ctl.h
@@ -108,5 +108,22 @@
typedef void (*genl_family_event_handler_t)(void *arg, const struct genl_family *gf, int action);
EVENTHANDLER_DECLARE(genl_family_event, genl_family_event_handler_t);
+struct thread;
+#if defined(NETLINK) || defined(NETLINK_MODULE)
+/* Provide optimized calls to the functions inside the same linking unit */
+struct nlpcb *_nl_get_thread_nlp(struct thread *td);
+
+static inline struct nlpcb *
+nl_get_thread_nlp(struct thread *td)
+{
+ return (_nl_get_thread_nlp(td));
+}
+
+#else
+/* Provide access to the functions via netlink_glue.c */
+struct nlpcb *nl_get_thread_nlp(struct thread *td);
+
+#endif
+
#endif
#endif
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
--- 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_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_DEBUG, 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 @@
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_MONITOR))
+ nl_set_source_metadata(m, num_messages);
+ 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 @@
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 @@
}
}
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 @@
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 @@
return (NLF_EXT_ACK);
case NETLINK_GET_STRICT_CHK:
return (NLF_STRICT);
+ case NETLINK_MONITOR:
+ return (NLF_MONITOR);
}
return (0);
@@ -630,6 +676,7 @@
case NETLINK_CAP_ACK:
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
+ case NETLINK_MONITOR:
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
if (error != 0)
break;
@@ -642,6 +689,8 @@
else
nlp->nl_flags &= ~flag;
NLCTL_WUNLOCK(ctl);
+ if (sopt->sopt_name == NETLINK_MONITOR && optval)
+ NLP_LOG(LOG_DEBUG, nlp, "MONITOR option set");
break;
default:
error = ENOPROTOOPT;
@@ -658,6 +707,7 @@
case NETLINK_CAP_ACK:
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
+ case NETLINK_MONITOR:
NLCTL_RLOCK(ctl);
optval = (nlp->nl_flags & nl_getoptflag(sopt->sopt_name)) != 0;
NLCTL_RUNLOCK(ctl);
diff --git a/sys/netlink/netlink_glue.c b/sys/netlink/netlink_glue.c
--- a/sys/netlink/netlink_glue.c
+++ b/sys/netlink/netlink_glue.c
@@ -177,6 +177,12 @@
return (false);
}
+static struct nlpcb *
+nl_get_thread_nlp_stub(struct thread *td __unused)
+{
+ return (NULL);
+}
+
const static struct nl_function_wrapper nl_stub = {
.nlmsg_add = nlmsg_add_stub,
.nlmsg_refill_buffer = nlmsg_refill_buffer_stub,
@@ -188,6 +194,7 @@
.nlmsg_get_group_writer = nlmsg_get_group_writer_stub,
.nlmsg_get_chain_writer = nlmsg_get_chain_writer_stub,
.nlmsg_end_dump = nlmsg_end_dump_stub,
+ .nl_get_thread_nlp = nl_get_thread_nlp_stub,
};
/*
@@ -262,5 +269,12 @@
{
return (_nl->nlmsg_end_dump(nw, error, hdr));
}
+
+struct nlpcb *
+nl_get_thread_nlp(struct thread *td)
+{
+ return (_nl->nl_get_thread_nlp(td));
+}
+
#endif /* !NETLINK */
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -257,10 +257,39 @@
{
NL_LOG(LOG_DEBUG3, "taskqueue called");
+ if (__predict_false(nlp->nl_need_thread_setup)) {
+ nl_set_thread_nlp(curthread, nlp);
+ NLP_LOCK(nlp);
+ nlp->nl_need_thread_setup = false;
+ NLP_UNLOCK(nlp);
+ }
+
while (nl_process_received_one(nlp))
;
}
+void
+nl_set_source_metadata(struct mbuf *m, int num_messages)
+{
+ struct nlpcb *nlp = nl_get_thread_nlp(curthread);
+ NL_LOG(LOG_DEBUG, "Trying to recover nlp from thread %p: %p",
+ curthread, nlp);
+
+ if (nlp == NULL)
+ return;
+
+ int max_off = M_TRAILINGSPACE(m);
+ for (int off = 0, count = 0; (count < num_messages) && (off < max_off); ) {
+ /* Update source PID for each of the messages */
+ struct nlmsghdr *hdr = mtodo(m, off);
+ hdr->nlmsg_pid = nlp->nl_port ? nlp->nl_port : nlp->nl_process_id;
+ NL_LOG(LOG_DEBUG, "Setting PID for message %u to %u",
+ hdr->nlmsg_type, hdr->nlmsg_pid);
+ off += NLMSG_ALIGN(hdr->nlmsg_len);
+ count++;
+ }
+}
+
void
nl_init_io(struct nlpcb *nlp)
{
diff --git a/sys/netlink/netlink_module.c b/sys/netlink/netlink_module.c
--- a/sys/netlink/netlink_module.c
+++ b/sys/netlink/netlink_module.c
@@ -219,6 +219,7 @@
switch (what) {
case MOD_LOAD:
NL_LOG(LOG_DEBUG2, "Loading");
+ nl_osd_register();
#if !defined(NETLINK) && defined(NETLINK_MODULE)
nl_set_functions(&nl_module);
#endif
@@ -232,6 +233,7 @@
#if !defined(NETLINK) && defined(NETLINK_MODULE)
nl_set_functions(NULL);
#endif
+ nl_osd_unregister();
} else
ret = EBUSY;
break;
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -62,6 +62,7 @@
bool nl_tx_blocked; /* No new requests accepted */
bool nl_linux; /* true if running under compat */
bool nl_unconstrained_vnet; /* true if running under VNET jail (or without jail) */
+ bool nl_need_thread_setup;
struct nl_io_queue rx_queue;
struct nl_io_queue tx_queue;
struct taskqueue *nl_taskqueue;
@@ -88,6 +89,7 @@
#define NLF_CAP_ACK 0x01 /* Do not send message body with errmsg */
#define NLF_EXT_ACK 0x02 /* Allow including extended TLVs in ack */
#define NLF_STRICT 0x04 /* Perform strict header checks */
+#define NLF_MONITOR 0x08 /* Send original nl_pid in the notifications */
SYSCTL_DECL(_net_netlink);
SYSCTL_DECL(_net_netlink_debug);
@@ -130,6 +132,9 @@
/* netlink_domain.c */
void nl_send_group(struct mbuf *m, int cnt, int proto, int group_id);
+void nl_osd_register(void);
+void nl_osd_unregister(void);
+void nl_set_thread_nlp(struct thread *td, struct nlpcb *nlp);
/* netlink_io.c */
#define NL_IOF_UNTRANSLATED 0x01
@@ -144,6 +149,7 @@
void nl_taskqueue_handler(void *_arg, int pending);
int nl_receive_async(struct mbuf *m, struct socket *so);
void nl_process_receive_locked(struct nlpcb *nlp);
+void nl_set_source_metadata(struct mbuf *m, int num_messages);
/* netlink_generic.c */
struct genl_family {
@@ -185,6 +191,7 @@
bool (*nlmsg_get_group_writer)(struct nl_writer *nw, int size, int protocol, int group_id);
bool (*nlmsg_get_chain_writer)(struct nl_writer *nw, int size, struct mbuf **pm);
bool (*nlmsg_end_dump)(struct nl_writer *nw, int error, struct nlmsghdr *hdr);
+ struct nlpcb * (*nl_get_thread_nlp)(struct thread *td);
};
void nl_set_functions(const struct nl_function_wrapper *nl);

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 30, 8:26 AM (21 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32478937
Default Alt Text
D39391.id119781.diff (10 KB)

Event Timeline