diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile --- a/usr.sbin/syslogd/Makefile +++ b/usr.sbin/syslogd/Makefile @@ -15,6 +15,11 @@ LIBADD= util +.if ${MK_CASPER} != "no" +SRCS+= syslogd_cap.c +CFLAGS+= -DWITH_CASPER +LIBADD+= cap_net casper nv +.endif .if ${MK_INET_SUPPORT} != "no" CFLAGS+= -DINET .endif diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h new file mode 100644 --- /dev/null +++ b/usr.sbin/syslogd/syslogd.h @@ -0,0 +1,179 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1983, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * 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. + */ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Prodrive Technologies, https://prodrive-technologies.com/ + * Author: Ed Schouten + * 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. + */ + +#ifndef _SYSLOGD_H_ +#define _SYSLOGD_H_ + +#include +#include +#include + +#define SYSLOG_NAMES +#include + +#include + +#define MAXLINE 8192 /* maximum line length */ +#define MAXSVLINE MAXLINE /* maximum saved line length */ +#define MAXUNAMES 20 /* maximum number of user names */ + +/* Timestamps of log entries. */ +struct logtime { + struct tm tm; + suseconds_t usec; +}; + +enum filt_proptype { + FILT_PROP_NOOP, + FILT_PROP_MSG, + FILT_PROP_HOSTNAME, + FILT_PROP_PROGNAME, +}; + +enum filt_cmptype { + FILT_CMP_CONTAINS, + FILT_CMP_EQUAL, + FILT_CMP_STARTS, + FILT_CMP_REGEX, +}; + +/* + * This structure holds a property-based filter + */ +struct prop_filter { + enum filt_proptype prop_type; + enum filt_cmptype cmp_type; + uint8_t cmp_flags; +#define FILT_FLAG_EXCLUDE (1 << 0) +#define FILT_FLAG_EXTENDED (1 << 1) +#define FILT_FLAG_ICASE (1 << 2) + char *pflt_strval; + size_t pflt_strlen; + regex_t *pflt_re; +}; + +enum f_type { + F_UNUSED, /* unused entry */ + F_FILE, /* regular file */ + F_TTY, /* terminal */ + F_CONSOLE, /* console terminal */ + F_FORW, /* remote machine */ + F_USERS, /* list of users */ + F_WALL, /* everyone logged on */ + F_PIPE, /* pipe to program */ +}; + +/* + * This structure represents the files that will have log + * copies printed. + * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY + * or if f_type is F_PIPE and f_pid > 0. + */ +struct filed { + enum f_type f_type; + + /* Used for filtering. */ + char *f_host; /* host from which to recd. */ + char *f_program; /* program this applies to */ + struct prop_filter *f_prop_filter; /* property-based filter */ + u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ + u_char f_pcmp[LOG_NFACILITIES+1]; /* compare priority */ +#define PRI_LT 0x1 +#define PRI_EQ 0x2 +#define PRI_GT 0x4 + + /* Logging destinations. */ + int f_file; /* file descriptor */ + int f_flags; /* file-specific flags */ +#define FFLAG_SYNC 0x01 +#define FFLAG_NEEDSYNC 0x02 + union { + char f_uname[MAXUNAMES][MAXLOGNAME]; /* F_WALL, F_USERS */ + char f_fname[MAXPATHLEN]; /* F_FILE, F_CONSOLE, F_TTY */ + struct { + char f_hname[MAXHOSTNAMELEN]; + struct addrinfo *f_addr; + } f_forw; /* F_FORW */ + struct { + char f_pname[MAXPATHLEN]; + int f_procdesc; + } f_pipe; /* F_PIPE */ + } f_un; +#define fu_uname f_un.f_uname +#define fu_fname f_un.f_fname +#define fu_forw_hname f_un.f_forw.f_hname +#define fu_forw_addr f_un.f_forw.f_addr +#define fu_pipe_pname f_un.f_pipe.f_pname +#define fu_pipe_pd f_un.f_pipe.f_procdesc + + /* Book-keeping. */ + char f_prevline[MAXSVLINE]; /* last message logged */ + time_t f_time; /* time this was last written */ + struct logtime f_lasttime; /* time of last occurrence */ + int f_prevpri; /* pri of f_prevline */ + size_t f_prevlen; /* length of f_prevline */ + int f_prevcount; /* repetition cnt of prevline */ + u_int f_repeatcount; /* number of "repeated" msgs */ + STAILQ_ENTRY(filed) next; /* next in linked list */ +}; + +#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 @@ -80,12 +80,6 @@ * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will * cause it to reread its configuration file. * - * Defined Constants: - * - * MAXLINE -- the maximum line length that can be handled. - * DEFUPRI -- the default priority for user messages - * DEFSPRI -- the default priority for kernel messages - * * Author: Eric Allman * extensive changes by Ralph Campbell * more extensive changes by Eric Allman (again) @@ -95,8 +89,6 @@ * Priority comparison code by Harlan Stenn. */ -#define MAXLINE 8192 /* maximum line length */ -#define MAXSVLINE MAXLINE /* maximum saved line length */ #define DEFUPRI (LOG_USER|LOG_NOTICE) #define DEFSPRI (LOG_KERN|LOG_CRIT) #define TIMERINTVL 30 /* interval for checking flush, mark */ @@ -148,11 +140,10 @@ #include #include "pathnames.h" +#include "syslogd.h" +#include "syslogd_cap.h" #include "ttymsg.h" -#define SYSLOG_NAMES -#include - static const char *ConfFile = _PATH_LOGCONF; static const char *PidFile = _PATH_LOGPID; static const char include_str[] = "include"; @@ -160,8 +151,6 @@ #define dprintf if (Debug) printf -#define MAXUNAMES 20 /* maximum number of user names */ - #define sstosa(ss) ((struct sockaddr *)(ss)) #ifdef INET #define sstosin(ss) ((struct sockaddr_in *)(void *)(ss)) @@ -215,117 +204,14 @@ #define MARK 0x008 /* this message is a mark */ #define ISKERNEL 0x010 /* kernel generated message */ -/* Timestamps of log entries. */ -struct logtime { - struct tm tm; - suseconds_t usec; -}; - /* Traditional syslog timestamp format. */ #define RFC3164_DATELEN 15 #define RFC3164_DATEFMT "%b %e %H:%M:%S" -enum filt_proptype { - FILT_PROP_NOOP, - FILT_PROP_MSG, - FILT_PROP_HOSTNAME, - FILT_PROP_PROGNAME, -}; - -enum filt_cmptype { - FILT_CMP_CONTAINS, - FILT_CMP_EQUAL, - FILT_CMP_STARTS, - FILT_CMP_REGEX, -}; - -/* - * This structure holds a property-based filter - */ -struct prop_filter { - enum filt_proptype prop_type; - enum filt_cmptype cmp_type; - uint8_t cmp_flags; -#define FILT_FLAG_EXCLUDE (1 << 0) -#define FILT_FLAG_ICASE (1 << 1) - union { - char *p_strval; - regex_t *p_re; - } pflt_uniptr; -#define pflt_strval pflt_uniptr.p_strval -#define pflt_re pflt_uniptr.p_re - size_t pflt_strlen; -}; - -enum f_type { - F_UNUSED, /* unused entry */ - F_FILE, /* regular file */ - F_TTY, /* terminal */ - F_CONSOLE, /* console terminal */ - F_FORW, /* remote machine */ - F_USERS, /* list of users */ - F_WALL, /* everyone logged on */ - F_PIPE, /* pipe to program */ -}; - -/* - * This structure represents the files that will have log - * copies printed. - * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY - * or if f_type is F_PIPE and f_pid > 0. - */ -struct filed { - enum f_type f_type; - - /* Used for filtering. */ - char *f_host; /* host from which to recd. */ - char *f_program; /* program this applies to */ - struct prop_filter *f_prop_filter; /* property-based filter */ - u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ - u_char f_pcmp[LOG_NFACILITIES+1]; /* compare priority */ -#define PRI_LT 0x1 -#define PRI_EQ 0x2 -#define PRI_GT 0x4 - - /* Logging destinations. */ - int f_file; /* file descriptor */ - int f_flags; /* file-specific flags */ -#define FFLAG_SYNC 0x01 -#define FFLAG_NEEDSYNC 0x02 - union { - char f_uname[MAXUNAMES][MAXLOGNAME]; /* F_WALL, F_USERS */ - char f_fname[MAXPATHLEN]; /* F_FILE, F_CONSOLE, F_TTY */ - struct { - char f_hname[MAXHOSTNAMELEN]; - struct addrinfo *f_addr; - } f_forw; /* F_FORW */ - struct { - char f_pname[MAXPATHLEN]; - int f_procdesc; - } f_pipe; /* F_PIPE */ - } f_un; -#define fu_uname f_un.f_uname -#define fu_fname f_un.f_fname -#define fu_forw_hname f_un.f_forw.f_hname -#define fu_forw_addr f_un.f_forw.f_addr -#define fu_pipe_pname f_un.f_pipe.f_pname -#define fu_pipe_pd f_un.f_pipe.f_procdesc - - /* Book-keeping. */ - char f_prevline[MAXSVLINE]; /* last message logged */ - time_t f_time; /* time this was last written */ - struct logtime f_lasttime; /* time of last occurrence */ - int f_prevpri; /* pri of f_prevline */ - size_t f_prevlen; /* length of f_prevline */ - int f_prevcount; /* repetition cnt of prevline */ - u_int f_repeatcount; /* number of "repeated" msgs */ - STAILQ_ENTRY(filed) next; /* next in linked list */ -}; static STAILQ_HEAD(, filed) fhead = STAILQ_HEAD_INITIALIZER(fhead); /* Log files that we write to */ static struct filed consfile; /* Console */ - /* * Queue of about-to-be dead processes we should watch out for. */ @@ -2559,7 +2445,7 @@ case FILT_CMP_REGEX: regfree(f->f_prop_filter->pflt_re); free(f->f_prop_filter->pflt_re); - break; + /* FALLTHROUGH */ case FILT_CMP_CONTAINS: case FILT_CMP_EQUAL: case FILT_CMP_STARTS: @@ -2723,7 +2609,6 @@ struct prop_filter *pfilter; char *filter, *filter_endpos, *filter_begpos, *p; char **ap, *argv[2] = {NULL, NULL}; - int re_flags = REG_NOSUB; int escaped; pfilter = calloc(1, sizeof(*pfilter)); @@ -2799,7 +2684,7 @@ pfilter->cmp_type = FILT_CMP_REGEX; else if (strcasecmp(argv[1], "ereregex") == 0) { pfilter->cmp_type = FILT_CMP_REGEX; - re_flags |= REG_EXTENDED; + pfilter->cmp_flags |= REG_EXTENDED; } else { logerror("unknown cmp function"); goto error; @@ -2850,21 +2735,28 @@ } if (pfilter->cmp_type == FILT_CMP_REGEX) { + int re_flags = REG_NOSUB; + pfilter->pflt_re = calloc(1, sizeof(*pfilter->pflt_re)); if (pfilter->pflt_re == NULL) { logerror("RE calloc() error"); goto error; } + if (pfilter->cmp_flags & FILT_FLAG_EXTENDED) + re_flags |= REG_EXTENDED; if (pfilter->cmp_flags & FILT_FLAG_ICASE) re_flags |= REG_ICASE; if (regcomp(pfilter->pflt_re, filter, re_flags) != 0) { logerror("RE compilation error"); goto error; } - } else { - pfilter->pflt_strval = strdup(filter); - pfilter->pflt_strlen = strlen(filter); } + pfilter->pflt_strval = strdup(filter); + if (pfilter->pflt_strval == NULL) { + logerror("strdup"); + exit(1); + } + pfilter->pflt_strlen = strlen(filter); free(filter_begpos); return (pfilter); diff --git a/usr.sbin/syslogd/syslogd_cap.h b/usr.sbin/syslogd/syslogd_cap.h new file mode 100644 --- /dev/null +++ b/usr.sbin/syslogd/syslogd_cap.h @@ -0,0 +1,55 @@ +/*- + * 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. + */ + +#ifndef _SYSLOGD_CAP_H_ +#define _SYSLOGD_CAP_H_ + +#include + +#include + +#include + +#ifdef WITH_CASPER + +#include +#include + +#include +#include + +#include "syslogd.h" + +nvlist_t *filed_to_nvlist(const struct filed *); +struct filed *nvlist_to_filed(const nvlist_t *); + +#endif /* WITH_CASPER */ + +#endif /* !_SYSLOGD_CAP_H_ */ diff --git a/usr.sbin/syslogd/syslogd_cap.c b/usr.sbin/syslogd/syslogd_cap.c new file mode 100644 --- /dev/null +++ b/usr.sbin/syslogd/syslogd_cap.c @@ -0,0 +1,215 @@ +/*- + * 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 +#include +#include +#include +#include + +#include + +#include "syslogd_cap.h" + +/* + * syslogd_cap.c: Functions shared between syslogd Capsicum components. + * + * NVLIST STORING CONVENTIONS: + * + * Structures may be added to nvlists as binaries, e.g. using + * nvlist_add_binary(), but all pointer and file descriptor + * members will not be accessible to syslogd after transfer. + * + * Structure members that are pointers or file descriptors + * must be copied into the nvlist seperately, alongside the + * binary structure data. + * + * For example: + * struct prop_filter->pflt_strval is a pointer, so we can + * seperately copy the string data and the struct prop_filter + * into an nvlist and assign the prop_filter->pflt_strval + * pointer after the transfer to syslogd. + */ + +/* + * Convert the given prop_filter structure into an nvlist. + * Return a heap allocated pointer to the resulting nvlist. + */ +static nvlist_t * +prop_filter_to_nvlist(const struct prop_filter *pfilter) +{ + nvlist_t *nvl_prop_filter = nvlist_create(0); + + if (pfilter->pflt_strval != NULL) { + nvlist_add_string(nvl_prop_filter, "pflt_strval", + pfilter->pflt_strval); + } + nvlist_add_binary(nvl_prop_filter, "prop_filter", pfilter, + sizeof(*pfilter)); + + return (nvl_prop_filter); +} + +/* + * Convert the given nvlist into a prop_filter structure. + * Return a heap allocated pointer to the resulting prop_filter. + */ +static struct prop_filter * +nvlist_to_prop_filter(const nvlist_t *nvl_prop_filter) +{ + struct prop_filter *pfilter; + size_t sz; + + pfilter = malloc(sizeof(*pfilter)); + if (pfilter == NULL) + err(1, "malloc"); + (void)memcpy(pfilter, nvlist_get_binary(nvl_prop_filter, + "prop_filter", &sz), sizeof(*pfilter)); + assert(sz == sizeof(*pfilter)); + if (!nvlist_exists_string(nvl_prop_filter, "pflt_strval")) + return (pfilter); + pfilter->pflt_strval = strdup(nvlist_get_string(nvl_prop_filter, + "pflt_strval")); + if (pfilter->cmp_type == FILT_CMP_REGEX) { + int re_flags = REG_NOSUB; + pfilter->pflt_re = calloc(1, sizeof(*pfilter->pflt_re)); + if (pfilter->pflt_re == NULL) + errx(1, "RE calloc() error"); + if ((pfilter->cmp_flags & FILT_FLAG_EXTENDED) != 0) + re_flags |= REG_EXTENDED; + if ((pfilter->cmp_flags & FILT_FLAG_ICASE) != 0) + re_flags |= REG_ICASE; + if (regcomp(pfilter->pflt_re, pfilter->pflt_strval, + re_flags) != 0) + errx(1, "RE compilation error"); + } + + return (pfilter); +} + +/* + * Convert the given struct filed into an nvl_filed nvlist. + * Return a heap allocated pointer to the resulting nvlist. + */ +nvlist_t * +filed_to_nvlist(const struct filed *filed) +{ + nvlist_t *nvl_filed = nvlist_create(0); + + if (filed->f_host != NULL) + nvlist_add_string(nvl_filed, "f_host", filed->f_host); + if (filed->f_program != NULL) + nvlist_add_string(nvl_filed, "f_program", filed->f_program); + if (filed->f_prop_filter != NULL) { + nvlist_add_nvlist(nvl_filed, "nvl_prop_filter", + prop_filter_to_nvlist(filed->f_prop_filter)); + } + if (filed->fu_forw_addr != NULL) { + struct addrinfo *ai = filed->fu_forw_addr, *cur; + nvlist_t *nvl_addrinfo; + uint64_t i; + + for (cur = ai, i = 0; cur != NULL; cur = cur->ai_next, ++i) { + nvl_addrinfo = addrinfo_pack(cur); + nvlist_append_nvlist_array(nvl_filed, "addrinfo_list", + nvl_addrinfo); + nvlist_destroy(nvl_addrinfo); + } + nvlist_add_number(nvl_filed, "addrinfo_count", i); + } + if (filed->f_type == F_FILE && filed->f_file >= 0) + nvlist_add_descriptor(nvl_filed, "f_file", filed->f_file); + nvlist_add_binary(nvl_filed, "filed", filed, sizeof(*filed)); + + return (nvl_filed); +} + +/* + * Convert the given nvl_filed nvlist into a struct filed. + * Return a heap allocated pointer to the resulting struct + * filed. + */ +struct filed * +nvlist_to_filed(const nvlist_t *nvl_filed) +{ + struct filed *f; + size_t sz; + + f = malloc(sizeof(*f)); + if (f == NULL) + err(1, "malloc"); + (void)memcpy(f, nvlist_get_binary(nvl_filed, "filed", &sz), sizeof(*f)); + assert(sz = sizeof(*f)); + if (nvlist_exists_string(nvl_filed, "f_host")) + f->f_host = strdup(nvlist_get_string(nvl_filed, "f_host")); + if (nvlist_exists_string(nvl_filed, "f_program")) { + f->f_program = strdup(dnvlist_get_string(nvl_filed, + "f_program", NULL)); + } + if (nvlist_exists_nvlist(nvl_filed, "nvl_prop_filter")) { + f->f_prop_filter = nvlist_to_prop_filter( + nvlist_get_nvlist(nvl_filed, "nvl_prop_filter")); + } + if (nvlist_exists_nvlist_array(nvl_filed, "addrinfo_list")) { + const nvlist_t * const *addrinfo_list; + struct addrinfo *ai, **next = NULL; + uint64_t addrinfo_count, i; + + addrinfo_count = nvlist_get_number(nvl_filed, "addrinfo_count"); + addrinfo_list = nvlist_get_nvlist_array(nvl_filed, + "addrinfo_list", &addrinfo_count); + for (i = 0; i < addrinfo_count; ++i) { + ai = addrinfo_unpack(addrinfo_list[i]); + if (next == NULL) + f->fu_forw_addr = ai; + else + *next = ai; + next = &ai->ai_next; + } + } + if (nvlist_exists_descriptor(nvl_filed, "f_file")) + f->f_file = dup(nvlist_get_descriptor(nvl_filed, "f_file")); + + return (f); +} + +/* 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) +{ + int error = EINVAL; + return (error); +} + +CREATE_SERVICE("syslogd.casper", NULL, casper_command, CASPER_SERVICE_STDIO);