1 /* $OpenBSD: util.c,v 1.3 2019/09/15 19:23:29 rob Exp $ */ 2 3 /* 4 * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@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 USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * 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 <stdio.h> 24 #include <string.h> 25 #include <time.h> 26 #include <netdb.h> 27 #include <ctype.h> 28 29 #include "relayd.h" 30 31 const char * 32 host_error(enum host_error he) 33 { 34 switch (he) { 35 case HCE_NONE: 36 return ("none"); 37 break; 38 case HCE_ABORT: 39 return ("aborted"); 40 break; 41 case HCE_INTERVAL_TIMEOUT: 42 return ("interval timeout"); 43 break; 44 case HCE_ICMP_OK: 45 return ("icmp ok"); 46 break; 47 case HCE_ICMP_READ_TIMEOUT: 48 return ("icmp read timeout"); 49 break; 50 case HCE_ICMP_WRITE_TIMEOUT: 51 return ("icmp write timeout"); 52 break; 53 case HCE_TCP_SOCKET_ERROR: 54 return ("tcp socket error"); 55 break; 56 case HCE_TCP_SOCKET_LIMIT: 57 return ("tcp socket limit"); 58 break; 59 case HCE_TCP_SOCKET_OPTION: 60 return ("tcp socket option"); 61 break; 62 case HCE_TCP_CONNECT_FAIL: 63 return ("tcp connect failed"); 64 break; 65 case HCE_TCP_CONNECT_TIMEOUT: 66 return ("tcp connect timeout"); 67 break; 68 case HCE_TCP_CONNECT_OK: 69 return ("tcp connect ok"); 70 break; 71 case HCE_TCP_WRITE_TIMEOUT: 72 return ("tcp write timeout"); 73 break; 74 case HCE_TCP_WRITE_FAIL: 75 return ("tcp write failed"); 76 break; 77 case HCE_TCP_READ_TIMEOUT: 78 return ("tcp read timeout"); 79 break; 80 case HCE_TCP_READ_FAIL: 81 return ("tcp read failed"); 82 break; 83 case HCE_SCRIPT_OK: 84 return ("script ok"); 85 break; 86 case HCE_SCRIPT_FAIL: 87 return ("script failed"); 88 break; 89 case HCE_TLS_CONNECT_OK: 90 return ("tls connect ok"); 91 break; 92 case HCE_TLS_CONNECT_FAIL: 93 return ("tls connect failed"); 94 break; 95 case HCE_TLS_CONNECT_TIMEOUT: 96 return ("tls connect timeout"); 97 break; 98 case HCE_TLS_CONNECT_ERROR: 99 return ("tls connect error"); 100 break; 101 case HCE_TLS_READ_TIMEOUT: 102 return ("tls read timeout"); 103 break; 104 case HCE_TLS_WRITE_TIMEOUT: 105 return ("tls write timeout"); 106 break; 107 case HCE_TLS_READ_ERROR: 108 return ("tls read error"); 109 break; 110 case HCE_TLS_WRITE_ERROR: 111 return ("tls write error"); 112 break; 113 case HCE_SEND_EXPECT_FAIL: 114 return ("send/expect failed"); 115 break; 116 case HCE_SEND_EXPECT_OK: 117 return ("send/expect ok"); 118 break; 119 case HCE_HTTP_CODE_ERROR: 120 return ("http code malformed"); 121 break; 122 case HCE_HTTP_CODE_FAIL: 123 return ("http code mismatch"); 124 break; 125 case HCE_HTTP_CODE_OK: 126 return ("http code ok"); 127 break; 128 case HCE_HTTP_DIGEST_ERROR: 129 return ("http digest malformed"); 130 break; 131 case HCE_HTTP_DIGEST_FAIL: 132 return ("http digest mismatch"); 133 break; 134 case HCE_HTTP_DIGEST_OK: 135 return ("http digest ok"); 136 break; 137 } 138 /* NOTREACHED */ 139 return ("invalid"); 140 } 141 142 const char * 143 host_status(enum host_status status) 144 { 145 switch (status) { 146 case HOST_DOWN: 147 return ("down"); 148 case HOST_UNKNOWN: 149 return ("unknown"); 150 case HOST_UP: 151 return ("up"); 152 }; 153 /* NOTREACHED */ 154 return ("invalid"); 155 } 156 157 const char * 158 table_check(enum table_check check) 159 { 160 switch (check) { 161 case CHECK_NOCHECK: 162 return ("none"); 163 case CHECK_ICMP: 164 return ("icmp"); 165 case CHECK_TCP: 166 return ("tcp"); 167 case CHECK_HTTP_CODE: 168 return ("http code"); 169 case CHECK_HTTP_DIGEST: 170 return ("http digest"); 171 case CHECK_BINSEND_EXPECT: 172 case CHECK_SEND_EXPECT: 173 return ("send expect"); 174 case CHECK_SCRIPT: 175 return ("script"); 176 }; 177 /* NOTREACHED */ 178 return ("invalid"); 179 } 180 181 #ifdef DEBUG 182 const char * 183 relay_state(enum relay_state state) 184 { 185 switch (state) { 186 case STATE_INIT: 187 return ("init"); 188 case STATE_PENDING: 189 return ("pending"); 190 case STATE_PRECONNECT: 191 return ("preconnect"); 192 case STATE_CONNECTED: 193 return ("connected"); 194 case STATE_CLOSED: 195 return ("closed"); 196 case STATE_DONE: 197 return ("done"); 198 }; 199 /* NOTREACHED */ 200 return ("invalid"); 201 } 202 #endif 203 204 const char * 205 print_availability(u_long cnt, u_long up) 206 { 207 static char buf[BUFSIZ]; 208 209 if (cnt == 0) 210 return (""); 211 bzero(buf, sizeof(buf)); 212 snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100); 213 return (buf); 214 } 215 216 const char * 217 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 218 { 219 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 220 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 221 buf[0] = '\0'; 222 return (NULL); 223 } 224 return (buf); 225 } 226 227 const char * 228 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len) 229 { 230 struct timeval tv; 231 u_long h, sec, min; 232 233 timerclear(&tv); 234 timersub(a, b, &tv); 235 sec = tv.tv_sec % 60; 236 min = tv.tv_sec / 60 % 60; 237 h = tv.tv_sec / 60 / 60; 238 239 snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec); 240 return (buf); 241 } 242 243 const char * 244 printb_flags(const u_int32_t v, const char *bits) 245 { 246 static char buf[2][BUFSIZ]; 247 static int idx = 0; 248 int i, any = 0; 249 char c, *p, *r; 250 251 p = r = buf[++idx % 2]; 252 bzero(p, BUFSIZ); 253 254 if (bits) { 255 bits++; 256 while ((i = *bits++)) { 257 if (v & (1 << (i - 1))) { 258 if (any) { 259 *p++ = ','; 260 *p++ = ' '; 261 } 262 any = 1; 263 for (; (c = *bits) > 32; bits++) { 264 if (c == '_') 265 *p++ = ' '; 266 else 267 *p++ = tolower((u_char)c); 268 } 269 } else 270 for (; *bits > 32; bits++) 271 ; 272 } 273 } 274 275 return (r); 276 } 277 278 void 279 getmonotime(struct timeval *tv) 280 { 281 struct timespec ts; 282 283 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 284 fatal("clock_gettime"); 285 286 TIMESPEC_TO_TIMEVAL(tv, &ts); 287 } 288 289 struct ibuf * 290 string2binary(const char *string) 291 { 292 unsigned long i, j, x; 293 unsigned char *binary = NULL; 294 struct ibuf *ibuf = NULL; 295 char hex[3]; 296 int len; 297 298 if (strlen(string) % 2 != 0) { 299 return NULL; 300 } 301 302 binary = calloc(strlen(string), sizeof(unsigned char)); 303 if (binary == NULL) { 304 return NULL; 305 } 306 307 hex[2] = '\0'; 308 j = 0; 309 for (i = 0; i < strlen(string); i++) { 310 if (isxdigit(string[i]) == 0 || isxdigit(string[i+1]) == 0) { 311 free(binary); 312 return NULL; 313 } else { 314 hex[0] = string[i]; 315 hex[1] = string[i+1]; 316 x = strtoul(hex, NULL, 16); 317 binary[j++] = (unsigned char)x; 318 i++; 319 } 320 } 321 len = strlen(string) / 2; 322 if ((ibuf = ibuf_open(len)) == NULL || 323 ibuf_add(ibuf, binary, len) == -1) { 324 ibuf_free(ibuf); 325 free(binary); 326 return NULL; 327 } 328 free(binary); 329 return ibuf; 330 } 331 332 void 333 print_hex(uint8_t *buf, off_t offset, size_t length) 334 { 335 unsigned int i; 336 337 if (log_getverbose() < 3 || !length) 338 return; 339 340 for (i = 0; i < length; i++) { 341 if (i && (i % 4) == 0) { 342 if ((i % 32) == 0) 343 print_debug("\n"); 344 else 345 print_debug(" "); 346 } 347 print_debug("%02x", buf[offset + i]); 348 } 349 print_debug("\n"); 350 } 351 352 void 353 print_debug(const char *emsg, ...) 354 { 355 va_list ap; 356 357 if (log_getverbose() > 2) { 358 va_start(ap, emsg); 359 vfprintf(stderr, emsg, ap); 360 va_end(ap); 361 } 362 } 363