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