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