1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2017 Mariusz Zaborski <oshogbo@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/dnv.h> 33 #include <sys/nv.h> 34 35 #include <assert.h> 36 #include <errno.h> 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <syslog.h> 42 43 #include <libcasper.h> 44 #include <libcasper_service.h> 45 46 #include "cap_syslog.h" 47 48 #define CAP_SYSLOG_LIMIT 2048 49 50 void 51 cap_syslog(cap_channel_t *chan, int pri, const char *fmt, ...) 52 { 53 va_list ap; 54 55 va_start(ap, fmt); 56 cap_vsyslog(chan, pri, fmt, ap); 57 va_end(ap); 58 } 59 60 void 61 cap_vsyslog(cap_channel_t *chan, int priority, const char *fmt, va_list ap) 62 { 63 nvlist_t *nvl; 64 char message[CAP_SYSLOG_LIMIT]; 65 66 (void)vsnprintf(message, sizeof(message), fmt, ap); 67 68 nvl = nvlist_create(0); 69 nvlist_add_string(nvl, "cmd", "vsyslog"); 70 nvlist_add_number(nvl, "priority", priority); 71 nvlist_add_string(nvl, "message", message); 72 nvl = cap_xfer_nvlist(chan, nvl); 73 if (nvl == NULL) { 74 return; 75 } 76 nvlist_destroy(nvl); 77 } 78 79 void 80 cap_openlog(cap_channel_t *chan, const char *ident, int logopt, int facility) 81 { 82 nvlist_t *nvl; 83 84 nvl = nvlist_create(0); 85 nvlist_add_string(nvl, "cmd", "openlog"); 86 if (ident != NULL) { 87 nvlist_add_string(nvl, "ident", ident); 88 } 89 nvlist_add_number(nvl, "logopt", logopt); 90 nvlist_add_number(nvl, "facility", facility); 91 nvl = cap_xfer_nvlist(chan, nvl); 92 if (nvl == NULL) { 93 return; 94 } 95 nvlist_destroy(nvl); 96 } 97 98 void 99 cap_closelog(cap_channel_t *chan) 100 { 101 nvlist_t *nvl; 102 103 nvl = nvlist_create(0); 104 nvlist_add_string(nvl, "cmd", "closelog"); 105 nvl = cap_xfer_nvlist(chan, nvl); 106 if (nvl == NULL) { 107 return; 108 } 109 nvlist_destroy(nvl); 110 } 111 112 int 113 cap_setlogmask(cap_channel_t *chan, int maskpri) 114 { 115 nvlist_t *nvl; 116 int omask; 117 118 nvl = nvlist_create(0); 119 nvlist_add_string(nvl, "cmd", "setlogmask"); 120 nvlist_add_number(nvl, "maskpri", maskpri); 121 nvl = cap_xfer_nvlist(chan, nvl); 122 omask = nvlist_get_number(nvl, "omask"); 123 124 nvlist_destroy(nvl); 125 126 return (omask); 127 } 128 129 /* 130 * Service functions. 131 */ 132 133 static char *LogTag; 134 135 static void 136 slog_vsyslog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 137 nvlist_t *nvlout __unused) 138 { 139 140 syslog(nvlist_get_number(nvlin, "priority"), "%s", 141 nvlist_get_string(nvlin, "message")); 142 } 143 144 static void 145 slog_openlog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 146 nvlist_t *nvlout __unused) 147 { 148 const char *ident; 149 150 ident = dnvlist_get_string(nvlin, "ident", NULL); 151 if (ident != NULL) { 152 free(LogTag); 153 LogTag = strdup(ident); 154 } 155 156 openlog(LogTag, nvlist_get_number(nvlin, "logopt"), 157 nvlist_get_number(nvlin, "facility")); 158 } 159 160 static void 161 slog_closelog(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 162 nvlist_t *nvlout __unused) 163 { 164 165 closelog(); 166 167 free(LogTag); 168 LogTag = NULL; 169 } 170 171 static void 172 slog_setlogmask(const nvlist_t *limits __unused, const nvlist_t *nvlin, 173 nvlist_t *nvlout) 174 { 175 int omask; 176 177 omask = setlogmask(nvlist_get_number(nvlin, "maskpri")); 178 nvlist_add_number(nvlout, "omask", omask); 179 } 180 181 static int 182 syslog_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 183 nvlist_t *nvlout) 184 { 185 186 if (strcmp(cmd, "vsyslog") == 0) { 187 slog_vsyslog(limits, nvlin, nvlout); 188 } else if (strcmp(cmd, "openlog") == 0) { 189 slog_openlog(limits, nvlin, nvlout); 190 } else if (strcmp(cmd, "closelog") == 0) { 191 slog_closelog(limits, nvlin, nvlout); 192 } else if (strcmp(cmd, "setlogmask") == 0) { 193 slog_setlogmask(limits, nvlin, nvlout); 194 } else { 195 return (EINVAL); 196 } 197 198 return (0); 199 } 200 201 CREATE_SERVICE("system.syslog", NULL, syslog_command, CASPER_SERVICE_STDIO); 202