subr.c revision 243730
150476Speter/*- 247857Sbrian * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net> 347857Sbrian * All rights reserved. 447857Sbrian * 547857Sbrian * Redistribution and use in source and binary forms, with or without 647857Sbrian * modification, are permitted provided that the following conditions 747857Sbrian * are met: 847857Sbrian * 1. Redistributions of source code must retain the above copyright 947857Sbrian * notice, this list of conditions and the following disclaimer. 1047857Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1147857Sbrian * notice, this list of conditions and the following disclaimer in the 1247857Sbrian * documentation and/or other materials provided with the distribution. 1347857Sbrian * 1447857Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1547857Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1647857Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1747857Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/subr.c#1 $ 27 */ 28 29#include "config.h" 30 31#ifdef HAVE_KQUEUE 32#include <sys/types.h> 33#include <sys/event.h> 34#include <sys/time.h> 35#endif 36 37#include <errno.h> 38#include <stdarg.h> 39#include <stdio.h> 40#include <string.h> 41#include <unistd.h> 42 43#ifndef HAVE_ARC4RANDOM 44#include <openssl/rand.h> 45#endif 46 47#ifndef HAVE_STRLCAT 48#include <compat/strlcat.h> 49#endif 50 51#include <pjdlog.h> 52 53#include "auditdistd.h" 54#include "subr.h" 55 56int 57vsnprlcat(char *str, size_t size, const char *fmt, va_list ap) 58{ 59 size_t len; 60 61 len = strlen(str); 62 return (vsnprintf(str + len, size - len, fmt, ap)); 63} 64 65int 66snprlcat(char *str, size_t size, const char *fmt, ...) 67{ 68 va_list ap; 69 int result; 70 71 va_start(ap, fmt); 72 result = vsnprlcat(str, size, fmt, ap); 73 va_end(ap); 74 return (result); 75} 76 77const char * 78role2str(int role) 79{ 80 81 switch (role) { 82 case ADIST_ROLE_SENDER: 83 return ("sender"); 84 case ADIST_ROLE_RECEIVER: 85 return ("receiver"); 86 } 87 return ("unknown"); 88} 89 90const char * 91adist_errstr(int error) 92{ 93 94 switch (error) { 95 case ADIST_ERROR_WRONG_ORDER: 96 return ("wrong operations order"); 97 case ADIST_ERROR_INVALID_NAME: 98 return ("invalid trail file name"); 99 case ADIST_ERROR_OPEN_OLD: 100 return ("attempt to open an old trail file"); 101 case ADIST_ERROR_CREATE: 102 return ("creation of new trail file failed"); 103 case ADIST_ERROR_OPEN: 104 return ("open of existing trail file failed"); 105 case ADIST_ERROR_READ: 106 return ("read failed"); 107 case ADIST_ERROR_WRITE: 108 return ("write failed"); 109 case ADIST_ERROR_RENAME: 110 return ("rename of a trail file failed"); 111 default: 112 return ("unknown error"); 113 } 114} 115 116void 117adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, 118 const char *fmt, ...) 119{ 120 char msg[1024]; 121 va_list ap; 122 123 va_start(ap, fmt); 124 (void)vsnprintf(msg, sizeof(msg), fmt, ap); 125 va_end(ap); 126 (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ", 127 (uintmax_t)adreq->adr_seq); 128 switch (adreq->adr_cmd) { 129 case ADIST_CMD_OPEN: 130 (void)snprlcat(msg, sizeof(msg), "OPEN(%s)", 131 adreq->adr_data); 132 break; 133 case ADIST_CMD_APPEND: 134 (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)", 135 (uintmax_t)adreq->adr_datasize); 136 break; 137 case ADIST_CMD_CLOSE: 138 (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)", 139 adreq->adr_data); 140 break; 141 case ADIST_CMD_KEEPALIVE: 142 (void)snprlcat(msg, sizeof(msg), "KEEPALIVE"); 143 break; 144 case ADIST_CMD_ERROR: 145 (void)snprlcat(msg, sizeof(msg), "ERROR"); 146 break; 147 default: 148 (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)", 149 adreq->adr_cmd); 150 break; 151 } 152 if (error != -1) 153 (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error)); 154 (void)strlcat(msg, ".", sizeof(msg)); 155 pjdlog_common(loglevel, debuglevel, -1, "%s", msg); 156} 157 158int 159adist_random(unsigned char *buf, size_t size) 160{ 161#ifdef HAVE_ARC4RANDOM_BUF 162 arc4random_buf(buf, size); 163 return (0); 164#elif defined(HAVE_ARC4RANDOM) 165 uint32_t val; 166 167 PJDLOG_ASSERT(size > 0); 168 PJDLOG_ASSERT((size % sizeof(val)) == 0); 169 170 do { 171 val = arc4random(); 172 bcopy(&val, buf, sizeof(val)); 173 buf += sizeof(val); 174 size -= sizeof(val); 175 } while (size > 0); 176 177 return (0); 178#else 179 if (RAND_bytes(buf, (int)size) == 0) 180 return (-1); 181 return (0); 182#endif 183} 184 185static int wait_for_dir_kq = -1; 186static int wait_for_file_kq = -1; 187 188int 189wait_for_dir_init(int fd) 190{ 191#ifdef HAVE_KQUEUE 192 struct kevent ev; 193 int error, kq; 194 195 PJDLOG_ASSERT(wait_for_dir_kq == -1); 196#endif 197 198 PJDLOG_ASSERT(fd != -1); 199 200#ifdef HAVE_KQUEUE 201 kq = kqueue(); 202 if (kq == -1) { 203 pjdlog_errno(LOG_WARNING, "kqueue() failed"); 204 return (-1); 205 } 206 EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 207 NOTE_WRITE, 0, 0); 208 if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { 209 error = errno; 210 pjdlog_errno(LOG_WARNING, "kevent() failed"); 211 (void)close(kq); 212 errno = error; 213 return (-1); 214 } 215 wait_for_dir_kq = kq; 216#endif 217 218 return (0); 219} 220 221int 222wait_for_file_init(int fd) 223{ 224#ifdef HAVE_KQUEUE 225 struct kevent ev[2]; 226 int error, kq; 227#endif 228 229 PJDLOG_ASSERT(fd != -1); 230 231#ifdef HAVE_KQUEUE 232 kq = kqueue(); 233 if (kq == -1) { 234 pjdlog_errno(LOG_WARNING, "kqueue() failed"); 235 return (-1); 236 } 237 EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 238 NOTE_RENAME, 0, 0); 239 EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 240 0, 0, 0); 241 if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) { 242 error = errno; 243 pjdlog_errno(LOG_WARNING, "kevent() failed"); 244 (void)close(kq); 245 errno = error; 246 return (-1); 247 } 248 wait_for_file_kq = kq; 249#endif 250 251 return (0); 252} 253 254/* 255 * Wait for new file to appear in directory. 256 */ 257void 258wait_for_dir(void) 259{ 260#ifdef HAVE_KQUEUE 261 struct kevent ev; 262#endif 263 264 if (wait_for_dir_kq == -1) { 265 sleep(1); 266 return; 267 } 268 269#ifdef HAVE_KQUEUE 270 PJDLOG_ASSERT(wait_for_dir_kq != -1); 271 272 if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) { 273 pjdlog_errno(LOG_WARNING, "kevent() failed"); 274 sleep(1); 275 } 276#endif 277} 278 279/* 280 * Wait for file growth or rename. 281 */ 282void 283wait_for_file(void) 284{ 285#ifdef HAVE_KQUEUE 286 struct kevent ev[2]; 287#endif 288 289 if (wait_for_file_kq == -1) { 290 sleep(1); 291 return; 292 } 293 294#ifdef HAVE_KQUEUE 295 PJDLOG_ASSERT(wait_for_file_kq != -1); 296 297 if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) { 298 pjdlog_errno(LOG_WARNING, "kevent() failed"); 299 sleep(1); 300 } 301#endif 302} 303