]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Support all vnode note types
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 24 Sep 2017 14:25:41 +0000 (22:25 +0800)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 24 Sep 2017 14:25:59 +0000 (22:25 +0800)
Extends the event API to allow callbacks to be registered for all vnode NOTE_* events.

17 files changed:
src/include/event.h
src/lib/io/network.c
src/lib/ldap/bind.c
src/lib/ldap/sasl.c
src/lib/ldap/start_tls.c
src/lib/util/event.c
src/main/connection.c
src/main/process.c
src/main/radsniff.c
src/main/unlang_interpret.c
src/modules/proto_bfd/proto_bfd.c
src/modules/rlm_logtee/rlm_logtee.c
src/modules/rlm_radius/rlm_radius_udp.c
src/modules/rlm_radius/track.c
src/modules/rlm_radius/track.h
src/modules/rlm_rest/io.c
src/modules/rlm_unbound/rlm_unbound.c

index 3aa8425419faf88430cd571d0717696cac7c823f..6dba0753fd4c35c9329684304e56881fadf05fc3 100644 (file)
@@ -50,12 +50,19 @@ typedef struct fr_event_timer fr_event_timer_t;
  */
 typedef struct fr_event_pid fr_event_pid_t;
 
+/** The type of filter to install for an FD
+ */
+typedef enum {
+       FR_EVENT_FILTER_IO,
+       FR_EVENT_FILTER_VNODE
+} fr_event_filter_t;
+
 /** Called when a timer event fires
  *
  * @param[in] now      The current time.
  * @param[in] uctx     User ctx passed to #fr_event_timer_insert.
  */
-typedef        void (*fr_event_callback_t)(fr_event_list_t *el, struct timeval *now, void *uctx);
+typedef        void (*fr_event_cb_t)(fr_event_list_t *el, struct timeval *now, void *uctx);
 
 /** Called after each event loop cycle
  *
@@ -64,7 +71,7 @@ typedef       void (*fr_event_callback_t)(fr_event_list_t *el, struct timeval *now, vo
  * @param[in] now      The current time.
  * @param[in] uctx     User ctx passed to #fr_event_list_alloc.
  */
-typedef        int (*fr_event_status_t)(void *uctx, struct timeval *now);
+typedef        int (*fr_event_status_cb_t)(void *uctx, struct timeval *now);
 
 /** Called when an IO event occurs on a file descriptor
  *
@@ -73,7 +80,7 @@ typedef       int (*fr_event_status_t)(void *uctx, struct timeval *now);
  * @param[in] flags    field as returned by kevent.
  * @param[in] uctx     User ctx passed to #fr_event_fd_insert.
  */
-typedef void (*fr_event_fd_io_t)(fr_event_list_t *el, int fd, int flags, void *uctx);
+typedef void (*fr_event_fd_cb_t)(fr_event_list_t *el, int fd, int flags, void *uctx);
 
 /** Called when an IO error event occurs on a file descriptor
  *
@@ -83,7 +90,7 @@ typedef void (*fr_event_fd_io_t)(fr_event_list_t *el, int fd, int flags, void *u
  * @param[in] fd_errno File descriptor error.
  * @param[in] uctx     User ctx passed to #fr_event_fd_insert.
  */
-typedef void (*fr_event_fd_error_t)(fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx);
+typedef void (*fr_event_error_cb_t)(fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx);
 
 /** Called when a child process has exited
  *
@@ -92,7 +99,7 @@ typedef void (*fr_event_fd_error_t)(fr_event_list_t *el, int fd, int flags, int
  * @param[in] status   exit status
  * @param[in] uctx     User ctx passed to #fr_event_fd_insert.
  */
-typedef void (*fr_event_pid_callback_t)(fr_event_list_t *el, pid_t pid, int status, void *uctx);
+typedef void (*fr_event_pid_cb_t)(fr_event_list_t *el, pid_t pid, int status, void *uctx);
 
 /** Called when a user kevent occurs
  *
@@ -102,35 +109,62 @@ typedef void (*fr_event_pid_callback_t)(fr_event_list_t *el, pid_t pid, int stat
  */
 typedef void (*fr_event_user_handler_t)(int kq, struct kevent const *kev, void *uctx);
 
+/** Callbacks for the #FR_EVENT_FILTER_IO filter
+ */
+typedef struct {
+       fr_event_fd_cb_t        read;                   //!< Callback for when data is available.
+       fr_event_fd_cb_t        write;                  //!< Callback for when we can write data.
+} fr_event_io_func_t;
+
+/** Callbacks for the #FR_EVENT_FILTER_VNODE filter
+ */
+typedef struct {
+       fr_event_fd_cb_t        delete;                 //!< The file was deleted.
+       fr_event_fd_cb_t        write;                  //!< The file was written to.
+       fr_event_fd_cb_t        extend;                 //!< Additional files were added to a directory.
+       fr_event_fd_cb_t        attrib;                 //!< File attributes changed.
+       fr_event_fd_cb_t        link;                   //!< The link count on the file changed.
+       fr_event_fd_cb_t        rename;                 //!< The file was renamed.
+       fr_event_fd_cb_t        revoke;                 //!< Volume containing the file was unmounted or
+                                                       ///< access was revoked with revoke().
+       fr_event_fd_cb_t        funlock;                //!< The file was unlocked.
+} fr_event_vnode_func_t;
+
 int            fr_event_list_num_fds(fr_event_list_t *el);
 int            fr_event_list_num_elements(fr_event_list_t *el);
 int            fr_event_list_kq(fr_event_list_t *el);
 int            fr_event_list_time(struct timeval *when, fr_event_list_t *el);
 
 int            fr_event_fd_delete(fr_event_list_t *el, int fd);
+
+int            fr_event_filter_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
+                                      fr_event_filter_t filter,
+                                      void *funcs,
+                                      fr_event_error_cb_t error,
+                                      void *uctx);
+
 int            fr_event_fd_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
-                                  fr_event_fd_io_t read_fn,
-                                  fr_event_fd_io_t write_fn,
-                                  fr_event_fd_io_t vnode_fn,
-                                  fr_event_fd_error_t error,
+                                  fr_event_fd_cb_t read_fn,
+                                  fr_event_fd_cb_t write_fn,
+                                  fr_event_error_cb_t error,
                                   void *uctx);
 
 int            fr_event_pid_wait(TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_pid_t const **ev_p,
-                                 pid_t pid, fr_event_pid_callback_t wait_fn, void *uctx) CC_HINT(nonnull(2,5));
+                                 pid_t pid, fr_event_pid_cb_t wait_fn, void *uctx) CC_HINT(nonnull(2,5));
 
 int            fr_event_timer_insert(TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev,
-                                     struct timeval *when, fr_event_callback_t callback, void const *uctx);
+                                     struct timeval *when, fr_event_cb_t callback, void const *uctx);
 int            fr_event_timer_delete(fr_event_list_t *el, fr_event_timer_t const **ev);
 int            fr_event_timer_run(fr_event_list_t *el, struct timeval *when);
 
 uintptr_t              fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *uctx) CC_HINT(nonnull(1,2));
 int            fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t user, void *uctx) CC_HINT(nonnull(1,2));
 
