diff options
author | mpi <mpi@openbsd.org> | 2020-06-22 13:14:32 +0000 |
---|---|---|
committer | mpi <mpi@openbsd.org> | 2020-06-22 13:14:32 +0000 |
commit | 7ab02df9ba969938f0d288bc81680642c429c9c4 (patch) | |
tree | c8acd59001aa58d4ef33443e29ffa4622b51de89 | |
parent | Change tsc_get_timecount return from uint to u_int per sys/timetc.h. (diff) | |
download | wireguard-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.2 | 11 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 3 | ||||
-rw-r--r-- | sys/kern/tty_pty.c | 23 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 22 | ||||
-rw-r--r-- | sys/sys/event.h | 9 |
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 */ |