xref: /openbsd-src/usr.sbin/relayd/log.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: log.c,v 1.13 2008/07/18 12:26:52 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_status(enum host_status status)
171 {
172 	switch (status) {
173 	case HOST_DOWN:
174 		return ("down");
175 	case HOST_UNKNOWN:
176 		return ("unknown");
177 	case HOST_UP:
178 		return ("up");
179 	};
180 	/* NOTREACHED */
181 	return ("invalid");
182 }
183 
184 const char *
185 table_check(enum table_check check)
186 {
187 	switch (check) {
188 	case CHECK_NOCHECK:
189 		return ("none");
190 	case CHECK_ICMP:
191 		return ("icmp");
192 	case CHECK_TCP:
193 		return ("tcp");
194 	case CHECK_HTTP_CODE:
195 		return ("http code");
196 	case CHECK_HTTP_DIGEST:
197 		return ("http digest");
198 	case CHECK_SEND_EXPECT:
199 		return ("send expect");
200 	case CHECK_SCRIPT:
201 		return ("script");
202 	};
203 	/* NOTREACHED */
204 	return ("invalid");
205 }
206 
207 const char *
208 print_availability(u_long cnt, u_long up)
209 {
210 	static char buf[BUFSIZ];
211 
212 	if (cnt == 0)
213 		return ("");
214 	bzero(buf, sizeof(buf));
215 	snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100);
216 	return (buf);
217 }
218 
219 const char *
220 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
221 {
222 	if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
223 	    buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
224 		buf[0] = '\0';
225 		return (NULL);
226 	}
227 	return (buf);
228 }
229 
230 const char *
231 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
232 {
233 	struct timeval		tv;
234 	u_long			h, sec, min;
235 
236 	timerclear(&tv);
237 	timersub(a, b, &tv);
238 	sec = tv.tv_sec % 60;
239 	min = tv.tv_sec / 60 % 60;
240 	h = tv.tv_sec / 60 / 60;
241 
242 	snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
243 	return (buf);
244 }
245 
246 const char *
247 print_httperror(u_int code)
248 {
249 	u_int			 i;
250 	struct {
251 		u_int		 ht_code;
252 		const char	*ht_err;
253 	}			 httperr[] = {
254 		{ 100, "Continue" },
255 		{ 101, "Switching Protocols" },
256 		{ 200, "OK" },
257 		{ 201, "Created" },
258 		{ 202, "Accepted" },
259 		{ 203, "Non-Authorative Information" },
260 		{ 204, "No Content" },
261 		{ 205, "Reset Content" },
262 		{ 206, "Partial Content" },
263 		{ 300, "Multiple Choices" },
264 		{ 301, "Moved Permanently" },
265 		{ 302, "Moved Temporarily" },
266 		{ 303, "See Other" },
267 		{ 304, "Not Modified" },
268 		{ 307, "Temporary Redirect" },
269 		{ 400, "Bad Request" },
270 		{ 401, "Unauthorized" },
271 		{ 402, "Payment Required" },
272 		{ 403, "Forbidden" },
273 		{ 404, "Not Found" },
274 		{ 405, "Method Not Allowed" },
275 		{ 406, "Not Acceptable" },
276 		{ 407, "Proxy Authentication Required" },
277 		{ 408, "Request Timeout" },
278 		{ 409, "Conflict" },
279 		{ 410, "Gone" },
280 		{ 411, "Length Required" },
281 		{ 412, "Precondition Failed" },
282 		{ 413, "Request Entity Too Large" },
283 		{ 414, "Request-URL Too Long" },
284 		{ 415, "Unsupported Media Type" },
285 		{ 416, "Requested Range Not Satisfiable" },
286 		{ 417, "Expectation Failed" },
287 		{ 500, "Internal Server Error" },
288 		{ 501, "Not Implemented" },
289 		{ 502, "Bad Gateway" },
290 		{ 503, "Service Unavailable" },
291 		{ 504, "Gateway Timeout" },
292 		{ 505, "HTTP Version Not Supported" },
293 		{ 0 }
294 	};
295 
296 	for (i = 0; httperr[i].ht_code != 0; i++)
297 		if (httperr[i].ht_code == code)
298 			return (httperr[i].ht_err);
299 	return ("Unknown Error");
300 }
301