1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 if (logopt & LOG_PERROR) { 92 nvlist_add_descriptor(nvl, "stderr", STDERR_FILENO); 93 } 94 nvl = cap_xfer_nvlist(chan, nvl); 95 if (nvl == NULL) { 96 return; 97 } 98 nvlist_destroy(nvl); 99 } 100 101 void 102 cap_closelog(cap_channel_t *chan) 103 { 104 nvlist_t *nvl; 105 106 nvl = nvlist_create(0); 107 nvlist_add_string(nvl, "cmd", "closelog"); 108 nvl = cap_xfer_nvlist(chan, nvl); 109 if (nvl == NULL) { 110 return; 111 } 112 nvlist_destroy(nvl); 113 } 114 115 int 116 cap_setlogmask(cap_channel_t *chan, int maskpri) 117 { 118 nvlist_t *nvl; 119 int omask; 120 121 nvl = nvlist_create(0); 122 nvlist_add_string(nvl, "cmd", "setlogmask"); 123 nvlist_add_number(nvl, "maskpri", maskpri); 124 nvl = cap_xfer_nvlist(chan, nvl); 125 omask = nvlist_get_number(nvl, "omask"); 126 127 nvlist_destroy(nvl); 128 129 return (omask); 130 } 131 132 /* 133 * Service functions. 134 */ 135 136 static char *LogTag; 137 static int prev_stderr = -1; 138 139 static void 140 slog_vsyslog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 141 nvlist_t *nvlout __unused) 142 { 143 144 syslog(nvlist_get_number(nvlin, "priority"), "%s", 145 nvlist_get_string(nvlin, "message")); 146 } 147 148 static void 149 slog_openlog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 150 nvlist_t *nvlout __unused) 151 { 152 const char *ident; 153 uint64_t logopt; 154 int stderr_fd; 155 156 ident = dnvlist_get_string(nvlin, "ident", NULL); 157 if (ident != NULL) { 158 free(LogTag); 159 LogTag = strdup(ident); 160 } 161 162 logopt = nvlist_get_number(nvlin, "logopt"); 163 if (logopt & LOG_PERROR) { 164 stderr_fd = dnvlist_get_descriptor(nvlin, "stderr", -1); 165 if (prev_stderr == -1) 166 prev_stderr = dup(STDERR_FILENO); 167 if (prev_stderr != -1) 168 (void)dup2(stderr_fd, STDERR_FILENO); 169 } else if (prev_stderr != -1) { 170 (void)dup2(prev_stderr, STDERR_FILENO); 171 close(prev_stderr); 172 prev_stderr = -1; 173 } 174 openlog(LogTag, logopt, nvlist_get_number(nvlin, "facility")); 175 } 176 177 static void 178 slog_closelog(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 179 nvlist_t *nvlout __unused) 180 { 181 182 closelog(); 183 184 free(LogTag); 185 LogTag = NULL; 186 187 if (prev_stderr != -1) { 188 (void)dup2(prev_stderr, STDERR_FILENO); 189 close(prev_stderr); 190 prev_stderr = -1; 191 } 192 } 193 194 static void 195 slog_setlogmask(const nvlist_t *limits __unused, const nvlist_t *nvlin, 196 nvlist_t *nvlout) 197 { 198 int omask; 199 200 omask = setlogmask(nvlist_get_number(nvlin, "maskpri")); 201 nvlist_add_number(nvlout, "omask", omask); 202 } 203 204 static int 205 syslog_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 206 nvlist_t *nvlout) 207 { 208 209 if (strcmp(cmd, "vsyslog") == 0) { 210 slog_vsyslog(limits, nvlin, nvlout); 211 } else if (strcmp(cmd, "openlog") == 0) { 212 slog_openlog(limits, nvlin, nvlout); 213 } else if (strcmp(cmd, "closelog") == 0) { 214 slog_closelog(limits, nvlin, nvlout); 215 } else if (strcmp(cmd, "setlogmask") == 0) { 216 slog_setlogmask(limits, nvlin, nvlout); 217 } else { 218 return (EINVAL); 219 } 220 221 return (0); 222 } 223 224 CREATE_SERVICE("system.syslog", NULL, syslog_command, 0); 225