diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile --- a/usr.sbin/syslogd/Makefile +++ b/usr.sbin/syslogd/Makefile @@ -16,7 +16,8 @@ LIBADD= util .if ${MK_CASPER} != "no" -SRCS+= syslogd_cap.c +SRCS+= syslogd_cap.c \ + syslogd_cap_config.c CFLAGS+= -DWITH_CASPER LIBADD+= cap_net casper nv .endif diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h --- a/usr.sbin/syslogd/syslogd.h +++ b/usr.sbin/syslogd/syslogd.h @@ -71,6 +71,8 @@ #include #include +#include +#include #define MAXLINE 8192 /* maximum line length */ #define MAXSVLINE MAXLINE /* maximum saved line length */ @@ -175,5 +177,13 @@ u_int f_repeatcount; /* number of "repeated" msgs */ STAILQ_ENTRY(filed) next; /* next in linked list */ }; +extern STAILQ_HEAD(filed_list, filed) fhead; + +extern char LocalHostName[MAXHOSTNAMELEN]; + +void closelogfiles(void); +void logerror(const char *); +void parseconfigfile(FILE *, bool); +void readconfigfile(const char *); #endif /* !_SYSLOGD_H_ */ diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -208,8 +208,10 @@ #define RFC3164_DATELEN 15 #define RFC3164_DATEFMT "%b %e %H:%M:%S" -static STAILQ_HEAD(, filed) fhead = - STAILQ_HEAD_INITIALIZER(fhead); /* Log files that we write to */ +/* + * List of log files. + */ +struct filed_list fhead = STAILQ_HEAD_INITIALIZER(fhead); static struct filed consfile; /* Console */ /* @@ -289,7 +291,7 @@ static bool Debug; /* debug flag */ static bool Foreground = false; /* Run in foreground, instead of daemonizing */ static bool resolve = true; /* resolve hostname */ -static char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ +char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ static const char *LocalDomain; /* our local domain name */ static bool Initialized; /* set when we have initialized ourselves */ static int MarkInterval = 20 * 60; /* interval between marks in seconds */ @@ -338,7 +340,6 @@ static void fprintlog_write(struct filed *, struct iovlist *, int); static void fprintlog_successive(struct filed *, int); static void init(bool); -static void logerror(const char *); static void logmsg(int, const struct logtime *, const char *, const char *, const char *, const char *, const char *, const char *, int); static void markit(void); @@ -2183,7 +2184,7 @@ /* * Print syslogd errors some place. */ -static void +void logerror(const char *msg) { char buf[512]; @@ -2260,7 +2261,7 @@ return (1); } -static void +void parseconfigfile(FILE *cf, bool allow_includes) { FILE *cf2; @@ -2395,7 +2396,7 @@ } } -static void +void readconfigfile(const char *path) { FILE *cf; @@ -2413,7 +2414,7 @@ /* * Close all open log files. */ -static void +void closelogfiles(void) { struct filed *f; diff --git a/usr.sbin/syslogd/syslogd_cap.h b/usr.sbin/syslogd/syslogd_cap.h --- a/usr.sbin/syslogd/syslogd_cap.h +++ b/usr.sbin/syslogd/syslogd_cap.h @@ -47,9 +47,17 @@ #include "syslogd.h" +void cap_readconfigfile(cap_channel_t *, const char *); +int casper_readconfigfile(nvlist_t *, nvlist_t *); + nvlist_t *filed_to_nvlist(const struct filed *); struct filed *nvlist_to_filed(const nvlist_t *); +#else /* !WITH_CASPER */ + +#define cap_readconfigfile(chan, cf) \ + readconfigfile(cf) + #endif /* WITH_CASPER */ #endif /* !_SYSLOGD_CAP_H_ */ diff --git a/usr.sbin/syslogd/syslogd_cap.c b/usr.sbin/syslogd/syslogd_cap.c --- a/usr.sbin/syslogd/syslogd_cap.c +++ b/usr.sbin/syslogd/syslogd_cap.c @@ -204,10 +204,14 @@ /* This is where libcasper receives commands via nvlist. */ static int -casper_command(const char *cmd __unused, const nvlist_t *limits __unused, - nvlist_t *nvlin __unused, nvlist_t *nvlout __unused) +casper_command(const char *cmd, const nvlist_t *limits __unused, + nvlist_t *nvlin, nvlist_t *nvlout) { int error = EINVAL; + + if (strcmp(cmd, "readconfigfile") == 0) + error = casper_readconfigfile(nvlin, nvlout); + return (error); } diff --git a/usr.sbin/syslogd/syslogd_cap_config.c b/usr.sbin/syslogd/syslogd_cap_config.c new file mode 100644 --- /dev/null +++ b/usr.sbin/syslogd/syslogd_cap_config.c @@ -0,0 +1,127 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Jake Freeland + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +#include + +#include "syslogd_cap.h" + +/* + * Return an nvlist of filed configuration files based on + * the global fhead list. + */ +static nvlist_t * +create_config(void) +{ + struct filed *f; + nvlist_t *config = nvlist_create(0); + + STAILQ_FOREACH(f, &fhead, next) { + nvlist_t *nvl_filed = filed_to_nvlist(f); + nvlist_append_nvlist_array(config, "filed_list", nvl_filed); + nvlist_destroy(nvl_filed); + } + + return (config); +} + +/* + * Add each filed configuration file contained in @config onto + * the global fhead list. + */ +static void +populate_config(const nvlist_t *config) +{ + if (nvlist_exists_nvlist_array(config, "filed_list")) { + struct filed *f; + const nvlist_t * const *filed_list; + uint64_t filed_count, i; + + filed_list = nvlist_get_nvlist_array(config, "filed_list", + &filed_count); + for (i = 0; i < filed_count; ++i) { + f = nvlist_to_filed(filed_list[i]); + STAILQ_INSERT_TAIL(&fhead, f, next); + } + } +} + +/* + * Ask the libcasper process to parse the configuration file. + * Use the resulting nvlist to populate our global filed list. + */ +void +cap_readconfigfile(cap_channel_t *chan, const char *path) +{ + nvlist_t *nvl = nvlist_create(0); + int error; + + nvlist_add_string(nvl, "cmd", "readconfigfile"); + nvlist_add_string(nvl, "path", path); + /* It is possible that our hostname was changed. */ + nvlist_add_string(nvl, "LocalHostName", LocalHostName); + nvl = cap_xfer_nvlist(chan, nvl); + if (nvl == NULL) { + logerror("Failed to xfer configuration nvlist"); + exit(1); + } + error = nvlist_get_number(nvl, "error"); + if (error != 0) { + errno = error; + logerror("Failed to parse configuration file"); + } + populate_config(nvlist_get_nvlist(nvl, "config")); + nvlist_destroy(nvl); +} + +/* + * Now that we're executing as libcasper, we can obtain the + * resources specified in the configuration. + */ +int +casper_readconfigfile(nvlist_t *nvlin, nvlist_t *nvlout) +{ + /* Refresh our copy of LocalHostName, in case it changed. */ + strlcpy(LocalHostName, nvlist_get_string(nvlin, "LocalHostName"), + sizeof(LocalHostName)); + /* + * If we're here, then syslogd's global filed list + * should be empty to prepare for the new config. + * Do the same here, in the libcasper process. + */ + closelogfiles(); + /* + * Populate the libcasper process' filed list and + * export it for use in syslogd using create_config(). + */ + readconfigfile(nvlist_get_string(nvlin, "path")); + nvlist_add_nvlist(nvlout, "config", create_config()); + return (0); +}