-int            fr_event_pre_insert(fr_event_list_t *el, fr_event_status_t callback, void *uctx) CC_HINT(nonnull(1,2));
-int            fr_event_pre_delete(fr_event_list_t *el, fr_event_status_t callback, void *uctx) CC_HINT(nonnull(1,2));
+int            fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
+int            fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
 
-int            fr_event_post_insert(fr_event_list_t *el, fr_event_callback_t callback, void *uctx) CC_HINT(nonnull(1,2));
-int            fr_event_post_delete(fr_event_list_t *el, fr_event_callback_t callback, void *uctx) CC_HINT(nonnull(1,2));
+int            fr_event_post_insert(fr_event_list_t *el, fr_event_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
+int            fr_event_post_delete(fr_event_list_t *el, fr_event_cb_t callback, void *uctx) CC_HINT(nonnull(1,2));
 
 int            fr_event_corral(fr_event_list_t *el, bool wait);
 void           fr_event_service(fr_event_list_t *el);
@@ -139,7 +173,7 @@ void                fr_event_loop_exit(fr_event_list_t *el, int code);
 bool           fr_event_loop_exiting(fr_event_list_t *el);
 int            fr_event_loop(fr_event_list_t *el);
 
-fr_event_list_t        *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_t status, void *status_ctx);
+fr_event_list_t        *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_ctx);
 
 #ifdef __cplusplus
 }
