diff --git a/src/Makefile.am b/src/Makefile.am index 575e937..82ef099 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ AM_CFLAGS += -Wno-unused-result -Wno-unused-parameter -fno-strict-ali AM_CPPFLAGS = -DSYSCONFDIR=\"@sysconfdir@\" -DLOCALSTATEDIR=\"@localstatedir@\" AM_CPPFLAGS += -D_BSD_SOURCE -D_DEFAULT_SOURCE -syslogd_SOURCES = syslogd.c syslogd.h syslog.h queue.h compat.h +syslogd_SOURCES = syslogd.c syslogd.h socket.c socket.h syslog.h queue.h compat.h syslogd_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600 syslogd_LDADD = $(LIBS) $(LIBOBJS) diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..3f9bc08 --- /dev/null +++ b/src/socket.c @@ -0,0 +1,168 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 2017-2019 Joachim Nilsson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "queue.h" + +struct sock { + LIST_ENTRY(sock) link; + + int sd; + + void (*cb)(int, void *arg); + void *arg; +}; + +static int max_fdnum = -1; +LIST_HEAD(, sock) sl = LIST_HEAD_INITIALIZER(); + + +int nfds(void) +{ + return max_fdnum + 1; +} + +/* + * register socket/fd/pipe created elsewhere, optional callback + */ +int socket_register(int sd, void (*cb)(int, void *), void *arg) +{ + struct sock *entry; + + entry = malloc(sizeof(*entry)); + if (!entry) + return -1; + + entry->sd = sd; + entry->cb = cb; + entry->arg = arg; + LIST_INSERT_HEAD(&sl, entry, link); + +#if !defined(HAVE_SOCK_CLOEXEC) && defined(HAVE_FCNTL_H) + fcntl(sd, F_SETFD, fcntl(sd, F_GETFD) | FD_CLOEXEC); +#endif + + /* Keep track for select() */ + if (sd > max_fdnum) + max_fdnum = sd; + + return sd; +} + +/* + * create socket, with optional callback for reading inbound data + */ +int socket_create(int domain, int type, int proto, void (*cb)(int, void *), void *arg) +{ + int sd; + +#ifdef HAVE_SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif + sd = socket(domain, type, proto); + if (sd < 0) + return -1; + + if (socket_register(sd, cb, arg) < 0) { + close(sd); + return -1; + } + + return sd; +} + +int socket_close(int sd) +{ + struct sock *entry, *tmp; + + LIST_FOREACH_SAFE(entry, &sl, link, tmp) { + if (entry->sd == sd) { + LIST_REMOVE(entry, link); + close(entry->sd); + free(entry); + + return 0; + } + } + + errno = ENOENT; + return -1; +} + +int socket_poll(struct timeval *timeout) +{ + int num; + fd_set fds; + struct sock *entry; + + FD_ZERO(&fds); + LIST_FOREACH(entry, &sl, link) + FD_SET(entry->sd, &fds); + + num = select(nfds(), &fds, NULL, NULL, timeout); + if (num <= 0) { + /* Log all errors, except when signalled, ignore failures. */ + if (num < 0 && EINTR != errno) + smclog(LOG_WARNING, "Failed select(): %s", strerror(errno)); + + return num; + } + + LIST_FOREACH(entry, &sl, link) { + if (!FD_ISSET(entry->sd, &fds)) + continue; + + if (entry->cb) + entry->cb(entry->sd, entry->arg); + } + + return num; +} + +/** + * Local Variables: + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..0fe5cb7 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 2017-2019 Joachim Nilsson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef SYSKLOGD_SOCKET_H_ +#define SYSKLOGD_SOCKET_H_ + +#include +#include +#include + +int socket_register(int sd, void (*cb)(int, void *), void *arg); +int socket_create (int domain, int type, int proto, void (*cb)(int, void *), void *arg); +int socket_close (int sd); +int socket_poll (struct timeval *timeout); + +#endif /* SYSKLOGD_SOCKET_H_ */ diff --git a/src/syslogd.c b/src/syslogd.c index 321cff7..fc90c40 100644 --- a/src/syslogd.c +++ b/src/syslogd.c @@ -90,6 +90,7 @@ static char sccsid[] __attribute__((unused)) = #define SYSLOG_NAMES #include "syslogd.h" +#include "socket.h" #include "compat.h" char *ConfFile = _PATH_LOGCONF;