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