1243730Srwatson/*- 2243730Srwatson * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net> 3243730Srwatson * All rights reserved. 4243730Srwatson * 5243730Srwatson * Redistribution and use in source and binary forms, with or without 6243730Srwatson * modification, are permitted provided that the following conditions 7243730Srwatson * are met: 8243730Srwatson * 1. Redistributions of source code must retain the above copyright 9243730Srwatson * notice, this list of conditions and the following disclaimer. 10243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11243730Srwatson * notice, this list of conditions and the following disclaimer in the 12243730Srwatson * documentation and/or other materials provided with the distribution. 13243730Srwatson * 14243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24243730Srwatson * SUCH DAMAGE. 25243730Srwatson */ 26243730Srwatson 27243734Srwatson#include <config/config.h> 28243730Srwatson 29243730Srwatson#ifdef HAVE_KQUEUE 30243730Srwatson#include <sys/types.h> 31243730Srwatson#include <sys/event.h> 32243730Srwatson#include <sys/time.h> 33243730Srwatson#endif 34243730Srwatson 35243730Srwatson#include <errno.h> 36243730Srwatson#include <stdarg.h> 37243730Srwatson#include <stdio.h> 38243730Srwatson#include <string.h> 39243730Srwatson#include <unistd.h> 40243730Srwatson 41243730Srwatson#ifndef HAVE_ARC4RANDOM 42243730Srwatson#include <openssl/rand.h> 43243730Srwatson#endif 44243730Srwatson 45243730Srwatson#ifndef HAVE_STRLCAT 46243730Srwatson#include <compat/strlcat.h> 47243730Srwatson#endif 48243730Srwatson 49243730Srwatson#include "auditdistd.h" 50243734Srwatson#include "pjdlog.h" 51243730Srwatson#include "subr.h" 52243730Srwatson 53243730Srwatsonint 54243730Srwatsonvsnprlcat(char *str, size_t size, const char *fmt, va_list ap) 55243730Srwatson{ 56243730Srwatson size_t len; 57243730Srwatson 58243730Srwatson len = strlen(str); 59243730Srwatson return (vsnprintf(str + len, size - len, fmt, ap)); 60243730Srwatson} 61243730Srwatson 62243730Srwatsonint 63243730Srwatsonsnprlcat(char *str, size_t size, const char *fmt, ...) 64243730Srwatson{ 65243730Srwatson va_list ap; 66243730Srwatson int result; 67243730Srwatson 68243730Srwatson va_start(ap, fmt); 69243730Srwatson result = vsnprlcat(str, size, fmt, ap); 70243730Srwatson va_end(ap); 71243730Srwatson return (result); 72243730Srwatson} 73243730Srwatson 74243730Srwatsonconst char * 75243730Srwatsonrole2str(int role) 76243730Srwatson{ 77243730Srwatson 78243730Srwatson switch (role) { 79243730Srwatson case ADIST_ROLE_SENDER: 80243730Srwatson return ("sender"); 81243730Srwatson case ADIST_ROLE_RECEIVER: 82243730Srwatson return ("receiver"); 83243730Srwatson } 84243730Srwatson return ("unknown"); 85243730Srwatson} 86243730Srwatson 87243730Srwatsonconst char * 88243730Srwatsonadist_errstr(int error) 89243730Srwatson{ 90243730Srwatson 91243730Srwatson switch (error) { 92243730Srwatson case ADIST_ERROR_WRONG_ORDER: 93243730Srwatson return ("wrong operations order"); 94243730Srwatson case ADIST_ERROR_INVALID_NAME: 95243730Srwatson return ("invalid trail file name"); 96243730Srwatson case ADIST_ERROR_OPEN_OLD: 97243730Srwatson return ("attempt to open an old trail file"); 98243730Srwatson case ADIST_ERROR_CREATE: 99243730Srwatson return ("creation of new trail file failed"); 100243730Srwatson case ADIST_ERROR_OPEN: 101243730Srwatson return ("open of existing trail file failed"); 102243730Srwatson case ADIST_ERROR_READ: 103243730Srwatson return ("read failed"); 104243730Srwatson case ADIST_ERROR_WRITE: 105243730Srwatson return ("write failed"); 106243730Srwatson case ADIST_ERROR_RENAME: 107243730Srwatson return ("rename of a trail file failed"); 108243730Srwatson default: 109243730Srwatson return ("unknown error"); 110243730Srwatson } 111243730Srwatson} 112243730Srwatson 113243730Srwatsonvoid 114243730Srwatsonadreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, 115243730Srwatson const char *fmt, ...) 116243730Srwatson{ 117243730Srwatson char msg[1024]; 118243730Srwatson va_list ap; 119243730Srwatson 120243730Srwatson va_start(ap, fmt); 121243730Srwatson (void)vsnprintf(msg, sizeof(msg), fmt, ap); 122243730Srwatson va_end(ap); 123243730Srwatson (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ", 124243730Srwatson (uintmax_t)adreq->adr_seq); 125243730Srwatson switch (adreq->adr_cmd) { 126243730Srwatson case ADIST_CMD_OPEN: 127243730Srwatson (void)snprlcat(msg, sizeof(msg), "OPEN(%s)", 128243730Srwatson adreq->adr_data); 129243730Srwatson break; 130243730Srwatson case ADIST_CMD_APPEND: 131243730Srwatson (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)", 132243730Srwatson (uintmax_t)adreq->adr_datasize); 133243730Srwatson break; 134243730Srwatson case ADIST_CMD_CLOSE: 135243730Srwatson (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)", 136243730Srwatson adreq->adr_data); 137243730Srwatson break; 138243730Srwatson case ADIST_CMD_KEEPALIVE: 139243730Srwatson (void)snprlcat(msg, sizeof(msg), "KEEPALIVE"); 140243730Srwatson break; 141243730Srwatson case ADIST_CMD_ERROR: 142243730Srwatson (void)snprlcat(msg, sizeof(msg), "ERROR"); 143243730Srwatson break; 144243730Srwatson default: 145243730Srwatson (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)", 146243730Srwatson adreq->adr_cmd); 147243730Srwatson break; 148243730Srwatson } 149243730Srwatson if (error != -1) 150243730Srwatson (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error)); 151243730Srwatson (void)strlcat(msg, ".", sizeof(msg)); 152243730Srwatson pjdlog_common(loglevel, debuglevel, -1, "%s", msg); 153243730Srwatson} 154243730Srwatson 155243730Srwatsonint 156243730Srwatsonadist_random(unsigned char *buf, size_t size) 157243730Srwatson{ 158243730Srwatson#ifdef HAVE_ARC4RANDOM_BUF 159243730Srwatson arc4random_buf(buf, size); 160243730Srwatson return (0); 161243730Srwatson#elif defined(HAVE_ARC4RANDOM) 162243730Srwatson uint32_t val; 163243730Srwatson 164243730Srwatson PJDLOG_ASSERT(size > 0); 165243730Srwatson PJDLOG_ASSERT((size % sizeof(val)) == 0); 166243730Srwatson 167243730Srwatson do { 168243730Srwatson val = arc4random(); 169243730Srwatson bcopy(&val, buf, sizeof(val)); 170243730Srwatson buf += sizeof(val); 171243730Srwatson size -= sizeof(val); 172243730Srwatson } while (size > 0); 173243730Srwatson 174243730Srwatson return (0); 175243730Srwatson#else 176243730Srwatson if (RAND_bytes(buf, (int)size) == 0) 177243730Srwatson return (-1); 178243730Srwatson return (0); 179243730Srwatson#endif 180243730Srwatson} 181243730Srwatson 182243730Srwatsonstatic int wait_for_dir_kq = -1; 183243730Srwatsonstatic int wait_for_file_kq = -1; 184243730Srwatson 185243730Srwatsonint 186243730Srwatsonwait_for_dir_init(int fd) 187243730Srwatson{ 188243730Srwatson#ifdef HAVE_KQUEUE 189243730Srwatson struct kevent ev; 190243730Srwatson int error, kq; 191243730Srwatson 192243730Srwatson PJDLOG_ASSERT(wait_for_dir_kq == -1); 193243730Srwatson#endif 194243730Srwatson 195243730Srwatson PJDLOG_ASSERT(fd != -1); 196243730Srwatson 197243730Srwatson#ifdef HAVE_KQUEUE 198243730Srwatson kq = kqueue(); 199243730Srwatson if (kq == -1) { 200243730Srwatson pjdlog_errno(LOG_WARNING, "kqueue() failed"); 201243730Srwatson return (-1); 202243730Srwatson } 203243730Srwatson EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 204243730Srwatson NOTE_WRITE, 0, 0); 205243730Srwatson if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { 206243730Srwatson error = errno; 207243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 208243730Srwatson (void)close(kq); 209243730Srwatson errno = error; 210243730Srwatson return (-1); 211243730Srwatson } 212243730Srwatson wait_for_dir_kq = kq; 213243730Srwatson#endif 214243730Srwatson 215243730Srwatson return (0); 216243730Srwatson} 217243730Srwatson 218243730Srwatsonint 219243730Srwatsonwait_for_file_init(int fd) 220243730Srwatson{ 221243730Srwatson#ifdef HAVE_KQUEUE 222243730Srwatson struct kevent ev[2]; 223243730Srwatson int error, kq; 224243730Srwatson#endif 225243730Srwatson 226243730Srwatson PJDLOG_ASSERT(fd != -1); 227243730Srwatson 228243730Srwatson#ifdef HAVE_KQUEUE 229271844Spjd if (wait_for_file_kq != -1) { 230271844Spjd close(wait_for_file_kq); 231271844Spjd wait_for_file_kq = -1; 232271844Spjd } 233271844Spjd 234243730Srwatson kq = kqueue(); 235243730Srwatson if (kq == -1) { 236243730Srwatson pjdlog_errno(LOG_WARNING, "kqueue() failed"); 237243730Srwatson return (-1); 238243730Srwatson } 239243730Srwatson EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 240243730Srwatson NOTE_RENAME, 0, 0); 241243730Srwatson EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 242243730Srwatson 0, 0, 0); 243243730Srwatson if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) { 244243730Srwatson error = errno; 245243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 246243730Srwatson (void)close(kq); 247243730Srwatson errno = error; 248243730Srwatson return (-1); 249243730Srwatson } 250243730Srwatson wait_for_file_kq = kq; 251243730Srwatson#endif 252243730Srwatson 253243730Srwatson return (0); 254243730Srwatson} 255243730Srwatson 256243730Srwatson/* 257243730Srwatson * Wait for new file to appear in directory. 258243730Srwatson */ 259243730Srwatsonvoid 260243730Srwatsonwait_for_dir(void) 261243730Srwatson{ 262243730Srwatson#ifdef HAVE_KQUEUE 263243730Srwatson struct kevent ev; 264243730Srwatson#endif 265243730Srwatson 266243730Srwatson if (wait_for_dir_kq == -1) { 267243730Srwatson sleep(1); 268243730Srwatson return; 269243730Srwatson } 270243730Srwatson 271243730Srwatson#ifdef HAVE_KQUEUE 272243730Srwatson PJDLOG_ASSERT(wait_for_dir_kq != -1); 273243730Srwatson 274243730Srwatson if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) { 275243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 276243730Srwatson sleep(1); 277243730Srwatson } 278243730Srwatson#endif 279243730Srwatson} 280243730Srwatson 281243730Srwatson/* 282243730Srwatson * Wait for file growth or rename. 283243730Srwatson */ 284243730Srwatsonvoid 285243730Srwatsonwait_for_file(void) 286243730Srwatson{ 287243730Srwatson#ifdef HAVE_KQUEUE 288243730Srwatson struct kevent ev[2]; 289243730Srwatson#endif 290243730Srwatson 291243730Srwatson if (wait_for_file_kq == -1) { 292243730Srwatson sleep(1); 293243730Srwatson return; 294243730Srwatson } 295243730Srwatson 296243730Srwatson#ifdef HAVE_KQUEUE 297243730Srwatson PJDLOG_ASSERT(wait_for_file_kq != -1); 298243730Srwatson 299243730Srwatson if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) { 300243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 301243730Srwatson sleep(1); 302243730Srwatson } 303243730Srwatson#endif 304243730Srwatson} 305