xref: /openbsd/usr.sbin/relayd/log.c (revision 404b540a)
1 /*	$OpenBSD: log.c,v 1.14 2008/12/05 16:37:55 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/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 
39 #include <openssl/ssl.h>
40 
41 #include "relayd.h"
42 
43 int	 debug;
44 
45 void	 vlog(int, const char *, va_list);
46 void	 logit(int, const char *, ...);
47 
48 void
49 log_init(int n_debug)
50 {
51 	extern char	*__progname;
52 
53 	debug = n_debug;
54 
55 	if (!debug)
56 		openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
57 
58 	tzset();
59 }
60 
61 void
62 logit(int pri, const char *fmt, ...)
63 {
64 	va_list	ap;
65 
66 	va_start(ap, fmt);
67 	vlog(pri, fmt, ap);
68 	va_end(ap);
69 }
70 
71 void
72 vlog(int pri, const char *fmt, va_list ap)
73 {
74 	char	*nfmt;
75 
76 	if (debug) {
77 		/* best effort in out of mem situations */
78 		if (asprintf(&nfmt, "%s\n", fmt) == -1) {
79 			vfprintf(stderr, fmt, ap);
80 			fprintf(stderr, "\n");
81 		} else {
82 			vfprintf(stderr, nfmt, ap);
83 			free(nfmt);
84 		}
85 		fflush(stderr);
86 	} else
87 		vsyslog(pri, fmt, ap);
88 }
89 
90 
91 void
92 log_warn(const char *emsg, ...)
93 {
94 	char	*nfmt;
95 	va_list	 ap;
96 
97 	/* best effort to even work in out of memory situations */
98 	if (emsg == NULL)
99 		logit(LOG_CRIT, "%s", strerror(errno));
100 	else {
101 		va_start(ap, emsg);
102 
103 		if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
104 			/* we tried it... */
105 			vlog(LOG_CRIT, emsg, ap);
106 			logit(LOG_CRIT, "%s", strerror(errno));
107 		} else {
108 			vlog(LOG_CRIT, nfmt, ap);
109 			free(nfmt);
110 		}
111 		va_end(ap);
112 	}
113 }
114 
115 void
116 log_warnx(const char *emsg, ...)
117 {
118 	va_list	 ap;
119 
120 	va_start(ap, emsg);
121 	vlog(LOG_CRIT, emsg, ap);
122 	va_end(ap);
123 }
124 
125 void
126 log_info(const char *emsg, ...)
127 {
128 	va_list	 ap;
129 
130 	va_start(ap, emsg);
131 	vlog(LOG_INFO, emsg, ap);
132 	va_end(ap);
133 }
134 
135 void
136 log_debug(const char *emsg, ...)
137 {
138 	va_list	 ap;
139 
140 	if (debug > 1) {
141 		va_start(ap, emsg);
142 		vlog(LOG_DEBUG, emsg, ap);
143 		va_end(ap);
144 	}
145 }
146 
147 void
148 fatal(const char *emsg)
149 {
150 	if (emsg == NULL)
151 		logit(LOG_CRIT, "fatal: %s", strerror(errno));
152 	else
153 		if (errno)
154 			logit(LOG_CRIT, "fatal: %s: %s",
155 			    emsg, strerror(errno));
156 		else
157 			logit(LOG_CRIT, "fatal: %s", emsg);
158 
159 	exit(1);
160 }
161 
162 void
163 fatalx(const char *emsg)
164 {
165 	errno = 0;
166 	fatal(emsg);
167 }
168 
169 const char *
170 host_error(enum host_error he)
171 {
172 	switch (he) {
173 	case HCE_NONE:
174 		return ("none");
175 		break;
176 	case HCE_ABORT:
177 		return ("aborted");
178 		break;
179 	case HCE_INTERVAL_TIMEOUT:
180 		return ("interval timeout");
181 		break;
182 	case HCE_ICMP_OK:
183 		return ("icmp ok");
184 		break;
185 	case HCE_ICMP_READ_TIMEOUT:
186 		return ("icmp read timeout");
187 		break;
188 	case HCE_ICMP_WRITE_TIMEOUT:
189 		return ("icmp write timeout");
190 		break;
191 	case HCE_TCP_CONNECT_ERROR:
192 		return ("tcp connect error");
193 		break;
194 	case HCE_TCP_CONNECT_FAIL:
195 		return ("tcp connect failed");
196 		break;
197 	case HCE_TCP_CONNECT_TIMEOUT:
198 		return ("tcp connect timeout");
199 		break;
200 	case HCE_TCP_CONNECT_OK:
201 		return ("tcp connect ok");
202 		break;
203 	case HCE_TCP_WRITE_TIMEOUT:
204 		return ("tcp write timeout");
205 		break;
206 	case HCE_TCP_WRITE_FAIL:
207 		return ("tcp write failed");
208 		break;
209 	case HCE_TCP_READ_TIMEOUT:
210 		return ("tcp read timeout");
211 		break;
212 	case HCE_TCP_READ_FAIL:
213 		return ("tcp read failed");
214 		break;
215 	case HCE_SCRIPT_OK:
216 		return ("script ok");
217 		break;
218 	case HCE_SCRIPT_FAIL:
219 		return ("script failed");
220 		break;
221 	case HCE_SSL_CONNECT_OK:
222 		return ("ssl connect ok");
223 		break;
224 	case HCE_SSL_CONNECT_FAIL:
225 		return ("ssl connect failed");
226 		break;
227 	case HCE_SSL_CONNECT_TIMEOUT:
228 		return ("ssl connect timeout");
229 		break;
230 	case HCE_SSL_CONNECT_ERROR:
231 		return ("ssl connect error");
232 		break;
233 	case HCE_SSL_READ_TIMEOUT:
234 		return ("ssl read timeout");
235 		break;
236 	case HCE_SSL_WRITE_TIMEOUT:
237 		return ("ssl write timeout");
238 		break;
239 	case HCE_SSL_READ_ERROR:
240 		return ("ssl read error");
241 		break;
242 	case HCE_SSL_WRITE_ERROR:
243 		return ("ssl write error");
244 		break;
245 	case HCE_SEND_EXPECT_FAIL:
246 		return ("send/expect failed");
247 		break;
248 	case HCE_SEND_EXPECT_OK:
249 		return ("send/expect ok");
250 		break;
251 	case HCE_HTTP_CODE_ERROR:
252 		return ("http code malformed");
253 		break;
254 	case HCE_HTTP_CODE_FAIL:
255 		return ("http code mismatch");
256 		break;
257 	case HCE_HTTP_CODE_OK:
258 		return ("http code ok");
259 		break;
260 	case HCE_HTTP_DIGEST_ERROR:
261 		return ("http digest malformed");
262 		break;
263 	case HCE_HTTP_DIGEST_FAIL:
264 		return ("http digest mismatch");
265 		break;
266 	case HCE_HTTP_DIGEST_OK:
267 		return ("http digest ok");
268 		break;
269 	}
270 	/* NOTREACHED */
271 	return ("invalid");
272 }
273 
274 const char *
275 host_status(enum host_status status)
276 {
277 	switch (status) {
278 	case HOST_DOWN:
279 		return ("down");
280 	case HOST_UNKNOWN:
281 		return ("unknown");
282 	case HOST_UP:
283 		return ("up");
284 	};
285 	/* NOTREACHED */
286 	return ("invalid");
287 }
288 
289 const char *
290 table_check(enum table_check check)
291 {
292 	switch (check) {
293 	case CHECK_NOCHECK:
294 		return ("none");
295 	case CHECK_ICMP:
296 		return ("icmp");
297 	case CHECK_TCP:
298 		return ("tcp");
299 	case CHECK_HTTP_CODE:
300 		return ("http code");
301 	case CHECK_HTTP_DIGEST:
302 		return ("http digest");
303 	case CHECK_SEND_EXPECT:
304 		return ("send expect");
305 	case CHECK_SCRIPT:
306 		return ("script");
307 	};
308 	/* NOTREACHED */
309 	return ("invalid");
310 }
311 
312 const char *
313 print_availability(u_long cnt, u_long up)
314 {
315 	static char buf[BUFSIZ];
316 
317 	if (cnt == 0)
318 		return ("");
319 	bzero(buf, sizeof(buf));
320 	snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100);
321 	return (buf);
322 }
323 
324 const char *
325 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
326 {
327 	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
328 	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
329 		buf[0] = '\0';
330 		return (NULL);
331 	}
332 	return (buf);
333 }
334 
335 const char *
336 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
337 {
338 	struct timeval		tv;
339 	u_long			h, sec, min;
340 
341 	timerclear(&tv);
342 	timersub(a, b, &tv);
343 	sec = tv.tv_sec % 60;
344 	min = tv.tv_sec / 60 % 60;
345 	h = tv.tv_sec / 60 / 60;
346 
347 	snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
348 	return (buf);
349 }
350 
351 const char *
352 print_httperror(u_int code)
353 {
354 	u_int			 i;
355 	struct {
356 		u_int		 ht_code;
357 		const char	*ht_err;
358 	}			 httperr[] = {
359 		{ 100, "Continue" },
360 		{ 101, "Switching Protocols" },
361 		{ 200, "OK" },
362 		{ 201, "Created" },
363 		{ 202, "Accepted" },
364 		{ 203, "Non-Authorative Information" },
365 		{ 204, "No Content" },
366 		{ 205, "Reset Content" },
367 		{ 206, "Partial Content" },
368 		{ 300, "Multiple Choices" },
369 		{ 301, "Moved Permanently" },
370 		{ 302, "Moved Temporarily" },
371 		{ 303, "See Other" },
372 		{ 304, "Not Modified" },
373 		{ 307, "Temporary Redirect" },
374 		{ 400, "Bad Request" },
375 		{ 401, "Unauthorized" },
376 		{ 402, "Payment Required" },
377 		{ 403, "Forbidden" },
378 		{ 404, "Not Found" },
379 		{ 405, "Method Not Allowed" },
380 		{ 406, "Not Acceptable" },
381 		{ 407, "Proxy Authentication Required" },
382 		{ 408, "Request Timeout" },
383 		{ 409, "Conflict" },
384 		{ 410, "Gone" },
385 		{ 411, "Length Required" },
386 		{ 412, "Precondition Failed" },
387 		{ 413, "Request Entity Too Large" },
388 		{ 414, "Request-URL Too Long" },
389 		{ 415, "Unsupported Media Type" },
390 		{ 416, "Requested Range Not Satisfiable" },
391 		{ 417, "Expectation Failed" },
392 		{ 500, "Internal Server Error" },
393 		{ 501, "Not Implemented" },
394 		{ 502, "Bad Gateway" },
395 		{ 503, "Service Unavailable" },
396 		{ 504, "Gateway Timeout" },
397 		{ 505, "HTTP Version Not Supported" },
398 		{ 0 }
399 	};
400 
401 	for (i = 0; httperr[i].ht_code != 0; i++)
402 		if (httperr[i].ht_code == code)
403 			return (httperr[i].ht_err);
404 	return ("Unknown Error");
405 }
406