]> jfr.im git - irc/UndernetIRC/iauthd-c.git/commitdiff
Convert to libevent2 APIs
authorMichael Poole <redacted>
Sat, 6 Mar 2021 17:40:32 +0000 (12:40 -0500)
committerMichael Poole <redacted>
Sat, 6 Mar 2021 17:40:32 +0000 (12:40 -0500)
configure.ac
modules/iauth.h
modules/iauth_core.c
src/common.h
src/main.c
src/sar.c

index 4c28f154268965a5da61ef1f63102770844f375a..6825b08fb5fe35e486c935ee4bfbc2400b029788 100644 (file)
@@ -58,7 +58,7 @@ dnl Check libraries.
 AC_CHECK_LIB(dl, dlopen)
 AC_CHECK_LIB(socket, socket)
 AC_CHECK_LIB(event, event_dispatch,, AC_MSG_ERROR(
-[libevent or libevent2 must be installed to build iauthd-c.]))
+  [libevent2 must be installed to build iauthd-c.]))
 AC_CHECK_TYPE(evutil_socket_t,
   AC_DEFINE(HAVE_EVUTIL_SOCKET_T, 1, [Define if <evutil.h> defines evutil_socket_t]),, [#include <evutil.h>])
 
index 1deb32aa338b0ba076657b35d6ea7f475907f39e..7973de6f51ab880d73fc53564a8d6ef0b9f34ab9 100644 (file)
@@ -153,17 +153,17 @@ struct iauth_request {
      */
     int holds;
 
-    /** Timer event that fires when the IAuth request has been active
-     * for too long.
-     */
-    struct event timeout;
-
     /** Number of "soft holds" on the client.  IAuth will send a "Soft
      * Done" message when the number of holds less than one but this
      * is positive.
      */
     int soft_holds;
 
+    /** Timer event that fires when the IAuth request has been active
+     * for too long.
+     */
+    struct event *timeout;
+
     /** Boolean flags of which events have occurred for the client.
      * This includes indications of which fields are set.
      * Indexed by enum iauth_flags.
index 4fee4f6891c4d1b88211b17bd99aeedbdb2a02e9..fdc47047c8a4a2fcaedf9d2e4aebb0389c32601c 100644 (file)
@@ -33,8 +33,11 @@ static struct set *iauth_reqs;
 /** Set of all registered IAuth modules. */
 static struct set *iauth_modules;
 
-/** Event descriptor for input data. */
-static struct bufferevent *iauth_in;
+/** Input event object for IAuth. */
+static struct event *iauth_ev;
+
+/** Buffer object for input data. */
+static struct evbuffer *iauth_in;
 
 /** Bitset containing all requested policies. */
 static struct iauth_policyset iauth_policies;
@@ -428,7 +431,7 @@ void iauth_soft_done(struct iauth_request *req)
 static void iauth_req_cleanup(void *ptr)
 {
     struct iauth_request *req = ptr;
-    event_del(&req->timeout);
+    event_free(req->timeout);
     stats.n_req_data_frees += set_size(&req->data);
     set_clear(&req->data, 0);
 }
@@ -505,9 +508,9 @@ static void parse_new_client(int id, int argc, char *argv[])
     /* Do we have a timeout? */
     timeout.tv_sec = iauth_conf_timeout->parsed.p_interval;
     timeout.tv_usec = 0;
-    evtimer_set(&req->timeout, iauth_timeout, req);
+    req->timeout = evtimer_new(ev_base, iauth_timeout, req);
     if (timeout.tv_sec > 0)
-        evtimer_add(&req->timeout, &timeout);
+        evtimer_add(req->timeout, &timeout);
 
     /* Broadcast the message. */
     for (node = set_first(iauth_modules); node; node = set_next(node)) {
@@ -772,23 +775,33 @@ static void parse_info_request(int argc, char *argv[])
         log_message(iauth_log, LOG_WARNING, "Unrecognized info request: %s", argv[1]);
 }
 
-static void iauth_read(struct bufferevent *buf, UNUSED_ARG(void *arg))
+static void iauth_read(evutil_socket_t fd, short events, void *iauth_in_v)
 {
     struct iauth_request *req;
     char *argv[16];
     char *line;
     char *sep;
     size_t argc, len;
-    int id;
+    int id, res;
+
+    if (!(events & EV_READ))
+        return;
+
+    /* Read a chunk of data from the FD into our evbuffer. */
+    res = evbuffer_read(iauth_in_v, fd, 4096);
+    if (res < 0) {
+        if (errno != EWOULDBLOCK)
+            log_message(iauth_log, LOG_ERROR, "Unable to read input: %s", strerror(errno));
+        return;
+    }
+    if (res == 0) {
+        log_message(log_core, LOG_INFO, "Terminating due to EOF on input");
+        event_base_loopbreak(ev_base);
+        return;
+    }
 
     /* Parse out the start of the line (simple, standard bits). */
-    while ((line = evbuffer_readline(buf->input)) != NULL)
-    {
-        len = strlen(line);
-        if (len > 0 && line[len-1] == '\r')
-        {
-            line[len-1] = '\0';
-        }
+    while ((line = evbuffer_readln(iauth_in_v, &len, EVBUFFER_EOL_CRLF)) != NULL) {
         log_message(iauth_log, LOG_DEBUG, "> %s", line);
         id = strtol(line, &sep, 10);
 
@@ -818,6 +831,7 @@ static void iauth_read(struct bufferevent *buf, UNUSED_ARG(void *arg))
              * client disconnects.
             log_message(iauth_log, LOG_DEBUG, " .. no client found for id %d", id);
             */
+            free(line);
             return;
         }
 
@@ -872,14 +886,9 @@ static void iauth_read(struct bufferevent *buf, UNUSED_ARG(void *arg))
             parse_info_request(argc, argv);
             break;
         }
-    }
-}
 
-static void iauth_io_error(UNUSED_ARG(struct bufferevent *buf), short events, UNUSED_ARG(void *arg))
-{
-    if (events & EVBUFFER_EOF) {
-        log_message(log_core, LOG_INFO, "Terminating due to EOF on input");
-        event_loopbreak();
+        /* We are responsible for freeing the line. */
+        free(line);
     }
 }
 
@@ -916,14 +925,25 @@ void module_constructor(UNUSED_ARG(const char name[]))
     iauth_modules = set_alloc(set_compare_charp, NULL);
     iauth_conf = conf_register_object(NULL, "iauth");
     iauth_conf_timeout = conf_register_string(iauth_conf, CONF_STRING_INTERVAL, "timeout", "0");
-    event_once(-1, EV_TIMEOUT, iauth_startup, NULL, &tv_zero);
-    iauth_in = bufferevent_new(STDIN_FILENO, iauth_read, NULL, iauth_io_error, NULL);
-    bufferevent_enable(iauth_in, EV_READ);
+
+    event_base_once(ev_base, -1, EV_TIMEOUT, iauth_startup, NULL, &tv_zero);
+    iauth_in = evbuffer_new();
+    if (!iauth_in) {
+        log_message(iauth_log, LOG_FATAL, "Unable to create IAuth evbuffer");
+        return;
+    }
+    iauth_ev = event_new(ev_base, STDIN_FILENO, EV_PERSIST | EV_READ, iauth_read, iauth_in);
+    if (!iauth_ev) {
+        log_message(iauth_log, LOG_FATAL, "Unable to create IAuth event");
+        return;
+    }
+    event_add(iauth_ev, NULL);
 }
 
 void module_destructor(void)
 {
-    bufferevent_free(iauth_in);
+    evbuffer_free(iauth_in);
+    event_free(iauth_ev);
     set_clear(iauth_reqs, 0);
     free(iauth_reqs);
     set_clear(iauth_modules, 1);
index 9d538f42d29fb0856018c06415c272ec8f96562c..b13b10e18ea340ffd16d020625ea50553bb186a4 100644 (file)
 #include "src/compat.h"
 
 /* Include the libevent headers. */
-#include <evdns.h>
-#include <event.h>
+#include <event2/event.h>
+#include <event2/dns.h>
+#include <event2/buffer.h>
+extern struct event_base *ev_base;
+extern struct evdns_base *ev_dns;
 
 /** Evaluates to the length of an array \a x. */
 #define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
index 1b52434ebbebb844e8e432733ba98641db61f80a..b573206ee33d1fa54de0b14f21fd8c158179e670 100644 (file)
@@ -41,14 +41,17 @@ static struct {
 } conf;
 
 static const struct argument args[];
-static struct event sighup_evt;
-static struct event sigusr1_evt;
+static struct event *sighup_evt;
+static struct event *sigusr1_evt;
 static const char *config_filename = SYSCONFDIR "/iauthd-c.conf";
 static const char *iauthd_executable;
 static int verbose_debug;
 static int early_exit;
 static int no_chdir;
 static int restart;
+static int ev_arbitrary_fds;
+struct event_base *ev_base;
+struct evdns_base *ev_dns;
 int clean_exit;
 
 static int do_arg_help(UNUSED_ARG(const char *arg))
@@ -103,6 +106,12 @@ static int do_arg_no_chdir(UNUSED_ARG(const char *arg))
     return 0;
 }
 
+static int do_arg_arbitrary_fds(UNUSED_ARG(const char *arg))
+{
+    ev_arbitrary_fds = 1;
+    return 0;
+}
+
 static const struct argument args[] = {
     { "help", '?', do_arg_help, 0, "Show usage information" },
     { "version", 'v', do_arg_version, 0, "Show software version" },
@@ -110,6 +119,7 @@ static const struct argument args[] = {
     { "config", 'f', do_arg_config, 1, "Use specific configuration file" },
     { "debug", 'd', do_arg_debug, 0, "Enable verbose debug output" },
     { "no-chdir", 'n', do_arg_no_chdir, 0, "Disable chdir(LOGDIR) at startup" },
+    { "arbitrary-fds", 'A', do_arg_arbitrary_fds, 0, "Request libevent support for arbitrary FD types"},
     { NULL, '\0', NULL, 0, NULL }
 };
 
@@ -214,7 +224,7 @@ static void break_loop(UNUSED_ARG(int fd), UNUSED_ARG(short event), UNUSED_ARG(v
 {
     log_message(log_core, LOG_INFO, "break_loop() called due to signal");
     clean_exit = 1;
-    event_loopbreak();
+    event_base_loopbreak(ev_base);
 }
 
 static void reload_config(UNUSED_ARG(int fd), UNUSED_ARG(short event), UNUSED_ARG(void *arg))
@@ -223,8 +233,18 @@ static void reload_config(UNUSED_ARG(int fd), UNUSED_ARG(short event), UNUSED_AR
     conf_read(config_filename);
 }
 
+static void main_cleanup(void)
+{
+    event_free(sigusr1_evt);
+    event_free(sighup_evt);
+    evdns_base_free(ev_dns, 0);
+    event_base_free(ev_base);
+}
+
 int main(int argc, char *argv[])
 {
+    struct event_config *ev_cfg;
+
     iauthd_executable = argv[0];
     atexit(call_exit_funcs);
     parse_arguments(argc, argv);
@@ -244,17 +264,32 @@ int main(int argc, char *argv[])
     conf.modules = conf_register_string_list(conf.root, "modules", NULL);
 
     /* Initialize libevent. */
-    if (!event_init()) {
+    ev_cfg = event_config_new();
+    if (!ev_cfg) {
+        fprintf(stderr, "Allocation of event_config structure failed.\n");
+        return EXIT_FAILURE;
+    }
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    ev_arbitrary_fds = 1;
+#endif
+    if (ev_arbitrary_fds && event_config_require_features(ev_cfg, EV_FEATURE_FDS)) {
+        fprintf(stderr, "libevent rejected EV_FEATURE_FDS.\n");
+        return EXIT_FAILURE;
+    }
+    ev_base = event_base_new_with_config(ev_cfg);
+    event_config_free(ev_cfg);
+    if (!ev_base) {
         fprintf(stderr, "Unable to initialize event library.\n");
         return EXIT_FAILURE;
     }
 
     /* Initialize libevent's DNS module. */
-    if (evdns_init()) {
+    ev_dns = evdns_base_new(ev_base, 0);
+    if (!ev_dns) {
         fprintf(stderr, "Unable to initialize DNS library.\n");
         return EXIT_FAILURE;
     }
-    evdns_search_clear();
+    reg_exit_func(main_cleanup);
 
     /* Capture libevent's error messages to our own log. */
     event_set_log_callback(log_for_libevent);
@@ -281,15 +316,19 @@ int main(int argc, char *argv[])
     log_set_verbosity(verbose_debug ? 2 : 0);
 
     /* Handle signals. */
-    signal_set(&sighup_evt, SIGHUP, break_loop, NULL);
-    if (event_add(&sighup_evt, NULL))
-        log_message(log_core, LOG_FATAL, "Unable to handle SIGHUP handler.");
-    signal_set(&sigusr1_evt, SIGUSR1, reload_config, NULL);
-    if (event_add(&sigusr1_evt, NULL))
-        log_message(log_core, LOG_FATAL, "Unable to handle SIGUSR1 handler.");
+    sighup_evt = event_new(ev_base, SIGHUP, EV_SIGNAL | EV_PERSIST, break_loop, NULL);
+    if (!sighup_evt)
+        log_message(log_core, LOG_FATAL, "Unable to create SIGHUP handler.");
+    if (event_add(sighup_evt, NULL))
+        log_message(log_core, LOG_FATAL, "Unable to add SIGHUP handler.");
+    sigusr1_evt = event_new(ev_base, SIGUSR1, EV_SIGNAL | EV_PERSIST, reload_config, NULL);
+    if (!sigusr1_evt)
+        log_message(log_core, LOG_FATAL, "Unable to create SIGUSR1 handler.");
+    if (event_add(sigusr1_evt, NULL))
+        log_message(log_core, LOG_FATAL, "Unable to add SIGUSR1 handler.");
 
     /* Run the event loop. */
-    event_dispatch();
+    event_base_dispatch(ev_base);
 
     if (restart)
     {
index 619d22507c76a2234abe40f1842f8eaa8c2fc2a2..739037af78a674ac6c1f3ec4e6f7237acf65fb1e 100644 (file)
--- a/src/sar.c
+++ b/src/sar.c
@@ -280,8 +280,8 @@ struct sar_request {
 
 static struct set sar_requests;
 static struct set sar_nameservers;
-static struct event sar_fd;
-static struct event sar_timeout;
+static struct event *sar_fd;
+static struct event *sar_timeout;
 static int sar_fd_fd;
 
 #define TV_LESS(A, B) evutil_timercmp(&(A), &(B), <)
@@ -320,7 +320,7 @@ static void sar_request_fail(struct sar_request *req, unsigned int rcode)
     sar_abort(req);
 }
 
-static void sar_timeout_cb(UNUSED_ARG(int fd), UNUSED_ARG(short event), void *timer)
+static void sar_timeout_cb(UNUSED_ARG(int fd), UNUSED_ARG(short event), UNUSED_ARG(void *datum))
 {
     struct set_node *it;
     struct set_node *next;
@@ -345,19 +345,21 @@ static void sar_timeout_cb(UNUSED_ARG(int fd), UNUSED_ARG(short event), void *ti
             sar_request_send(req);
     }
     if (next_timeout.tv_sec < INT_MAX)
-        evtimer_add(timer, &next_timeout);
+        evtimer_add(sar_timeout, &next_timeout);
 }
 
 static void sar_check_timeout(struct timeval when)
 {
-    if (!evutil_timerisset(&sar_timeout.ev_timeout))
+    struct timeval previous;
+
+    if (!evtimer_pending(sar_timeout, &previous))
     {
-        evtimer_add(&sar_timeout, &when);
+        evtimer_add(sar_timeout, &when);
     }
-    else if (TV_LESS(when, sar_timeout.ev_timeout))
+    else if (TV_LESS(when, previous))
     {
-        evtimer_del(&sar_timeout);
-        evtimer_add(&sar_timeout, &when);
+        evtimer_del(sar_timeout);
+        evtimer_add(sar_timeout, &when);
     }
     /* else existing timeout is sooner */
 }
@@ -642,7 +644,7 @@ static const unsigned char *sar_extract_rdata(struct dns_rr *rr, unsigned int le
     return raw + rr->rd_start;
 }
 
-static void sar_fd_cb(int fd, short event, void *arg)
+static void sar_fd_cb(int fd, short event, UNUSED_ARG(void *arg))
 {
     struct sockaddr_storage ss;
     struct dns_header hdr;
@@ -653,7 +655,6 @@ static void sar_fd_cb(int fd, short event, void *arg)
     int id, res, rcode, buf_len;
 
     assert(fd == sar_fd_fd);
-    assert(arg == &sar_fd);
     if (event != EV_READ)
         return;
     buf_len = conf.sar_edns0->parsed.p_integer;
@@ -673,7 +674,7 @@ static void sar_fd_cb(int fd, short event, void *arg)
 
     id = hdr.id;
     req = set_find(&sar_requests, &id);
-    log_message(sar_log, LOG_DEBUG, "sar_fd_cb(%d, EV_READ, %p): hdr {id=%d, flags=0x%x, qdcount=%d, ancount=%d, nscount=%d, arcount=%d} -> req %p", fd, arg, hdr.id, hdr.flags, hdr.qdcount, hdr.ancount, hdr.nscount, hdr.arcount, req);
+    log_message(sar_log, LOG_DEBUG, "sar_fd_cb(%d, EV_READ): hdr {id=%d, flags=0x%x, qdcount=%d, ancount=%d, nscount=%d, arcount=%d} -> req %p", fd, hdr.id, hdr.flags, hdr.qdcount, hdr.ancount, hdr.nscount, hdr.arcount, req);
     if (!req || !req->retries || !(hdr.flags & REQ_FLAG_QR)) {
         ns->resp_ignored++;
         return;
@@ -764,8 +765,8 @@ static int sar_open_fd(void)
         }
     }
 
-    event_set(&sar_fd, sar_fd_fd, EV_READ, sar_fd_cb, &sar_fd);
-    if (event_add(&sar_fd, NULL)) {
+    sar_fd = event_new(ev_base, sar_fd_fd, EV_READ | EV_PERSIST, sar_fd_cb, NULL);
+    if (event_add(sar_fd, NULL)) {
         log_message(sar_log, LOG_FATAL, "Unable to register resolver socket with event loop.");
         return 1;
     }
@@ -886,7 +887,7 @@ static void sar_request_send(struct sar_request *req)
     struct set_node *it;
 
     /* make sure we have our local socket */
-    if (!event_initialized(&sar_fd) && sar_open_fd()) {
+    if (!sar_fd && sar_open_fd()) {
         sar_request_fail(req, RCODE_SOCKET_FAILURE);
         return;
     }
@@ -2000,7 +2001,9 @@ static struct sar_family_helper sar_ipv6_helper = {
 
 static void sar_cleanup(void)
 {
-    event_del(&sar_fd);
+    event_free(sar_timeout);
+    if (sar_fd)
+        event_free(sar_fd);
     set_clear(&sar_nameservers, 0);
     set_clear(&services_byname, 0);
     set_clear(&services_byport, 0);
@@ -2013,7 +2016,7 @@ void sar_init(void)
     conf.sar_root = conf_register_object(NULL, "resolver");
     services_byname.compare = set_compare_charp;
     services_byport.compare = set_compare_int;
-    evtimer_set(&sar_timeout, sar_timeout_cb, &sar_timeout);
+    sar_timeout = evtimer_new(ev_base, sar_timeout_cb, NULL);
 
     sar_register_helper(&sar_ipv4_helper);
 #if defined(AF_INET6)