xref: /openbsd/usr.sbin/relayd/log.c (revision cecf84d4)
1 /*	$OpenBSD: log.c,v 1.27 2015/01/22 17:42:09 reyk 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/socket.h>
21 #include <sys/time.h>
22 
23 #include <errno.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <syslog.h>
29 #include <netdb.h>
30 #include <ctype.h>
31 #include <time.h>
32 
33 #include "relayd.h"
34 
35 int	 debug;
36 int	 verbose;
37 
38 void	 vlog(int, const char *, va_list)
39 	    __attribute__((__format__ (printf, 2, 0)));
40 void	 logit(int, const char *, ...)
41 	    __attribute__((__format__ (printf, 2, 3)));
42 
43 void
44 log_init(int n_debug)
45 {
46 	extern char	*__progname;
47 
48 	debug = n_debug;
49 	verbose = n_debug;
50 
51 	if (!debug)
52 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
53 
54 	tzset();
55 }
56 
57 void
58 log_verbose(int v)
59 {
60 	verbose = v;
61 }
62 
63 void
64 logit(int pri, const char *fmt, ...)
65 {
66 	va_list	ap;
67 
68 	va_start(ap, fmt);
69 	vlog(pri, fmt, ap);
70 	va_end(ap);
71 }
72 
73 void
74 vlog(int pri, const char *fmt, va_list ap)
75 {
76 	char	*nfmt;
77 
78 	if (debug) {
79 		/* best effort in out of mem situations */
80 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
81 			vfprintf(stderr, fmt, ap);
82 			fprintf(stderr, "\n");
83 		} else {
84 			vfprintf(stderr, nfmt, ap);
85 			free(nfmt);
86 		}
87 		fflush(stderr);
88 	} else
89 		vsyslog(pri, fmt, ap);
90 }
91 
92 
93 void
94 log_warn(const char *emsg, ...)
95 {
96 	char	*nfmt;
97 	va_list	 ap;
98 
99 	/* best effort to even work in out of memory situations */
100 	if (emsg == NULL)
101 		logit(LOG_CRIT, "%s", strerror(errno));
102 	else {
103 		va_start(ap, emsg);
104 
105 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
106 			/* we tried it... */
107 			vlog(LOG_CRIT, emsg, ap);
108 			logit(LOG_CRIT, "%s", strerror(errno));
109 		} else {
110 			vlog(LOG_CRIT, nfmt, ap);
111 			free(nfmt);
112 		}
113 		va_end(ap);
114 	}
115 }
116 
117 void
118 log_warnx(const char *emsg, ...)
119 {
120 	va_list	 ap;
121 
122 	va_start(ap, emsg);
123 	vlog(LOG_CRIT, emsg, ap);
124 	va_end(ap);
125 }
126 
127 void
128 log_info(const char *emsg, ...)
129 {
130 	va_list	 ap;
131 
132 	va_start(ap, emsg);
133 	vlog(LOG_INFO, emsg, ap);
134 	va_end(ap);
135 }
136 
137 void
138 log_debug(const char *emsg, ...)
139 {
140 	va_list	 ap;
141 
142 	if (verbose > 1) {
143 		va_start(ap, emsg);
144 		vlog(LOG_DEBUG, emsg, ap);
145 		va_end(ap);
146 	}
147 }
148 
149 void
150 fatal(const char *emsg)
151 {
152 	if (emsg == NULL)
153 		logit(LOG_CRIT, "fatal: %s", strerror(errno));
154 	else
155 		if (errno)
156 			logit(LOG_CRIT, "fatal: %s: %s",
157 			    emsg, strerror(errno));
158 		else
159 			logit(LOG_CRIT, "fatal: %s", emsg);
160 
161 	exit(1);
162 }
163 
164 void
165 fatalx(const char *emsg)
166 {
167 	errno = 0;
168 	fatal(emsg);
169 }
170 
171 const char *
172 host_error(enum host_error he)
173 {
174 	switch (he) {
175 	case HCE_NONE:
176 		return ("none");
177 		break;
178 	case HCE_ABORT:
179 		return ("aborted");
180 		break;
181 	case HCE_INTERVAL_TIMEOUT:
182 		return ("interval timeout");
183 		break;
184 	case HCE_ICMP_OK:
185 		return ("icmp ok");
186 		break;
187 	case HCE_ICMP_READ_TIMEOUT:
188 		return ("icmp read timeout");
189 		break;
190 	case HCE_ICMP_WRITE_TIMEOUT:
191 		return ("icmp write timeout");
192 		break;
193 	case HCE_TCP_SOCKET_ERROR:
194 		return ("tcp socket error");
195 		break;
196 	case HCE_TCP_SOCKET_LIMIT:
197 		return ("tcp socket limit");
198 		break;
199 	case HCE_TCP_SOCKET_OPTION:
200 		return ("tcp socket option");
201 		break;
202 	case HCE_TCP_CONNECT_FAIL:
203 		return ("tcp connect failed");
204 		break;
205 	case HCE_TCP_CONNECT_TIMEOUT:
206 		return ("tcp connect timeout");
207 		break;
208 	case HCE_TCP_CONNECT_OK:
209 		return ("tcp connect ok");
210 		break;
211 	case HCE_TCP_WRITE_TIMEOUT:
212 		return ("tcp write timeout");
213 		break;
214 	case HCE_TCP_WRITE_FAIL:
215 		return ("tcp write failed");
216 		break;
217 	case HCE_TCP_READ_TIMEOUT:
218 		return ("tcp read timeout");
219 		break;
220 	case HCE_TCP_READ_FAIL:
221 		return ("tcp read failed");
222 		break;
223 	case HCE_SCRIPT_OK:
224 		return ("script ok");
225 		break;
226 	case HCE_SCRIPT_FAIL:
227 		return ("script failed");
228 		break;
229 	case HCE_TLS_CONNECT_OK:
230 		return ("tls connect ok");
231 		break;
232 	case HCE_TLS_CONNECT_FAIL:
233 		return ("tls connect failed");
234 		break;
235 	case HCE_TLS_CONNECT_TIMEOUT:
236 		return ("tls connect timeout");
237 		break;
238 	case HCE_TLS_CONNECT_ERROR:
239 		return ("tls connect error");
240 		break;
241 	case HCE_TLS_READ_TIMEOUT:
242 		return ("tls read timeout");
243 		break;
244 	case HCE_TLS_WRITE_TIMEOUT:
245 		return ("tls write timeout");
246 		break;
247 	case HCE_TLS_READ_ERROR:
248 		return ("tls read error");
249 		break;
250 	case HCE_TLS_WRITE_ERROR:
251 		return ("tls write error");
252 		break;
253 	case HCE_SEND_EXPECT_FAIL:
254 		return ("send/expect failed");
255 		break;
256 	case HCE_SEND_EXPECT_OK:
257 		return ("send/expect ok");
258 		break;
259 	case HCE_HTTP_CODE_ERROR:
260 		return ("http code malformed");
261 		break;
262 	case HCE_HTTP_CODE_FAIL:
263 		return ("http code mismatch");
264 		break;
265 	case HCE_HTTP_CODE_OK:
266 		return ("http code ok");
267 		break;
268 	case HCE_HTTP_DIGEST_ERROR:
269 		return ("http digest malformed");
270 		break;
271 	case HCE_HTTP_DIGEST_FAIL:
272 		return ("http digest mismatch");
273 		break;
274 	case HCE_HTTP_DIGEST_OK:
275 		return ("http digest ok");
276 		break;
277 	}
278 	/* NOTREACHED */
279 	return ("invalid");
280 }
281 
282 const char *
283 host_status(enum host_status status)
284 {
285 	switch (status) {
286 	case HOST_DOWN:
287 		return ("down");
288 	case HOST_UNKNOWN:
289 		return ("unknown");
290 	case HOST_UP:
291 		return ("up");
292 	};
293 	/* NOTREACHED */
294 	return ("invalid");
295 }
296 
297 const char *
298 table_check(enum table_check check)
299 {
300 	switch (check) {
301 	case CHECK_NOCHECK:
302 		return ("none");
303 	case CHECK_ICMP:
304 		return ("icmp");
305 	case CHECK_TCP:
306 		return ("tcp");
307 	case CHECK_HTTP_CODE:
308 		return ("http code");
309 	case CHECK_HTTP_DIGEST:
310 		return ("http digest");
311 	case CHECK_SEND_EXPECT:
312 		return ("send expect");
313 	case CHECK_SCRIPT:
314 		return ("script");
315 	};
316 	/* NOTREACHED */
317 	return ("invalid");
318 }
319 
320 const char *
321 print_availability(u_long cnt, u_long up)
322 {
323 	static char buf[BUFSIZ];
324 
325 	if (cnt == 0)
326 		return ("");
327 	bzero(buf, sizeof(buf));
328 	snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100);
329 	return (buf);
330 }
331 
332 const char *
333 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
334 {
335 	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
336 	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
337 		buf[0] = '\0';
338 		return (NULL);
339 	}
340 	return (buf);
341 }
342 
343 const char *
344 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
345 {
346 	struct timeval		tv;
347 	u_long			h, sec, min;
348 
349 	timerclear(&tv);
350 	timersub(a, b, &tv);
351 	sec = tv.tv_sec % 60;
352 	min = tv.tv_sec / 60 % 60;
353 	h = tv.tv_sec / 60 / 60;
354 
355 	snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
356 	return (buf);
357 }
358 
359 const char *
360 printb_flags(const u_int32_t v, const char *bits)
361 {
362 	static char	 buf[2][BUFSIZ];
363 	static int	 idx = 0;
364 	int		 i, any = 0;
365 	char		 c, *p, *r;
366 
367 	p = r = buf[++idx % 2];
368 	bzero(p, BUFSIZ);
369 
370 	if (bits) {
371 		bits++;
372 		while ((i = *bits++)) {
373 			if (v & (1 << (i - 1))) {
374 				if (any) {
375 					*p++ = ',';
376 					*p++ = ' ';
377 				}
378 				any = 1;
379 				for (; (c = *bits) > 32; bits++) {
380 					if (c == '_')
381 						*p++ = ' ';
382 					else
383 						*p++ = tolower((u_char)c);
384 				}
385 			} else
386 				for (; *bits > 32; bits++)
387 					;
388 		}
389 	}
390 
391 	return (r);
392 }
393 
394 void
395 getmonotime(struct timeval *tv)
396 {
397 	struct timespec	 ts;
398 
399 	if (clock_gettime(CLOCK_MONOTONIC, &ts))
400 		fatal("clock_gettime");
401 
402 	TIMESPEC_TO_TIMEVAL(tv, &ts);
403 }
404