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