xref: /openbsd-src/usr.sbin/relayd/log.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: log.c,v 1.20 2013/11/27 18:38:39 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/tree.h>
23 
24 #include <net/if.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/in.h>
27 #include <netinet/ip.h>
28 #include <arpa/inet.h>
29 
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <event.h>
37 #include <netdb.h>
38 #include <ctype.h>
39 
40 #include <openssl/ssl.h>
41 
42 #include "relayd.h"
43 
44 int	 debug;
45 int	 verbose;
46 
47 void	 vlog(int, const char *, va_list)
48 	    __attribute__((__format__ (printf, 2, 0)));
49 void	 logit(int, const char *, ...)
50 	    __attribute__((__format__ (printf, 2, 3)));
51 
52 void
53 log_init(int n_debug)
54 {
55 	extern char	*__progname;
56 
57 	debug = n_debug;
58 	verbose = n_debug;
59 
60 	if (!debug)
61 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
62 
63 	tzset();
64 }
65 
66 void
67 log_verbose(int v)
68 {
69 	verbose = v;
70 }
71 
72 void
73 logit(int pri, const char *fmt, ...)
74 {
75 	va_list	ap;
76 
77 	va_start(ap, fmt);
78 	vlog(pri, fmt, ap);
79 	va_end(ap);
80 }
81 
82 void
83 vlog(int pri, const char *fmt, va_list ap)
84 {
85 	char	*nfmt;
86 
87 	if (debug) {
88 		/* best effort in out of mem situations */
89 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
90 			vfprintf(stderr, fmt, ap);
91 			fprintf(stderr, "\n");
92 		} else {
93 			vfprintf(stderr, nfmt, ap);
94 			free(nfmt);
95 		}
96 		fflush(stderr);
97 	} else
98 		vsyslog(pri, fmt, ap);
99 }
100 
101 
102 void
103 log_warn(const char *emsg, ...)
104 {
105 	char	*nfmt;
106 	va_list	 ap;
107 
108 	/* best effort to even work in out of memory situations */
109 	if (emsg == NULL)
110 		logit(LOG_CRIT, "%s", strerror(errno));
111 	else {
112 		va_start(ap, emsg);
113 
114 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
115 			/* we tried it... */
116 			vlog(LOG_CRIT, emsg, ap);
117 			logit(LOG_CRIT, "%s", strerror(errno));
118 		} else {
119 			vlog(LOG_CRIT, nfmt, ap);
120 			free(nfmt);
121 		}
122 		va_end(ap);
123 	}
124 }
125 
126 void
127 log_warnx(const char *emsg, ...)
128 {
129 	va_list	 ap;
130 
131 	va_start(ap, emsg);
132 	vlog(LOG_CRIT, emsg, ap);
133 	va_end(ap);
134 }
135 
136 void
137 log_info(const char *emsg, ...)
138 {
139 	va_list	 ap;
140 
141 	va_start(ap, emsg);
142 	vlog(LOG_INFO, emsg, ap);
143 	va_end(ap);
144 }
145 
146 void
147 log_debug(const char *emsg, ...)
148 {
149 	va_list	 ap;
150 
151 	if (verbose > 1) {
152 		va_start(ap, emsg);
153 		vlog(LOG_DEBUG, emsg, ap);
154 		va_end(ap);
155 	}
156 }
157 
158 void
159 fatal(const char *emsg)
160 {
161 	if (emsg == NULL)
162 		logit(LOG_CRIT, "fatal: %s", strerror(errno));
163 	else
164 		if (errno)
165 			logit(LOG_CRIT, "fatal: %s: %s",
166 			    emsg, strerror(errno));
167 		else
168 			logit(LOG_CRIT, "fatal: %s", emsg);
169 
170 	exit(1);
171 }
172 
173 void
174 fatalx(const char *emsg)
175 {
176 	errno = 0;
177 	fatal(emsg);
178 }
179 
180 const char *
181 host_error(enum host_error he)
182 {
183 	switch (he) {
184 	case HCE_NONE:
185 		return ("none");
186 		break;
187 	case HCE_ABORT:
188 		return ("aborted");
189 		break;
190 	case HCE_INTERVAL_TIMEOUT:
191 		return ("interval timeout");
192 		break;
193 	case HCE_ICMP_OK:
194 		return ("icmp ok");
195 		break;
196 	case HCE_ICMP_READ_TIMEOUT:
197 		return ("icmp read timeout");
198 		break;
199 	case HCE_ICMP_WRITE_TIMEOUT:
200 		return ("icmp write timeout");
201 		break;
202 	case HCE_TCP_SOCKET_ERROR:
203 		return ("tcp socket error");
204 		break;
205 	case HCE_TCP_SOCKET_LIMIT:
206 		return ("tcp socket limit");
207 		break;
208 	case HCE_TCP_SOCKET_OPTION:
209 		return ("tcp socket option");
210 		break;
211 	case HCE_TCP_CONNECT_FAIL:
212 		return ("tcp connect failed");
213 		break;
214 	case HCE_TCP_CONNECT_TIMEOUT:
215 		return ("tcp connect timeout");
216 		break;
217 	case HCE_TCP_CONNECT_OK:
218 		return ("tcp connect ok");
219 		break;
220 	case HCE_TCP_WRITE_TIMEOUT:
221 		return ("tcp write timeout");
222 		break;
223 	case HCE_TCP_WRITE_FAIL:
224 		return ("tcp write failed");
225 		break;
226 	case HCE_TCP_READ_TIMEOUT:
227 		return ("tcp read timeout");
228 		break;
229 	case HCE_TCP_READ_FAIL:
230 		return ("tcp read failed");
231 		break;
232 	case HCE_SCRIPT_OK:
233 		return ("script ok");
234 		break;
235 	case HCE_SCRIPT_FAIL:
236 		return ("script failed");
237 		break;
238 	case HCE_SSL_CONNECT_OK:
239 		return ("ssl connect ok");
240 		break;
241 	case HCE_SSL_CONNECT_FAIL:
242 		return ("ssl connect failed");
243 		break;
244 	case HCE_SSL_CONNECT_TIMEOUT:
245 		return ("ssl connect timeout");
246 		break;
247 	case HCE_SSL_CONNECT_ERROR:
248 		return ("ssl connect error");
249 		break;
250 	case HCE_SSL_READ_TIMEOUT:
251 		return ("ssl read timeout");
252 		break;
253 	case HCE_SSL_WRITE_TIMEOUT:
254 		return ("ssl write timeout");
255 		break;
256 	case HCE_SSL_READ_ERROR:
257 		return ("ssl read error");
258 		break;
259 	case HCE_SSL_WRITE_ERROR:
260 		return ("ssl write error");
261 		break;
262 	case HCE_SEND_EXPECT_FAIL:
263 		return ("send/expect failed");
264 		break;
265 	case HCE_SEND_EXPECT_OK:
266 		return ("send/expect ok");
267 		break;
268 	case HCE_HTTP_CODE_ERROR:
269 		return ("http code malformed");
270 		break;
271 	case HCE_HTTP_CODE_FAIL:
272 		return ("http code mismatch");
273 		break;
274 	case HCE_HTTP_CODE_OK:
275 		return ("http code ok");
276 		break;
277 	case HCE_HTTP_DIGEST_ERROR:
278 		return ("http digest malformed");
279 		break;
280 	case HCE_HTTP_DIGEST_FAIL:
281 		return ("http digest mismatch");
282 		break;
283 	case HCE_HTTP_DIGEST_OK:
284 		return ("http digest ok");
285 		break;
286 	}
287 	/* NOTREACHED */
288 	return ("invalid");
289 }
290 
291 const char *
292 host_status(enum host_status status)
293 {
294 	switch (status) {
295 	case HOST_DOWN:
296 		return ("down");
297 	case HOST_UNKNOWN:
298 		return ("unknown");
299 	case HOST_UP:
300 		return ("up");
301 	};
302 	/* NOTREACHED */
303 	return ("invalid");
304 }
305 
306 const char *
307 table_check(enum table_check check)
308 {
309 	switch (check) {
310 	case CHECK_NOCHECK:
311 		return ("none");
312 	case CHECK_ICMP:
313 		return ("icmp");
314 	case CHECK_TCP:
315 		return ("tcp");
316 	case CHECK_HTTP_CODE:
317 		return ("http code");
318 	case CHECK_HTTP_DIGEST:
319 		return ("http digest");
320 	case CHECK_SEND_EXPECT:
321 		return ("send expect");
322 	case CHECK_SCRIPT:
323 		return ("script");
324 	};
325 	/* NOTREACHED */
326 	return ("invalid");
327 }
328 
329 const char *
330 print_availability(u_long cnt, u_long up)
331 {
332 	static char buf[BUFSIZ];
333 
334 	if (cnt == 0)
335 		return ("");
336 	bzero(buf, sizeof(buf));
337 	snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100);
338 	return (buf);
339 }
340 
341 const char *
342 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
343 {
344 	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
345 	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
346 		buf[0] = '\0';
347 		return (NULL);
348 	}
349 	return (buf);
350 }
351 
352 const char *
353 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
354 {
355 	struct timeval		tv;
356 	u_long			h, sec, min;
357 
358 	timerclear(&tv);
359 	timersub(a, b, &tv);
360 	sec = tv.tv_sec % 60;
361 	min = tv.tv_sec / 60 % 60;
362 	h = tv.tv_sec / 60 / 60;
363 
364 	snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
365 	return (buf);
366 }
367 
368 const char *
369 print_httperror(u_int code)
370 {
371 	u_int			 i;
372 	struct {
373 		u_int		 ht_code;
374 		const char	*ht_err;
375 	}			 httperr[] = {
376 		{ 100, "Continue" },
377 		{ 101, "Switching Protocols" },
378 		{ 200, "OK" },
379 		{ 201, "Created" },
380 		{ 202, "Accepted" },
381 		{ 203, "Non-Authorative Information" },
382 		{ 204, "No Content" },
383 		{ 205, "Reset Content" },
384 		{ 206, "Partial Content" },
385 		{ 300, "Multiple Choices" },
386 		{ 301, "Moved Permanently" },
387 		{ 302, "Moved Temporarily" },
388 		{ 303, "See Other" },
389 		{ 304, "Not Modified" },
390 		{ 307, "Temporary Redirect" },
391 		{ 400, "Bad Request" },
392 		{ 401, "Unauthorized" },
393 		{ 402, "Payment Required" },
394 		{ 403, "Forbidden" },
395 		{ 404, "Not Found" },
396 		{ 405, "Method Not Allowed" },
397 		{ 406, "Not Acceptable" },
398 		{ 407, "Proxy Authentication Required" },
399 		{ 408, "Request Timeout" },
400 		{ 409, "Conflict" },
401 		{ 410, "Gone" },
402 		{ 411, "Length Required" },
403 		{ 412, "Precondition Failed" },
404 		{ 413, "Request Entity Too Large" },
405 		{ 414, "Request-URL Too Long" },
406 		{ 415, "Unsupported Media Type" },
407 		{ 416, "Requested Range Not Satisfiable" },
408 		{ 417, "Expectation Failed" },
409 		{ 500, "Internal Server Error" },
410 		{ 501, "Not Implemented" },
411 		{ 502, "Bad Gateway" },
412 		{ 503, "Service Unavailable" },
413 		{ 504, "Gateway Timeout" },
414 		{ 505, "HTTP Version Not Supported" },
415 		{ 0 }
416 	};
417 
418 	for (i = 0; httperr[i].ht_code != 0; i++)
419 		if (httperr[i].ht_code == code)
420 			return (httperr[i].ht_err);
421 	return ("Unknown Error");
422 }
423 
424 const char *
425 printb_flags(const u_int32_t v, const char *bits)
426 {
427 	static char	 buf[2][BUFSIZ];
428 	static int	 idx = 0;
429 	int		 i, any = 0;
430 	char		 c, *p, *r;
431 
432 	p = r = buf[++idx % 2];
433 	bzero(p, BUFSIZ);
434 
435 	if (bits) {
436 		bits++;
437 		while ((i = *bits++)) {
438 			if (v & (1 << (i - 1))) {
439 				if (any) {
440 					*p++ = ',';
441 					*p++ = ' ';
442 				}
443 				any = 1;
444 				for (; (c = *bits) > 32; bits++) {
445 					if (c == '_')
446 						*p++ = ' ';
447 					else
448 						*p++ = tolower((unsigned char)c);
449 				}
450 			} else
451 				for (; *bits > 32; bits++)
452 					;
453 		}
454 	}
455 
456 	return (r);
457 }
458 
459 void
460 getmonotime(struct timeval *tv)
461 {
462 	struct timespec	 ts;
463 
464 	if (clock_gettime(CLOCK_MONOTONIC, &ts))
465 		fatal("clock_gettime");
466 
467 	TIMESPEC_TO_TIMEVAL(tv, &ts);
468 }
469