summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2020-06-22 13:14:32 +0000
committermpi <mpi@openbsd.org>2020-06-22 13:14:32 +0000
commit7ab02df9ba969938f0d288bc81680642c429c9c4 (patch)
treec8acd59001aa58d4ef33443e29ffa4622b51de89
parentChange tsc_get_timecount return from uint to u_int per sys/timetc.h. (diff)
downloadwireguard-openbsd-7ab02df9ba969938f0d288bc81680642c429c9c4.tar.xz
wireguard-openbsd-7ab02df9ba969938f0d288bc81680642c429c9c4.zip
Extend kqueue interface with EVFILT_EXCEPT filter.
This filter, already implemented in macOS and Dragonfly BSD, returns exceptional conditions like the reception of out-of-band data. The functionnality is similar to poll(2)'s POLLPRI & POLLRDBAND and it can be used by the kqfilter-based poll & select implementation. ok millert@ on a previous version, ok visa@
-rw-r--r--lib/libc/sys/kqueue.211
-rw-r--r--sys/kern/kern_event.c3
-rw-r--r--sys/kern/tty_pty.c23
-rw-r--r--sys/kern/uipc_socket.c22
-rw-r--r--sys/sys/event.h9
5 files changed, 60 insertions, 8 deletions
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index fd5cc41c248..66c92b166c7 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -1,4 +1,4 @@
-.\" $OpenBSD: kqueue.2,v 1.40 2020/05/31 03:49:44 visa Exp $
+.\" $OpenBSD: kqueue.2,v 1.41 2020/06/22 13:14:32 mpi Exp $
.\"
.\" Copyright (c) 2000 Jonathan Lemon
.\" All rights reserved.
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.18 2001/02/14 08:48:35 guido Exp $
.\"
-.Dd $Mdocdate: May 31 2020 $
+.Dd $Mdocdate: June 22 2020 $
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -310,6 +310,13 @@ enabled and there is any data to read;
.Fa data
contains the number of bytes available.
.El
+.It Dv EVFILT_EXCEPT
+Takes a descriptor as the identifier, and returns whenever one of the
+specified exceptional conditions has occured on the descriptor.
+Conditions are specified in
+.Fa fflags .
+Currently, a filter can monitor the reception of out-of-band data with
+.Dv NOTE_OOB .
.It Dv EVFILT_WRITE
Takes a descriptor as the identifier, and returns whenever
it is possible to write to the descriptor.
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 4d0e2c88c5f..ddaf08795ec 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_event.c,v 1.139 2020/06/15 15:42:11 mpi Exp $ */
+/* $OpenBSD: kern_event.c,v 1.140 2020/06/22 13:14:32 mpi Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -158,6 +158,7 @@ const struct filterops *const sysfilt_ops[] = {
&sig_filtops, /* EVFILT_SIGNAL */
&timer_filtops, /* EVFILT_TIMER */
&file_filtops, /* EVFILT_DEVICE */
+ &file_filtops, /* EVFILT_EXCEPT */
};
void
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index 97f41437f8d..18c6a058005 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty_pty.c,v 1.100 2020/06/15 15:29:40 mpi Exp $ */
+/* $OpenBSD: tty_pty.c,v 1.101 2020/06/22 13:14:32 mpi Exp $ */
/* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */
/*
@@ -668,6 +668,16 @@ filt_ptcread(struct knote *kn, long hint)
tp = pti->pt_tty;
kn->kn_data = 0;
+ if (kn->kn_sfflags & NOTE_OOB) {
+ /* If in packet or user control mode, check for data. */
+ if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
+ ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) {
+ kn->kn_fflags |= NOTE_OOB;
+ kn->kn_data = 1;
+ return (1);
+ }
+ return (0);
+ }
if (ISSET(tp->t_state, TS_ISOPEN)) {
if (!ISSET(tp->t_state, TS_TTSTOP))
kn->kn_data = tp->t_outq.c_cc;
@@ -733,6 +743,13 @@ const struct filterops ptcwrite_filtops = {
.f_event = filt_ptcwrite,
};
+const struct filterops ptcexcept_filtops = {
+ .f_flags = FILTEROP_ISFD,
+ .f_attach = NULL,
+ .f_detach = filt_ptcrdetach,
+ .f_event = filt_ptcread,
+};
+
int
ptckqfilter(dev_t dev, struct knote *kn)
{
@@ -749,6 +766,10 @@ ptckqfilter(dev_t dev, struct knote *kn)
klist = &pti->pt_selw.si_note;
kn->kn_fop = &ptcwrite_filtops;
break;
+ case EVFILT_EXCEPT:
+ klist = &pti->pt_selr.si_note;
+ kn->kn_fop = &ptcexcept_filtops;
+ break;
default:
return (EINVAL);
}
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 3d6e12e88bc..8f3ac59436c 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.246 2020/06/18 14:05:21 mvs Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.247 2020/06/22 13:14:32 mpi Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -93,6 +93,12 @@ const struct filterops sowrite_filtops = {
.f_event = filt_sowrite,
};
+const struct filterops soexcept_filtops = {
+ .f_flags = FILTEROP_ISFD,
+ .f_attach = NULL,
+ .f_detach = filt_sordetach,
+ .f_event = filt_soread,
+};
#ifndef SOMINCONN
#define SOMINCONN 80
@@ -2026,6 +2032,10 @@ soo_kqfilter(struct file *fp, struct knote *kn)
kn->kn_fop = &sowrite_filtops;
sb = &so->so_snd;
break;
+ case EVFILT_EXCEPT:
+ kn->kn_fop = &soexcept_filtops;
+ sb = &so->so_rcv;
+ break;
default:
return (EINVAL);
}
@@ -2052,7 +2062,7 @@ int
filt_soread(struct knote *kn, long hint)
{
struct socket *so = kn->kn_fp->f_data;
- int s, rv;
+ int s, rv = 0;
if ((hint & NOTE_SUBMIT) == 0)
s = solock(so);
@@ -2062,7 +2072,13 @@ filt_soread(struct knote *kn, long hint)
rv = 0;
} else
#endif /* SOCKET_SPLICE */
- if (so->so_state & SS_CANTRCVMORE) {
+ if (kn->kn_sfflags & NOTE_OOB) {
+ if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
+ kn->kn_fflags |= NOTE_OOB;
+ kn->kn_data -= so->so_oobmark;
+ rv = 1;
+ }
+ } else if (so->so_state & SS_CANTRCVMORE) {
kn->kn_flags |= EV_EOF;
if (kn->kn_flags & __EV_POLL) {
if (so->so_state & SS_ISDISCONNECTED)
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 93a8a904d90..4a46d97af72 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: event.h,v 1.43 2020/06/15 15:42:11 mpi Exp $ */
+/* $OpenBSD: event.h,v 1.44 2020/06/22 13:14:32 mpi Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -39,6 +39,7 @@
#define EVFILT_SIGNAL (-6) /* attached to struct process */
#define EVFILT_TIMER (-7) /* timers */
#define EVFILT_DEVICE (-8) /* devices */
+#define EVFILT_EXCEPT (-9) /* exceptional conditions */
#define EVFILT_SYSCOUNT 8
@@ -87,6 +88,12 @@ struct kevent {
#define NOTE_EOF 0x0002 /* return on EOF */
/*
+ * data/hint flags for EVFILT_EXCEPT, shared with userspace and with
+ * EVFILT_{READ|WRITE}
+ */
+#define NOTE_OOB 0x0004 /* OOB data on a socket */
+
+/*
* data/hint flags for EVFILT_VNODE, shared with userspace
*/
#define NOTE_DELETE 0x0001 /* vnode was removed */