index 6164fb28d38c65cdbd9def8998f41f491430d8be..d99cc5a6be8a5a366a595ad16e165cd5622e0e48 100644 (file)
@@ -524,7 +524,6 @@ static void fr_network_write(UNUSED fr_event_list_t *el, UNUSED int sockfd, UNUS
        if (fr_event_fd_insert(nr, nr->el, s->fd,
                               fr_network_read,
                               NULL,
-                              NULL,
                               listen->app_io->error ? fr_network_error : NULL,
                               s) < 0) {
                ERROR("Failed adding new socket to event loop: %s", fr_strerror());
@@ -612,7 +611,6 @@ static void fr_network_socket_callback(void *ctx, void const *data, size_t data_
        if (fr_event_fd_insert(nr, nr->el, s->fd,
                               fr_network_read,
                               NULL,
-                              NULL,
                               app_io->error ? fr_network_error : NULL,
                               s) < 0) {
                ERROR("Failed adding new socket to event loop: %s", fr_strerror());
@@ -637,6 +635,7 @@ static void fr_network_directory_callback(void *ctx, void const *data, size_t da
        fr_network_t            *nr = ctx;
        fr_network_socket_t     *s;
        fr_app_io_t const       *app_io;
+       fr_event_vnode_func_t   funcs = { .extend = fr_network_vnode };
 
        rad_assert(data_size == sizeof(*s));
 
@@ -670,12 +669,10 @@ static void fr_network_directory_callback(void *ctx, void const *data, size_t da
        rad_assert(app_io->fd);
        s->fd = app_io->fd(s->listen->app_io_instance);
 
-       if (fr_event_fd_insert(nr, nr->el, s->fd,
-                              NULL,
-                              NULL,
-                              fr_network_vnode,
-                              app_io->error ? fr_network_error : NULL,
-                              s) < 0) {
+       if (fr_event_filter_insert(nr, nr->el, s->fd, FR_EVENT_FILTER_VNODE,
+                                  &funcs,
+                                  app_io->error ? fr_network_error : NULL,
+                                  s) < 0) {
                ERROR("Failed adding new socket to event loop: %s", fr_strerror());
                talloc_free(s);
                return;
@@ -990,7 +987,6 @@ static void fr_network_post_event(UNUSED fr_event_list_t *el, UNUSED struct time
                                if (fr_event_fd_insert(nr, nr->el, s->fd,
                                                       fr_network_read,
                                                       fr_network_write,
-                                                      NULL,
                                                       listen->app_io->error ? fr_network_error : NULL,
                                                       s) < 0) {
                                        ERROR("Failed adding write callback to event loop: %s", fr_strerror());
index ce3f65ad037216813f6cfed1de26c96e8a71b673..b4df292b65a47382cd24710121f83af665fedb98 100644 (file)
@@ -161,7 +161,6 @@ static void _ldap_bind_io_write(fr_event_list_t *el, int fd, UNUSED int flags, v
                ret = fr_event_fd_insert(bind_ctx, el, fd,
                                         NULL,
                                         _ldap_bind_io_write,   /* We'll be called again when the conn is open */
-                                        NULL,
                                         _ldap_bind_io_error,
                                         bind_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -171,7 +170,6 @@ static void _ldap_bind_io_write(fr_event_list_t *el, int fd, UNUSED int flags, v
                ret = fr_event_fd_insert(bind_ctx, el, fd,
                                         _ldap_bind_io_read,
                                         NULL,
-                                        NULL,
                                         _ldap_bind_io_error,
                                         bind_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -225,7 +223,6 @@ int fr_ldap_bind_async(fr_ldap_connection_t *c,
                ret = fr_event_fd_insert(bind_ctx, el, fd,
                                         NULL,
                                         _ldap_bind_io_write,
-                                        NULL,
                                         _ldap_bind_io_error,
                                         bind_ctx);
                if (!rad_cond_assert(ret == 0)) {
index 4612afdcb0ccef1dcef49ef0bd5502473d2ab1f7..ccebbfa6986f74c8ec3ef4aecc1f9b70c90fb39c 100644 (file)
@@ -161,11 +161,10 @@ static void _ldap_sasl_bind_io_read(fr_event_list_t *el, int fd, UNUSED int flag
                DEBUG3("Continuing SASL mech %s...", sasl_ctx->rmech);
 
                ret = fr_event_fd_insert(sasl_ctx, el, fd,
-                                       NULL,
-                                       _ldap_sasl_bind_io_write,       /* Need to write more SASL stuff */
                                         NULL,
-                                       _ldap_sasl_bind_io_error,
-                                       sasl_ctx);
+                                        _ldap_sasl_bind_io_write,      /* Need to write more SASL stuff */
+                                        _ldap_sasl_bind_io_error,
+                                        sasl_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
        }
                return;
@@ -234,7 +233,6 @@ static void _ldap_sasl_bind_io_write(fr_event_list_t *el, int fd, UNUSED int fla
                ret = fr_event_fd_insert(sasl_ctx, el, fd,
                                         NULL,
                                         _ldap_sasl_bind_io_write,      /* We'll be called again when the conn is open */
-                                        NULL,
                                         _ldap_sasl_bind_io_error,
                                         sasl_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -247,7 +245,6 @@ static void _ldap_sasl_bind_io_write(fr_event_list_t *el, int fd, UNUSED int fla
                ret = fr_event_fd_insert(sasl_ctx, el, fd,
                                         _ldap_sasl_bind_io_read,
                                         NULL,
-                                        NULL,
                                         _ldap_sasl_bind_io_error,
                                         sasl_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -327,7 +324,6 @@ int fr_ldap_sasl_bind_async(fr_ldap_connection_t *c,
                ret = fr_event_fd_insert(sasl_ctx, el, fd,
                                         NULL,
                                         _ldap_sasl_bind_io_write,
-                                        NULL,
                                         _ldap_sasl_bind_io_error,
                                         sasl_ctx);
                if (!rad_cond_assert(ret == 0)) {
index 64ac3a31bb360d90129e9dfca22c1bde88ae0c1d..b8eef16b15870ec2ad2c4d60b96a5d0570555989 100644 (file)
@@ -183,7 +183,6 @@ static void _ldap_start_tls_io_write(fr_event_list_t *el, int fd, UNUSED int fla
                ret = fr_event_fd_insert(tls_ctx, el, fd,
                                         NULL,
                                         _ldap_start_tls_io_write,      /* We'll be called again when the conn is open */
-                                        NULL,
                                         _ldap_start_tls_io_error,
                                         tls_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -193,7 +192,6 @@ static void _ldap_start_tls_io_write(fr_event_list_t *el, int fd, UNUSED int fla
                ret = fr_event_fd_insert(tls_ctx, el, fd,
                                         _ldap_start_tls_io_read,
                                         NULL,
-                                        NULL,
                                         _ldap_start_tls_io_error,
                                         tls_ctx);
                if (!rad_cond_assert(ret == 0)) goto error;
@@ -238,7 +236,6 @@ int fr_ldap_start_tls_async(fr_ldap_connection_t *c, LDAPControl **serverctrls,
                ret = fr_event_fd_insert(tls_ctx, el, fd,
                                         NULL,
                                         _ldap_start_tls_io_write,
-                                        NULL,
                                         _ldap_start_tls_io_error,
                                         tls_ctx);
                if (!rad_cond_assert(ret == 0)) {
index 53460bbf26122aaacb506578eb53bdf80e1b737e..be987291610f9020dadb7dccde5a8b9c38fff9f3 100644 (file)
@@ -47,7 +47,7 @@ RCSID("$Id$")
  */
 struct fr_event_timer {
        struct timeval          when;                   //!< When this timer should fire.
-       fr_event_callback_t     callback;               //!< Callback to execute when the timer fires.
+       fr_event_cb_t   callback;               //!< Callback to execute when the timer fires.
        void const              *uctx;                  //!< Context pointer to pass to the callback.
        TALLOC_CTX              *linked_ctx;            //!< talloc ctx this event was bound to.
 
@@ -55,23 +55,151 @@ struct fr_event_timer {
        int                     heap;                   //!< Where to store opaque heap data.
 };
 
-/** A file descriptor event
+typedef enum {
+       FR_EVENT_FD_SOCKET      = 1,                    //!< is a socket.
+       FR_EVENT_FD_FILE        = 2,                    //!< is a file.
+       FR_EVENT_FD_DIRECTORY   = 4,                    //!< is a directory.
+
+#ifdef SO_GET_FILTER
+       FR_EVENT_FD_PCAP        = 8,
+#endif
+} fr_event_fd_type_t;
+
+#ifndef SO_GET_FILTER
+#  define FR_EVENT_FD_PCAP     0
+#endif
+
+typedef struct {
+       size_t                  offset;                 //!< Offset of function pointer in structure.
+       char const              *name;                  //!< Name of the event.
+       int16_t                 filter;                 //!< Filter to apply.
+       uint16_t                flags;                  //!< Flags to use for inserting event.
+       uint32_t                fflags;                 //!< fflags to pass to filter.
+       fr_event_fd_type_t      type;                   //!< Type this filter applies to.
+       bool                    coalesce;               //!< Coalesce this map with the next.
+} fr_event_func_map_t;
+
+static fr_event_func_map_t io_func_map[] = {
+       {
+               .offset         = offsetof(fr_event_io_func_t, read),
+               .name           = "read",
+               .filter         = EVFILT_READ,
+               .flags          = EV_ADD | EV_ENABLE,
+               .fflags         = 0,
+               .type           = FR_EVENT_FD_SOCKET | FR_EVENT_FD_FILE | FR_EVENT_FD_PCAP
+       },
+       {
+               .offset         = offsetof(fr_event_io_func_t, write),
+               .name           = "write",
+               .filter         = EVFILT_WRITE,
+               .flags          = EV_ADD | EV_ENABLE,
+               .fflags         = 0,
+               .type           = FR_EVENT_FD_SOCKET | FR_EVENT_FD_FILE | FR_EVENT_FD_PCAP
+       },
+       { 0 }
+};
+
+static fr_event_func_map_t vnode_func_map[] = {
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, delete),
+               .name           = "delete",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_DELETE,
+               .type           = FR_EVENT_FD_FILE | FR_EVENT_FD_DIRECTORY,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, write),
+               .name           = "write",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_WRITE,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, extend),
+               .name           = "extend",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_EXTEND,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, attrib),
+               .name           = "attrib",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_ATTRIB,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, link),
+               .name           = "link",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_LINK,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, rename),
+               .name           = "rename",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_RENAME,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, revoke),
+               .name           = "revoke",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_REVOKE,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       {
+               .offset         = offsetof(fr_event_vnode_func_t, funlock),
+               .name           = "funlock",
+               .filter         = EVFILT_VNODE,
+               .flags          = EV_ADD | EV_ENABLE | EV_CLEAR,
+               .fflags         = NOTE_FUNLOCK,
+               .type           = FR_EVENT_FD_FILE,
+               .coalesce       = true
+       },
+       { 0 }
+};
+
+static FR_NAME_NUMBER const fr_event_fd_type_table[] = {
+       { "socket",             FR_EVENT_FD_SOCKET },
+       { "file",               FR_EVENT_FD_FILE },
+       { "directory",          FR_EVENT_FD_DIRECTORY },
+       { "pcap",               FR_EVENT_FD_PCAP },
+       { NULL,                 -1 },
+};
+
+/** A file descriptor/filter event
  *
  */
 struct fr_event_fd {
+       fr_event_filter_t       filter;
        int                     fd;                     //!< File descriptor we're listening for events on.
 
+       fr_event_fd_type_t      type;                   //!< Type of events we're interested in.
+
        int                     sock_type;              //!< The type of socket SOCK_STREAM, SOCK_RAW etc...
-       bool                    is_file;                //!< Is a file, not a socket.
 
-#ifdef SO_GET_FILTER
-       bool                    pf_attached;            //!< Has an attached packet filter (PF) program.
-#endif
+       union {
+               fr_event_io_func_t      io;
+               fr_event_vnode_func_t   vnode;
+       } funcs;
 
-       fr_event_fd_io_t        read;                   //!< Callback for when data is available.
-       fr_event_fd_io_t        write;                  //!< Callback for when we can write data.
-       fr_event_fd_io_t        vnode;                  //!< Callback for when we get EVFILT_VNODE
-       fr_event_fd_error_t     error;                  //!< Callback for when an error occurs on the FD.
+       fr_event_error_cb_t     error;                  //!< Callback for when an error occurs on the FD.
 
        bool                    is_registered;          //!< Whether this fr_event_fd_t's FD has been registered with
                                                        ///< kevent.  Mostly for debugging.
@@ -88,12 +216,11 @@ struct fr_event_fd {
        fr_event_fd_t           *next;                  //!< item in a list of fr_event_fd.
 };
 
-
 struct fr_event_pid {
        pid_t                   pid;                    //!< child to wait for
        fr_event_list_t         *el;                    //!< the event list which this thing is in
 
-       fr_event_pid_callback_t callback;               //!< callback to run when the child exits
+       fr_event_pid_cb_t       callback;               //!< callback to run when the child exits
        void                    *uctx;                  //!< Context pointer to pass to each file descriptor callback.
 };
 
@@ -102,7 +229,7 @@ struct fr_event_pid {
  */
 typedef struct {
        fr_dlist_t              entry;                  //!< Linked list of callback.
-       fr_event_status_t       callback;               //!< The callback to call.
+       fr_event_status_cb_t    callback;               //!< The callback to call.
        void                    *uctx;                  //!< Context for the callback.
 } fr_event_pre_t;
 
@@ -111,7 +238,7 @@ typedef struct {
  */
 typedef struct {
        fr_dlist_t              entry;                  //!< Linked list of callback.
-       fr_event_callback_t     callback;               //!< The callback to call.
+       fr_event_cb_t   callback;               //!< The callback to call.
        void                    *uctx;                  //!< Context for the callback.
 } fr_event_post_t;
 
@@ -179,7 +306,11 @@ static int fr_event_timer_cmp(void const *a, void const *b)
  */
 static int fr_event_fd_cmp(void const *a, void const *b)
 {
-       fr_event_fd_t const *ev_a = a, *ev_b = b;
+       fr_event_fd_t const     *ev_a = a, *ev_b = b;
+       int                     ret;
+
+       ret = (ev_a->filter > ev_b->filter) - (ev_b->filter < ev_b->filter);
+       if (ret != 0) return ret;
 
        return (ev_a->fd < ev_b->fd) - (ev_a->fd > ev_b->fd);
 }
@@ -245,6 +376,144 @@ int fr_event_list_time(struct timeval *when, fr_event_list_t *el)
        return 1;
 }
 
+/** Build a new evset based on function pointers present
+ *
+ * @param[out] where   to write the evset.
+ * @param[in] outlen   length of output buffer.
+ * @param[in] ef       event to insert.
+ * @param[in] map      of function pointer offsets to filters and filter flags.
+ * @param[in] funcs    to map to events.
+ * @return
+ *     - >= 0 the number of changes written to out.
+ *     - < 0 an error ocurred.
+ */
+static ssize_t fr_event_build_evset(struct kevent out[], size_t outlen,
+                                   fr_event_fd_t *ef, fr_event_func_map_t const map[],
+                                   void const *prev_funcs, void const *curr_funcs)
+{
+       struct kevent                   *out_p = out, *end = out_p + outlen;
+       fr_event_func_map_t const       *map_p;
+
+       /*
+        *      Iterate over the function map, setting/unsetting
+        *      filters and filter flags.
+        */
+       for (map_p = map; map_p->name; map_p++) {
+               bool            c_func = false;
+               bool            p_func = false;
+               uint32_t        c_fflags = 0;
+               uint32_t        p_fflags = 0;
+
+               do {
+                       if (*(uintptr_t const *)((uint8_t const *)curr_funcs + map_p->offset)) {
+                               c_fflags |= map_p->fflags;
+                               c_func = true;
+
+                               /*
+                                *      Check the filter will work for the
+                                *      type of file descriptor specified.
+                                */
+                               if (!(map_p->type & ef->type)) {
+                                       fr_strerror_printf("kevent %s, can't be applied to fd of type",
+                                                          map_p->name,
+                                                          fr_int2str(fr_event_fd_type_table,
+                                                                     map->type, "<INVALID>"));
+                                       return -1;
+                               }
+                       }
+
+                       if (*(uintptr_t const *)((uint8_t const *)prev_funcs + map_p->offset)) {
+                               p_fflags |= map_p->fflags;
+                               p_func = true;
+                       }
+
+                       if (!(map_p + 1)->coalesce) break;
+                       map_p++;
+               } while (1);
+
+               if (out_p > end) {
+                       fr_strerror_printf("Out of memory to store kevent filters");
+                       return -1;
+               }
+
+               /*
+                *      Upsert
+                */
+               if ((c_func && !p_func) || (c_func && p_func && (c_fflags != p_fflags))) {
+                       EV_SET(out_p++, ef->fd, map_p->filter, map_p->flags, c_fflags, 0, ef);
+               /*
+                *      Delete
+                */
+               } else if (!c_func && p_func) {
+                       EV_SET(out_p++, ef->fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
+               }
+       }
+
+       return out_p - out;
+}
+
+/** Discover the type of a file descriptor
+ *
+ * This function writes the result of the discovery to the ef->type,
+ * and ef->sock_type fields.
+ *
+ * @param[out] ef      to write type data to.
+ * @param[in] fd       to discover the type of.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+static int fr_event_fd_type_set(fr_event_fd_t *ef, int fd)
+{
+       int             sock_type;
+       socklen_t       opt_len = sizeof(sock_type);
+
+       /*
+        *      It's a socket or PCAP socket
+        */
+       if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) == 0) {
+#ifdef SO_GET_FILTER
+               opt_len = 0;
+               if (unlikely(getsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, NULL, &opt_len) < 0)) {
+                       fr_strerror_printf("Failed determining PF status: %s", fr_syserror(errno));
+                       return -1;
+               }
+               if (opt_len) {
+                       ef->type = FR_EVENT_FD_PCAP;
+               } else
+#endif
+               {
+                       ef->sock_type = sock_type;
+                       ef->type = FR_EVENT_FD_SOCKET;
+               }
+
+       /*
+        *      It's a file or directory
+        */
+       } else {
+               struct stat buf;
+
+               if (errno != ENOTSOCK) {
+                       fr_strerror_printf("Failed retrieving socket type: %s", fr_syserror(errno));
+                       return -1;
+               }
+
+               if (fstat(fd, &buf) < 0) {
+                       fr_strerror_printf("Failed calling stat() on file: %s", fr_syserror(errno));
+                       return -1;
+               }
+
+               if (S_ISDIR(buf.st_mode)) {
+                       ef->type = FR_EVENT_FD_DIRECTORY;
+               } else {
+                       ef->type = FR_EVENT_FD_FILE;
+               }
+       }
+       ef->fd = fd;
+
+       return 0;
+}
+
 /** Remove a file descriptor from the event loop and rbtree but don't free it
  *
  * This is used as the talloc destructor for events, and also called by
@@ -257,7 +526,7 @@ int fr_event_list_time(struct timeval *when, fr_event_list_t *el)
  */
 static int fr_event_fd_delete_internal(fr_event_fd_t *ef)
 {
-       struct kevent   evset[3];
+       struct kevent   evset[10];
        int             count = 0;
        fr_event_list_t *el;
 
@@ -265,9 +534,37 @@ static int fr_event_fd_delete_internal(fr_event_fd_t *ef)
 
        el = talloc_parent(ef);
 
-       if (ef->read) EV_SET(&evset[count++], ef->fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
-       if (ef->write) EV_SET(&evset[count++], ef->fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
-       if (ef->vnode) EV_SET(&evset[count++], ef->fd, EVFILT_VNODE, EV_DELETE, 0, 0, 0);
+       switch (ef->filter) {
+       /*
+        *      Build the filters for normal I/O events
+        */
+       case FR_EVENT_FILTER_IO:
+       {
+               fr_event_io_func_t funcs = { NULL };
+
+               count = fr_event_build_evset(evset, sizeof(evset)/sizeof(*evset), ef,
+                                            io_func_map, &ef->funcs.io, &funcs);
+               if (count < 0) return -1;
+       }
+               break;
+
+       /*
+        *      Build the filters for vnode events
+        */
+       case FR_EVENT_FILTER_VNODE:
+       {
+               fr_event_vnode_func_t funcs = { NULL };
+
+               count = fr_event_build_evset(evset, sizeof(evset)/sizeof(*evset), ef,
+                                            vnode_func_map, &ef->funcs.vnode, &funcs);
+               if (count < 0) return -1;
+
+
+       }
+
+       default:
+               break;
+       }
 
        if (unlikely(kevent(el->kq, evset, count, NULL, 0, NULL) < 0)) {
                fr_strerror_printf("Failed removing filters for FD %i: %s", ef->fd, fr_syserror(errno));
@@ -325,41 +622,30 @@ int fr_event_fd_delete(fr_event_list_t *el, int fd)
        return 0;
 }
 
-/** Associate a callback with an file descriptor
+/** Insert a filter for the specified fd
  *
  * @param[in] ctx      to bind lifetime of the event to.
  * @param[in] el       to insert fd callback into.
- * @param[in] fd       to read from.
- * @param[in] read_fn  function to call when fd is readable.
- * @param[in] write_fn function to call when fd is writable.
- * @param[in] vnode_fn function to call when the underlying file is extended.
+ * @param[in] fd       to install filters for.
+ * @param[in] filter   one of the #fr_event_filter_t values.
  * @param[in] error    function to call when an error occurs on the fd.
  * @param[in] uctx     to pass to handler.
- * @return
- *     - 0 on succes.
- *     - -1 on failure.
  */
-int fr_event_fd_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
-                      fr_event_fd_io_t read_fn,
-                      fr_event_fd_io_t write_fn,
-                      fr_event_fd_io_t vnode_fn,
-                      fr_event_fd_error_t error,
-                      void *uctx)
+int fr_event_filter_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
+                          fr_event_filter_t filter,
+                          void *funcs, fr_event_error_cb_t error,
+                          void *uctx)
 {
-       int             count = 0;
-       struct kevent   evset[3];
-       fr_event_fd_t   *ef, find;
+       bool            is_new = false;
+       ssize_t         count;
+       fr_event_fd_t   find, *ef;
+       struct kevent   evset[10];
 
        if (unlikely(!el)) {
                fr_strerror_printf("Invalid argument: NULL event list");
                return -1;
        }
 
-       if (unlikely(!read_fn && !write_fn && !vnode_fn)) {
-               fr_strerror_printf("Invalid arguments: All callbacks are NULL");
-               return -1;
-       }
-
        if (unlikely(fd < 0)) {
                fr_strerror_printf("Invalid arguments: Bad FD %i", fd);
                return -1;
@@ -390,109 +676,61 @@ int fr_event_fd_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
 
        /*
         *      No pre-existing event.  Allocate an entry
-        *      for insertion into the rbtree, and call
-        *      kevent to register read/write callbacks.
+        *      for insertion into the rbtree.
         */
        if (!ef) {
-               int             sock_type;
-               socklen_t       opt_len = sizeof(sock_type);
-
                ef = talloc_zero(el, fr_event_fd_t);
                if (unlikely(!ef)) {
                        fr_strerror_printf("Out of memory");
                        return -1;
                }
                talloc_set_destructor(ef, fr_event_fd_delete_internal);
+               ef->linked_ctx = ctx;
 
-               el->num_fds++;
-
-               ef->fd = fd;
-
-                /*
-                 *      Retrieve file descriptor metadata
-                 */
-                if (unlikely(getsockopt(fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0)) {
-                        if (errno != ENOTSOCK) {
-                                fr_strerror_printf("Failed retrieving socket type: %s", fr_syserror(errno));
-                                return -1;
-                        }
-                        ef->is_file = true;
-                }
-#ifdef SO_GET_FILTER
-                else {
-                        opt_len = 0;
-                        if (unlikely(getsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, NULL, &opt_len) < 0)) {
-                                fr_strerror_printf("Failed determining PF status: %s", fr_syserror(errno));
-                                return -1;
-                        }
-                        if (opt_len) ef->pf_attached = true;
-                        ef->sock_type = sock_type;
-                }
-#endif
-
-               if (read_fn) EV_SET(&evset[count++], fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, ef);
-               if (write_fn) EV_SET(&evset[count++], fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, ef);
-               if (vnode_fn) {
-                       struct stat buf;
-
-                       /*
-                        *      Sanity checks. If we care later, we
-                        *      can listen on all NOTE_* for FDs which
-                        *      are just files.
-                        */
-                       if (fstat(fd, &buf) < 0) {
-                               fr_strerror_printf("Failed calling stat() on file");
-                               talloc_free(ef);
-                               return -1;
-                       }
-
-                       if (!S_ISDIR(buf.st_mode)) {
-                               fr_strerror_printf("Added vnode handler on non-directory");
-                               talloc_free(ef);
-                               return -1;
-                       }
-
-                       EV_SET(&evset[count++], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_EXTEND, 0, ef);
-               }
-
-               if (unlikely(kevent(el->kq, evset, count, NULL, 0, NULL) < 0)) {
-                       fr_strerror_printf("Failed adding filter for FD %i: %s", fd, fr_syserror(errno));
+               /*
+                *      Determine what type of file descriptor
+                *      this is.
+                */
+               if (fr_event_fd_type_set(ef, fd) < 0) {
                        talloc_free(ef);
                        return -1;
                }
 
-               rbtree_insert(el->fds, ef);
-
-               ef->uctx = uctx;
-               ef->read = read_fn;
-               ef->write = write_fn;
-               ef->error = error;
-               ef->is_registered = true;
-               ef->linked_ctx = ctx;
-
-               return 0;
+               is_new = true;
        }
 
+       switch (filter) {
        /*
-        *      Calculate the diff between the filters that
-        *      should be registered and the filters we need.
+        *      Build the filters for normal I/O events
         */
-       if (ef->read) {
-               if (!read_fn) EV_SET(&evset[count++], ef->fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
-       } else {
-               if (read_fn) EV_SET(&evset[count++], ef->fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, ef);
-       }
-       if (ef->write) {
-               if (!write_fn) EV_SET(&evset[count++], ef->fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
-       } else {
-               if (write_fn) EV_SET(&evset[count++], ef->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, ef);
-       }
-       if (ef->vnode) {
-               if (!vnode_fn) EV_SET(&evset[count++], ef->fd, EVFILT_VNODE, EV_DELETE, 0, 0, 0);
-       } else {
-               if (vnode_fn) EV_SET(&evset[count++], ef->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_EXTEND, 0, ef);
+       case FR_EVENT_FILTER_IO:
+               count = fr_event_build_evset(evset, sizeof(evset)/sizeof(*evset), ef,
+                                            io_func_map, &ef->funcs.io, funcs);
+               if (count < 0) {
+               error:
+                       if (is_new) talloc_free(ef);
+                       return -1;
+               }
+               memcpy(&ef->funcs.io, funcs, sizeof(ef->funcs.io));
+               break;
+
+       /*
+        *      Build the filters for vnode events
+        */
+       case FR_EVENT_FILTER_VNODE:
+               count = fr_event_build_evset(evset, sizeof(evset)/sizeof(*evset), ef,
+                                            vnode_func_map, &ef->funcs.vnode, funcs);
+               if (count < 0) goto error;
+               memcpy(&ef->funcs.vnode, funcs, sizeof(ef->funcs.vnode));
+
+       default:
+               fr_strerror_printf("Filter %i not supported", fd, filter);
+               goto error;
        }
 
+       /*
+        *      We won't necessarily have changes
+        */
        if (count) {
                if (unlikely(kevent(el->kq, evset, count, NULL, 0, NULL) < 0)) {
                        fr_strerror_printf("Failed modifying filters for FD %i: %s", fd, fr_syserror(errno));
@@ -500,15 +738,51 @@ int fr_event_fd_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
                }
        }
 
+       ef->error = error;
        ef->deferred_free = false;
        ef->uctx = uctx;
-       ef->read = read_fn;
-       ef->write = write_fn;
-       ef->error = error;
+
+       /*
+        *      Register the fd in the tree of fds...
+        */
+       if (is_new) {
+               el->num_fds++;
+               rbtree_insert(el->fds, ef);
+               ef->is_registered = true;
+       }
 
        return 0;
 }
 
+/** Associate I/O callbacks with a file descriptor
+ *
+ * @param[in] ctx      to bind lifetime of the event to.
+ * @param[in] el       to insert fd callback into.
+ * @param[in] fd       to install filters for.
+ * @param[in] read_fn  function to call when fd is readable.
+ * @param[in] write_fn function to call when fd is writable.
+ * @param[in] error    function to call when an error occurs on the fd.
+ * @param[in] uctx     to pass to handler.
+ * @return
+ *     - 0 on succes.
+ *     - -1 on failure.
+ */
+int fr_event_fd_insert(TALLOC_CTX *ctx, fr_event_list_t *el, int fd,
+                      fr_event_fd_cb_t read_fn,
+                      fr_event_fd_cb_t write_fn,
+                      fr_event_error_cb_t error,
+                      void *uctx)
+{
+       fr_event_io_func_t funcs =  { .read = read_fn, .write = write_fn };
+
+       if (unlikely(!read_fn && !write_fn)) {
+               fr_strerror_printf("Invalid arguments: All callbacks are NULL");
+               return -1;
+       }
+
+       return fr_event_filter_insert(ctx, el, fd, FR_EVENT_FILTER_IO, &funcs, error, uctx);
+}
+
 /** Delete a timer event from the event list
  *
  * @param[in] el       to delete event from.
@@ -576,7 +850,7 @@ static int _event_timer_free(fr_event_timer_t *ev)
  *     - -1 on failure.
  */
 int fr_event_timer_insert(TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_timer_t const **ev_p,
-                         struct timeval *when, fr_event_callback_t callback, void const *uctx)
+                         struct timeval *when, fr_event_cb_t callback, void const *uctx)
 {
        fr_event_timer_t *ev;
 
@@ -696,7 +970,7 @@ static int event_pid_free(fr_event_pid_t *ev)
  *     - -1 on failure.
  */
 int fr_event_pid_wait(TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_pid_t const **ev_p,
-                     pid_t pid, fr_event_pid_callback_t wait_fn, void *uctx)
+                     pid_t pid, fr_event_pid_cb_t wait_fn, void *uctx)
 {
        fr_event_pid_t *ev;
        struct kevent evset;
@@ -787,7 +1061,7 @@ int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t callback,
  *     - < 0 on error
  *     - 0 on success
  */
-int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_t callback, void *uctx)
+int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx)
 {
        fr_event_pre_t *pre;
 
@@ -809,7 +1083,7 @@ int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_t callback, void *u
  *     - < 0 on error
  *     - 0 on success
  */
-int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_t callback, void *uctx)
+int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx)
 {
        fr_dlist_t *entry, *next;
 
@@ -844,7 +1118,7 @@ int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_t callback, void *u
  *     - < 0 on error
  *     - 0 on success
  */
-int fr_event_post_insert(fr_event_list_t *el, fr_event_callback_t callback, void *uctx)
+int fr_event_post_insert(fr_event_list_t *el, fr_event_cb_t callback, void *uctx)
 {
        fr_event_post_t *post;
 
@@ -866,7 +1140,7 @@ int fr_event_post_insert(fr_event_list_t *el, fr_event_callback_t callback, void
  *     - < 0 on error
  *     - 0 on success
  */
-int fr_event_post_delete(fr_event_list_t *el, fr_event_callback_t callback, void *uctx)
+int fr_event_post_delete(fr_event_list_t *el, fr_event_cb_t callback, void *uctx)
 {
        fr_dlist_t *entry, *next;
 
@@ -899,7 +1173,7 @@ int fr_event_post_delete(fr_event_list_t *el, fr_event_callback_t callback, void
  */
 int fr_event_timer_run(fr_event_list_t *el, struct timeval *when)
 {
-       fr_event_callback_t     callback;
+       fr_event_cb_t   callback;
        void                    *uctx;
        fr_event_timer_t        *ev;
 
@@ -1132,7 +1406,7 @@ void fr_event_service(fr_event_list_t *el)
                         *      This is fine, the callback will get notified
                         *      via the flags field.
                         */
-                       if (ef->is_file) goto service;
+                       if (ef->type == FR_EVENT_FD_FILE) goto service;
 #if defined(__linux__) && defined(SO_GET_FILTER)
                        /*
                         *      There seems to be an issue with the
@@ -1147,7 +1421,7 @@ void fr_event_service(fr_event_list_t *el)
                         *      with a packet filter attached, we ignore
                         *      the EOF flag and continue.
                         */
-                       if ((ef->sock_type == SOCK_RAW) && ef->pf_attached) goto service;
+                       if ((ef->sock_type == SOCK_RAW) && (ef->type == FR_EVENT_FD_PCAP)) goto service;
 #endif
                        fd_errno = el->events[i].fflags;
 
@@ -1156,17 +1430,68 @@ void fr_event_service(fr_event_list_t *el)
 
 service:
                ef->in_handler = true;
-               if (ef->read && (el->events[i].filter == EVFILT_READ)) {
-                       ef->read(el, ef->fd, flags, ef->uctx);
-               }
-               if (ef->write && (el->events[i].filter == EVFILT_WRITE) && !ef->deferred_free) {
-                       ef->write(el, ef->fd, flags, ef->uctx);
-               }
-               if (ef->vnode && (el->events[i].filter == EVFILT_VNODE) && !ef->deferred_free) {
+               /*
+                *      If any of these callbacks are NULL, then
+                *      there's a logic error somewhere.
+                *      Filters are only installed if there's a
+                *      callback to handle them.
+                */
+               switch (ef->filter) {
+               case FR_EVENT_FILTER_IO:
                        /*
-                        *      Note fflags, not flags!
+                        *      io.read can delete the event, in which case
+                        *      we *DON'T* want to call the write event.
                         */
-                       ef->vnode(el, ef->fd, el->events[i].fflags, ef->uctx);
+                       if (el->events[i].filter == EVFILT_READ) {
+                               ef->funcs.io.read(el, ef->fd, flags, ef->uctx);
+                       }
+                       if ((el->events[i].filter == EVFILT_WRITE) && !ef->deferred_free) {
+                               ef->funcs.io.write(el, ef->fd, flags, ef->uctx);
+                       }
+                       break;
+
+               case FR_EVENT_FILTER_VNODE:
+                       if (unlikely(!fr_cond_assert(el->events[i].filter == EVFILT_VNODE))) break;
+
+                       switch (el->events[i].fflags) {
+                       case NOTE_DELETE:
+                               ef->funcs.vnode.delete(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_WRITE:
+                               ef->funcs.vnode.write(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_EXTEND:
+                               ef->funcs.vnode.extend(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_ATTRIB:
+                               ef->funcs.vnode.attrib(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_LINK:
+                               ef->funcs.vnode.link(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_RENAME:
+                               ef->funcs.vnode.rename(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_REVOKE:
+                               ef->funcs.vnode.revoke(el, ef->fd, flags, ef->uctx);
+                               break;
+
+                       case NOTE_FUNLOCK:
+                               ef->funcs.vnode.funlock(el, ef->fd, flags, ef->uctx);
+
+                       default:
+                               if (unlikely(!fr_cond_assert(false))) break;
+                       }
+                       break;
+
+               default:
+                       break;
                }
                ef->in_handler = false;
        }
@@ -1298,7 +1623,7 @@ static int _event_list_free(fr_event_list_t *el)
  *     - A pointer to a new event list on success (free with talloc_free).
  *     - NULL on error.
  */
-fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_t status, void *status_uctx)
+fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
 {
        fr_event_list_t *el;
        struct kevent kev;
index 27fe198e57623363191ece9aa73a183d52134b38..a5c6a4132a934f43c7545baae0cc5067b4a319ab 100644 (file)
@@ -310,7 +310,10 @@ static void connection_state_init(fr_connection_t *conn, struct timeval *now)
                         *      assume it's open.
                         */
                        if (fr_event_fd_insert(conn, conn->el, conn->fd,
-                                              NULL, _connection_writable, NULL, _connection_error, conn) < 0) {
+                                              NULL,
+                                              _connection_writable,
+                                              _connection_error,
+                                              conn) < 0) {
                                PERROR("Failed inserting file descriptor (%i) into event loop %p",
                                       conn->fd, conn->el);
                                connection_state_failed(conn, now);
index ee4baa76cea47883205192c15575b7affb34c9be..387f47f70435606507c33e3f284470dfbd2f9a87 100644 (file)
@@ -390,7 +390,11 @@ int radius_event_start(UNUSED bool have_children)
        }
        DEBUG4("Created signal pipe.  Read end FD %i, write end FD %i", self_pipe[0], self_pipe[1]);
 
-       if (fr_event_fd_insert(NULL, event_list, self_pipe[0], event_signal_handler, NULL, NULL, NULL, event_list) < 0) {
+       if (fr_event_fd_insert(NULL, event_list, self_pipe[0],
+                              event_signal_handler,
+                              NULL,
+                              NULL,
+                              event_list) < 0) {
                PERROR("Failed creating signal pipe handler");
                return -1;
        }
index fa880cce23fbab5ffedae65866d38ad2ea20fd14..506d934209a755b6b0d652027b67ea55c9e7afc0 100644 (file)
@@ -2805,7 +2805,11 @@ int main(int argc, char *argv[])
                        exit(EXIT_FAILURE);
                }
 
-               if (fr_event_fd_insert(NULL, events, self_pipe[0], rs_signal_action, NULL, NULL, NULL, events) < 0) {
+               if (fr_event_fd_insert(NULL, events, self_pipe[0],
+                                      rs_signal_action,
+                                      NULL,
+                                      NULL,
+                                      events) < 0) {
                        ERROR("Failed inserting signal pipe descriptor: %s", fr_strerror());
                        goto finish;
                }
@@ -2824,7 +2828,11 @@ int main(int argc, char *argv[])
                        event->out = out;
                        event->stats = stats;
 
-                       if (fr_event_fd_insert(NULL, events, in_p->fd, rs_got_packet, NULL, NULL, NULL, event) < 0) {
+                       if (fr_event_fd_insert(NULL, events, in_p->fd,
+                                              rs_got_packet,
+                                              NULL,
+                                              NULL,
+                                              event) < 0) {
                                ERROR("Failed inserting file descriptor");
                                goto finish;
                        }
index cf24c1b39a3ea1951e38a5367441791dd27cbc76..f31c413050cd54ee11e3d1ad68aa154fc410e319 100644 (file)
@@ -2669,8 +2669,8 @@ int unlang_event_fd_add(REQUEST *request,
        if (fr_event_fd_insert(request, request->el, fd,
                               ev->fd_read ? unlang_event_fd_read_handler : NULL,
                               ev->fd_write ? unlang_event_fd_write_handler : NULL,
-                              NULL,
-                              ev->fd_error ? unlang_event_fd_error_handler: NULL, ev) < 0) {
+                              ev->fd_error ? unlang_event_fd_error_handler: NULL,
+                              ev) < 0) {
                talloc_free(ev);
                return -1;
        }
index 7ac77c1076aa5c86ae3ca883cf9de4518a8c1791..7fadba391ab3b60b454d822a6b1fc202f3fb873f 100644 (file)
@@ -337,7 +337,11 @@ static int bfd_pthread_create(bfd_state_t *session)
        fcntl(session->pipefd[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC);
 #endif
 
-       if (fr_event_fd_insert(session, session->el, session->pipefd[0], bfd_pipe_recv, NULL, NULL, NULL, session) < 0) {
+       if (fr_event_fd_insert(session, session->el, session->pipefd[0],
+                              bfd_pipe_recv,
+                              NULL,
+                              NULL,
+                              session) < 0) {
                PERROR("Failed inserting file descriptor into event list");
                goto close_pipes;
        }
index 0f2db8b1b516fe717a001f27bd5e578a524bd5d9..c7c9ef4ef3513d7ec01eec4bb841f76f519299f5 100644 (file)
@@ -297,7 +297,10 @@ static void logtee_fd_idle(rlm_logtee_thread_t *t)
 {
        DEBUG3("Marking socket (%i) as idle", fr_connection_get_fd(t->conn));
        if (fr_event_fd_insert(t->conn, t->el, fr_connection_get_fd(t->conn),
-                              _logtee_conn_read, NULL, NULL, _logtee_conn_error, t) < 0) {
+                              _logtee_conn_read,
+                              NULL,
+                              _logtee_conn_error,
+                              t) < 0) {
                PERROR("Failed inserting FD event");
        }
 }
@@ -312,7 +315,10 @@ static void logtee_fd_active(rlm_logtee_thread_t *t)
 {
        DEBUG3("Marking socket (%i) as active - Draining requests", fr_connection_get_fd(t->conn));
        if (fr_event_fd_insert(t->conn, t->el, fr_connection_get_fd(t->conn),
-                              _logtee_conn_read, _logtee_conn_writable, NULL, _logtee_conn_error, t) < 0) {
+                              _logtee_conn_read,
+                              _logtee_conn_writable,
+                              _logtee_conn_error,
+                              t) < 0) {
                PERROR("Failed inserting FD event");
        }
 }
index 057163cc9035dc1455f174699d04bc52d940feb5..13f3af1bbdc432377a24bf707ac599cc0dde966f 100644 (file)
@@ -316,7 +316,10 @@ static void fd_idle(rlm_radius_udp_connection_t *c)
        c->pending = false;
        DEBUG3("Marking socket %s as idle", c->name);
        if (fr_event_fd_insert(c->conn, t->el, c->fd,
-                              conn_read, NULL, NULL, conn_error, c) < 0) {
+                              conn_read,
+                              NULL,
+                              conn_error,
+                              c) < 0) {
                PERROR("Failed inserting FD event");
                talloc_free(c);
        }
@@ -344,7 +347,10 @@ static void fd_active(rlm_radius_udp_connection_t *c)
        if (c->idle_ev) (void) fr_event_timer_delete(c->thread->el, &c->idle_ev);
 
        if (fr_event_fd_insert(c->conn, t->el, c->fd,
-                              conn_read, conn_writable, NULL, conn_error, c) < 0) {
+                              conn_read,
+                              conn_writable,
+                              conn_error,
+                              c) < 0) {
                PERROR("Failed inserting FD event");
                talloc_free(c);
        }
index 4c9b616733b45c574dbbff545de14c5b0cf83a6d..b4960d13c5cf269c7e0e707172ddd2740ca62b30 100644 (file)
@@ -379,7 +379,7 @@ void rr_track_use_authenticator(rlm_radius_id_t *id, bool flag)
 }
 
 int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_t *el,
-                  fr_event_callback_t callback, void *uctx, rlm_radius_retry_t *retry,
+                  fr_event_cb_t callback, void *uctx, rlm_radius_retry_t *retry,
                   struct timeval *now)
 {
        uint32_t delay, frac;
@@ -474,7 +474,7 @@ int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_
 
 
 int rr_track_start(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_t *el,
-                  fr_event_callback_t callback, void *uctx, rlm_radius_retry_t *retry)
+                  fr_event_cb_t callback, void *uctx, rlm_radius_retry_t *retry)
 {
        struct timeval next;
 
index a7e186262a0525f34cde54859db92ba4f4e060ca..adc0e52cfc2322234211fb8f25a84b0ae330e6cc 100644 (file)
@@ -70,9 +70,9 @@ int rr_track_delete(rlm_radius_id_t *id, rlm_radius_request_t *rr) CC_HINT(nonnu
 void rr_track_use_authenticator(rlm_radius_id_t *id, bool flag) CC_HINT(nonnull);
 
 int rr_track_start(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_t *el,
-                  fr_event_callback_t callback, void *uctx, rlm_radius_retry_t *retry) CC_HINT(nonnull);
+                  fr_event_cb_t callback, void *uctx, rlm_radius_retry_t *retry) CC_HINT(nonnull);
 int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_t *el,
-                  fr_event_callback_t callback, void *uctx, rlm_radius_retry_t *retry,
+                  fr_event_cb_t callback, void *uctx, rlm_radius_retry_t *retry,
                   struct timeval *no) CC_HINT(nonnull);
 
 #endif /* _RLM_RADIUS_TRACK_H */
index cf9d0722491108107b64f12d9ffdbed080f4b0b1..2b85499f31ec05c0dec30c154781c3c5ce881d41 100644 (file)
@@ -268,7 +268,9 @@ static int _rest_io_event_modify(UNUSED CURL *easy, curl_socket_t fd, int what,
        switch (what) {
        case CURL_POLL_IN:
                if (fr_event_fd_insert(thread, thread->el, fd,
-                                      _rest_io_service_readable, NULL, NULL, _rest_io_service_errored,
+                                      _rest_io_service_readable,
+                                      NULL,
+                                      _rest_io_service_errored,
                                       thread) < 0) {
                        ERROR("multi-handle %p registration failed for read+error events on FD %i: %s",
                              thread->mandle, fd, fr_strerror());
@@ -279,7 +281,9 @@ static int _rest_io_event_modify(UNUSED CURL *easy, curl_socket_t fd, int what,
 
        case CURL_POLL_OUT:
                if (fr_event_fd_insert(thread, thread->el, fd,
-                                      NULL, _rest_io_service_writable, NULL, _rest_io_service_errored,
+                                      NULL,
+                                      _rest_io_service_writable,
+                                      _rest_io_service_errored,
                                       thread) < 0) {
                        ERROR("multi-handle %p registration failed for write+error events on FD %i: %s",
                              thread->mandle, fd, fr_strerror());
@@ -290,7 +294,9 @@ static int _rest_io_event_modify(UNUSED CURL *easy, curl_socket_t fd, int what,
 
        case CURL_POLL_INOUT:
                if (fr_event_fd_insert(thread, thread->el, fd,
-                                      _rest_io_service_readable, _rest_io_service_writable, NULL, _rest_io_service_errored,
+                                      _rest_io_service_readable,
+                                      _rest_io_service_writable,
+                                      _rest_io_service_errored,
                                       thread) < 0) {
                        ERROR("multi-handle %p registration failed for read+write+error events on FD %i: %s",
                              thread->mandle, fd, fr_strerror());
index fdbf36617de7340b80a8b9a2fc9798fb8cc7f732..7a413053d387bb89f00318063ef31b473e01a23d 100644 (file)
@@ -641,7 +641,11 @@ static int mod_instantiate(void *instance, CONF_SECTION *conf)
 
        inst->log_fd = ub_fd(inst->ub);
        if (inst->log_fd >= 0) {
-               if (fr_event_fd_insert(inst, inst->el, inst->log_fd, ub_fd_handler, NULL, NULL, NULL, inst) < 0) {
+               if (fr_event_fd_insert(inst, inst->el, inst->log_fd,
+                                      ub_fd_handler,
+                                      NULL,
+                                      NULL,
+                                      inst) < 0) {
                        cf_log_err(conf, "could not insert async fd");
                        inst->log_fd = -1;
                        goto error_nores;