From bec75f842fa401558a72d62bfbee04bc726407d6 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Mon, 15 Jul 2013 20:56:00 +0200 Subject: [PATCH] event: replace `evutil_make_socket_nonblocking()` by an idempotent version Once a file descriptor is locked with `BIOCLOCK`, it is not possible to make it non-blocking. Therefore, we need to make it non-blocking before locking it. Unfortunately, `evutil_make_socket_nonblocking()` does not check the current value of the flag to see if there is anything to do and we get a spurious warning. Just provide our version of this function for this purpose. --- src/daemon/event.c | 27 ++++++++++++++++++++++----- src/daemon/lldpd.h | 1 + src/daemon/priv-bsd.c | 4 +++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/daemon/event.c b/src/daemon/event.c index 17213c86..e1d5510b 100644 --- a/src/daemon/event.c +++ b/src/daemon/event.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -104,7 +105,7 @@ levent_snmp_add_fd(struct lldpd *cfg, int fd) log_warn("event", "unable to allocate memory for new SNMP event"); return; } - evutil_make_socket_nonblocking(fd); + levent_make_socket_nonblocking(fd); if ((snmpfd->ev = event_new(base, fd, EV_READ | EV_PERSIST, levent_snmp_read, @@ -358,7 +359,7 @@ levent_ctl_accept(evutil_socket_t fd, short what, void *arg) goto accept_failed; } client->cfg = cfg; - evutil_make_socket_nonblocking(s); + levent_make_socket_nonblocking(s); TAILQ_INSERT_TAIL(&lldpd_clients, client, next); if ((client->bev = bufferevent_socket_new(cfg->g_base, s, BEV_OPT_CLOSE_ON_FREE)) == NULL) { @@ -458,7 +459,7 @@ levent_init(struct lldpd *cfg) /* Setup unix socket */ log_debug("event", "register Unix socket"); TAILQ_INIT(&lldpd_clients); - evutil_make_socket_nonblocking(cfg->g_ctl); + levent_make_socket_nonblocking(cfg->g_ctl); if ((cfg->g_ctl_event = event_new(cfg->g_base, cfg->g_ctl, EV_READ|EV_PERSIST, levent_ctl_accept, cfg)) == NULL) fatalx("unable to setup control socket event"); @@ -547,7 +548,7 @@ levent_hardware_add_fd(struct lldpd_hardware *hardware, int fd) hardware->h_ifname); return; } - evutil_make_socket_nonblocking(fd); + levent_make_socket_nonblocking(fd); if ((hfd->ev = event_new(hardware->h_cfg->g_base, fd, EV_READ | EV_PERSIST, levent_hardware_recv, @@ -647,7 +648,7 @@ levent_iface_subscribe(struct lldpd *cfg, int socket) { log_debug("event", "subscribe to interface changes from socket %d", socket); - evutil_make_socket_nonblocking(socket); + levent_make_socket_nonblocking(socket); cfg->g_iface_event = event_new(cfg->g_base, socket, EV_READ | EV_PERSIST, levent_iface_recv, cfg); if (cfg->g_iface_event == NULL) { @@ -763,3 +764,19 @@ levent_schedule_pdu(struct lldpd_hardware *hardware) return; } } + +int +levent_make_socket_nonblocking(int fd) +{ + int flags; + if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { + log_warn("event", "fcntl(%d, F_GETFL)", fd); + return -1; + } + if (flags & O_NONBLOCK) return 0; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { + log_warn("event", "fcntl(%d, F_SETFL)", fd); + return -1; + } + return 0; +} diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index dc16e83c..58d86768 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -150,6 +150,7 @@ void levent_update_now(struct lldpd *); int levent_iface_subscribe(struct lldpd *, int); void levent_schedule_pdu(struct lldpd_hardware *); void levent_schedule_cleanup(struct lldpd *); +int levent_make_socket_nonblocking(int); /* lldp.c */ int lldp_send(PROTO_SEND_SIG); diff --git a/src/daemon/priv-bsd.c b/src/daemon/priv-bsd.c index 2a08875c..3a61b2d1 100644 --- a/src/daemon/priv-bsd.c +++ b/src/daemon/priv-bsd.c @@ -125,7 +125,9 @@ asroot_iface_init_os(int ifindex, char *name, int *fd) #endif #ifdef BIOCLOCK - /* Lock interface */ + /* Lock interface, but first make it non blocking since we cannot do + * this later */ + levent_make_socket_nonblocking(*fd); if (ioctl(*fd, BIOCLOCK, (caddr_t)&enable) < 0) { rc = errno; log_info("privsep", "unable to lock BPF interface %s", -- 2.39.5