1*479c151dSjsg /* $OpenBSD: util.c,v 1.5 2024/09/20 02:00:46 jsg Exp $ */ 27fb21699Sreyk 37fb21699Sreyk /* 47fb21699Sreyk * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> 57fb21699Sreyk * 67fb21699Sreyk * Permission to use, copy, modify, and distribute this software for any 77fb21699Sreyk * purpose with or without fee is hereby granted, provided that the above 87fb21699Sreyk * copyright notice and this permission notice appear in all copies. 97fb21699Sreyk * 107fb21699Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 117fb21699Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 127fb21699Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 137fb21699Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 147fb21699Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 157fb21699Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 167fb21699Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 177fb21699Sreyk */ 187fb21699Sreyk 197fb21699Sreyk #include <sys/types.h> 207fb21699Sreyk #include <sys/socket.h> 217fb21699Sreyk #include <sys/time.h> 227fb21699Sreyk 237fb21699Sreyk #include <stdio.h> 247fb21699Sreyk #include <string.h> 257fb21699Sreyk #include <time.h> 267fb21699Sreyk #include <netdb.h> 277fb21699Sreyk #include <ctype.h> 287fb21699Sreyk 297fb21699Sreyk #include "relayd.h" 307fb21699Sreyk 317fb21699Sreyk const char * 327fb21699Sreyk host_error(enum host_error he) 337fb21699Sreyk { 347fb21699Sreyk switch (he) { 357fb21699Sreyk case HCE_NONE: 367fb21699Sreyk return ("none"); 377fb21699Sreyk break; 387fb21699Sreyk case HCE_ABORT: 397fb21699Sreyk return ("aborted"); 407fb21699Sreyk break; 417fb21699Sreyk case HCE_INTERVAL_TIMEOUT: 427fb21699Sreyk return ("interval timeout"); 437fb21699Sreyk break; 447fb21699Sreyk case HCE_ICMP_OK: 457fb21699Sreyk return ("icmp ok"); 467fb21699Sreyk break; 477fb21699Sreyk case HCE_ICMP_READ_TIMEOUT: 487fb21699Sreyk return ("icmp read timeout"); 497fb21699Sreyk break; 507fb21699Sreyk case HCE_ICMP_WRITE_TIMEOUT: 517fb21699Sreyk return ("icmp write timeout"); 527fb21699Sreyk break; 537fb21699Sreyk case HCE_TCP_SOCKET_ERROR: 547fb21699Sreyk return ("tcp socket error"); 557fb21699Sreyk break; 567fb21699Sreyk case HCE_TCP_SOCKET_LIMIT: 577fb21699Sreyk return ("tcp socket limit"); 587fb21699Sreyk break; 597fb21699Sreyk case HCE_TCP_SOCKET_OPTION: 607fb21699Sreyk return ("tcp socket option"); 617fb21699Sreyk break; 627fb21699Sreyk case HCE_TCP_CONNECT_FAIL: 637fb21699Sreyk return ("tcp connect failed"); 647fb21699Sreyk break; 657fb21699Sreyk case HCE_TCP_CONNECT_TIMEOUT: 667fb21699Sreyk return ("tcp connect timeout"); 677fb21699Sreyk break; 687fb21699Sreyk case HCE_TCP_CONNECT_OK: 697fb21699Sreyk return ("tcp connect ok"); 707fb21699Sreyk break; 717fb21699Sreyk case HCE_TCP_WRITE_TIMEOUT: 727fb21699Sreyk return ("tcp write timeout"); 737fb21699Sreyk break; 747fb21699Sreyk case HCE_TCP_WRITE_FAIL: 757fb21699Sreyk return ("tcp write failed"); 767fb21699Sreyk break; 777fb21699Sreyk case HCE_TCP_READ_TIMEOUT: 787fb21699Sreyk return ("tcp read timeout"); 797fb21699Sreyk break; 807fb21699Sreyk case HCE_TCP_READ_FAIL: 817fb21699Sreyk return ("tcp read failed"); 827fb21699Sreyk break; 837fb21699Sreyk case HCE_SCRIPT_OK: 847fb21699Sreyk return ("script ok"); 857fb21699Sreyk break; 867fb21699Sreyk case HCE_SCRIPT_FAIL: 877fb21699Sreyk return ("script failed"); 887fb21699Sreyk break; 897fb21699Sreyk case HCE_TLS_CONNECT_OK: 907fb21699Sreyk return ("tls connect ok"); 917fb21699Sreyk break; 927fb21699Sreyk case HCE_TLS_CONNECT_FAIL: 937fb21699Sreyk return ("tls connect failed"); 947fb21699Sreyk break; 957fb21699Sreyk case HCE_TLS_CONNECT_TIMEOUT: 967fb21699Sreyk return ("tls connect timeout"); 977fb21699Sreyk break; 987fb21699Sreyk case HCE_TLS_CONNECT_ERROR: 997fb21699Sreyk return ("tls connect error"); 1007fb21699Sreyk break; 1017fb21699Sreyk case HCE_TLS_READ_TIMEOUT: 1027fb21699Sreyk return ("tls read timeout"); 1037fb21699Sreyk break; 1047fb21699Sreyk case HCE_TLS_WRITE_TIMEOUT: 1057fb21699Sreyk return ("tls write timeout"); 1067fb21699Sreyk break; 1077fb21699Sreyk case HCE_TLS_READ_ERROR: 1087fb21699Sreyk return ("tls read error"); 1097fb21699Sreyk break; 1107fb21699Sreyk case HCE_TLS_WRITE_ERROR: 1117fb21699Sreyk return ("tls write error"); 1127fb21699Sreyk break; 1137fb21699Sreyk case HCE_SEND_EXPECT_FAIL: 1147fb21699Sreyk return ("send/expect failed"); 1157fb21699Sreyk break; 1167fb21699Sreyk case HCE_SEND_EXPECT_OK: 1177fb21699Sreyk return ("send/expect ok"); 1187fb21699Sreyk break; 1197fb21699Sreyk case HCE_HTTP_CODE_ERROR: 1207fb21699Sreyk return ("http code malformed"); 1217fb21699Sreyk break; 1227fb21699Sreyk case HCE_HTTP_CODE_FAIL: 1237fb21699Sreyk return ("http code mismatch"); 1247fb21699Sreyk break; 1257fb21699Sreyk case HCE_HTTP_CODE_OK: 1267fb21699Sreyk return ("http code ok"); 1277fb21699Sreyk break; 1287fb21699Sreyk case HCE_HTTP_DIGEST_ERROR: 1297fb21699Sreyk return ("http digest malformed"); 1307fb21699Sreyk break; 1317fb21699Sreyk case HCE_HTTP_DIGEST_FAIL: 1327fb21699Sreyk return ("http digest mismatch"); 1337fb21699Sreyk break; 1347fb21699Sreyk case HCE_HTTP_DIGEST_OK: 1357fb21699Sreyk return ("http digest ok"); 1367fb21699Sreyk break; 1377fb21699Sreyk } 1387fb21699Sreyk /* NOTREACHED */ 1397fb21699Sreyk return ("invalid"); 1407fb21699Sreyk } 1417fb21699Sreyk 1427fb21699Sreyk const char * 1437fb21699Sreyk host_status(enum host_status status) 1447fb21699Sreyk { 1457fb21699Sreyk switch (status) { 1467fb21699Sreyk case HOST_DOWN: 1477fb21699Sreyk return ("down"); 1487fb21699Sreyk case HOST_UNKNOWN: 1497fb21699Sreyk return ("unknown"); 1507fb21699Sreyk case HOST_UP: 1517fb21699Sreyk return ("up"); 152*479c151dSjsg } 1537fb21699Sreyk /* NOTREACHED */ 1547fb21699Sreyk return ("invalid"); 1557fb21699Sreyk } 1567fb21699Sreyk 1577fb21699Sreyk const char * 1587fb21699Sreyk table_check(enum table_check check) 1597fb21699Sreyk { 1607fb21699Sreyk switch (check) { 1617fb21699Sreyk case CHECK_NOCHECK: 1627fb21699Sreyk return ("none"); 1637fb21699Sreyk case CHECK_ICMP: 1647fb21699Sreyk return ("icmp"); 1657fb21699Sreyk case CHECK_TCP: 1667fb21699Sreyk return ("tcp"); 1677fb21699Sreyk case CHECK_HTTP_CODE: 1687fb21699Sreyk return ("http code"); 1697fb21699Sreyk case CHECK_HTTP_DIGEST: 1707fb21699Sreyk return ("http digest"); 1713f229715Srob case CHECK_BINSEND_EXPECT: 1727fb21699Sreyk case CHECK_SEND_EXPECT: 1737fb21699Sreyk return ("send expect"); 1747fb21699Sreyk case CHECK_SCRIPT: 1757fb21699Sreyk return ("script"); 176*479c151dSjsg } 1777fb21699Sreyk /* NOTREACHED */ 1787fb21699Sreyk return ("invalid"); 1797fb21699Sreyk } 1807fb21699Sreyk 18165f47834Sreyk #ifdef DEBUG 18265f47834Sreyk const char * 18365f47834Sreyk relay_state(enum relay_state state) 18465f47834Sreyk { 18565f47834Sreyk switch (state) { 18665f47834Sreyk case STATE_INIT: 18765f47834Sreyk return ("init"); 18865f47834Sreyk case STATE_PENDING: 18965f47834Sreyk return ("pending"); 19065f47834Sreyk case STATE_PRECONNECT: 19165f47834Sreyk return ("preconnect"); 19265f47834Sreyk case STATE_CONNECTED: 19365f47834Sreyk return ("connected"); 19465f47834Sreyk case STATE_CLOSED: 19565f47834Sreyk return ("closed"); 19665f47834Sreyk case STATE_DONE: 19765f47834Sreyk return ("done"); 198*479c151dSjsg } 19965f47834Sreyk /* NOTREACHED */ 20065f47834Sreyk return ("invalid"); 20165f47834Sreyk } 20265f47834Sreyk #endif 20365f47834Sreyk 2047fb21699Sreyk const char * 2057fb21699Sreyk print_availability(u_long cnt, u_long up) 2067fb21699Sreyk { 2077fb21699Sreyk static char buf[BUFSIZ]; 2087fb21699Sreyk 2097fb21699Sreyk if (cnt == 0) 2107fb21699Sreyk return (""); 2117fb21699Sreyk bzero(buf, sizeof(buf)); 2127fb21699Sreyk snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100); 2137fb21699Sreyk return (buf); 2147fb21699Sreyk } 2157fb21699Sreyk 2167fb21699Sreyk const char * 2177fb21699Sreyk print_host(struct sockaddr_storage *ss, char *buf, size_t len) 2187fb21699Sreyk { 2197fb21699Sreyk if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 2207fb21699Sreyk buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 2217fb21699Sreyk buf[0] = '\0'; 2227fb21699Sreyk return (NULL); 2237fb21699Sreyk } 2247fb21699Sreyk return (buf); 2257fb21699Sreyk } 2267fb21699Sreyk 2277fb21699Sreyk const char * 2287fb21699Sreyk print_time(struct timeval *a, struct timeval *b, char *buf, size_t len) 2297fb21699Sreyk { 2307fb21699Sreyk struct timeval tv; 2317fb21699Sreyk u_long h, sec, min; 2327fb21699Sreyk 2337fb21699Sreyk timerclear(&tv); 2347fb21699Sreyk timersub(a, b, &tv); 2357fb21699Sreyk sec = tv.tv_sec % 60; 2367fb21699Sreyk min = tv.tv_sec / 60 % 60; 2377fb21699Sreyk h = tv.tv_sec / 60 / 60; 2387fb21699Sreyk 2397fb21699Sreyk snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec); 2407fb21699Sreyk return (buf); 2417fb21699Sreyk } 2427fb21699Sreyk 2437fb21699Sreyk const char * 2447fb21699Sreyk printb_flags(const u_int32_t v, const char *bits) 2457fb21699Sreyk { 2467fb21699Sreyk static char buf[2][BUFSIZ]; 2477fb21699Sreyk static int idx = 0; 2487fb21699Sreyk int i, any = 0; 2497fb21699Sreyk char c, *p, *r; 2507fb21699Sreyk 2517fb21699Sreyk p = r = buf[++idx % 2]; 2527fb21699Sreyk bzero(p, BUFSIZ); 2537fb21699Sreyk 2547fb21699Sreyk if (bits) { 2557fb21699Sreyk bits++; 2567fb21699Sreyk while ((i = *bits++)) { 2577fb21699Sreyk if (v & (1 << (i - 1))) { 2587fb21699Sreyk if (any) { 2597fb21699Sreyk *p++ = ','; 2607fb21699Sreyk *p++ = ' '; 2617fb21699Sreyk } 2627fb21699Sreyk any = 1; 2637fb21699Sreyk for (; (c = *bits) > 32; bits++) { 2647fb21699Sreyk if (c == '_') 2657fb21699Sreyk *p++ = ' '; 2667fb21699Sreyk else 2677fb21699Sreyk *p++ = tolower((u_char)c); 2687fb21699Sreyk } 2697fb21699Sreyk } else 2707fb21699Sreyk for (; *bits > 32; bits++) 2717fb21699Sreyk ; 2727fb21699Sreyk } 2737fb21699Sreyk } 2747fb21699Sreyk 2757fb21699Sreyk return (r); 2767fb21699Sreyk } 2777fb21699Sreyk 2787fb21699Sreyk void 2797fb21699Sreyk getmonotime(struct timeval *tv) 2807fb21699Sreyk { 2817fb21699Sreyk struct timespec ts; 2827fb21699Sreyk 2837fb21699Sreyk if (clock_gettime(CLOCK_MONOTONIC, &ts)) 2847fb21699Sreyk fatal("clock_gettime"); 2857fb21699Sreyk 2867fb21699Sreyk TIMESPEC_TO_TIMEVAL(tv, &ts); 2877fb21699Sreyk } 2883f229715Srob 2893f229715Srob struct ibuf * 2903f229715Srob string2binary(const char *string) 2913f229715Srob { 2923f229715Srob struct ibuf *ibuf = NULL; 293b5355054Sclaudio unsigned char ch, r; 294b5355054Sclaudio size_t i, len; 2953f229715Srob 296b5355054Sclaudio len = strlen(string); 297b5355054Sclaudio if (len % 2 != 0) 298b5355054Sclaudio goto fail; 299b5355054Sclaudio if ((ibuf = ibuf_open(len / 2)) == NULL) 300b5355054Sclaudio goto fail; 301b5355054Sclaudio 302b5355054Sclaudio while (*string) { 303b5355054Sclaudio r = 0; 304b5355054Sclaudio for (i = 0; i < 2; i++) { 305b5355054Sclaudio ch = string[i]; 306b5355054Sclaudio if (isdigit(ch)) 307b5355054Sclaudio ch -= '0'; 308b5355054Sclaudio else if (islower(ch)) 309b5355054Sclaudio ch -= ('a' - 10); 310b5355054Sclaudio else if (isupper(ch)) 311b5355054Sclaudio ch -= ('A' - 10); 312b5355054Sclaudio else 313b5355054Sclaudio goto fail; 314b5355054Sclaudio if (ch > 0xf) 315b5355054Sclaudio goto fail; 316b5355054Sclaudio r = r << 4 | ch; 317b5355054Sclaudio } 318b5355054Sclaudio if (ibuf_add_n8(ibuf, r) == -1) 319b5355054Sclaudio goto fail; 320b5355054Sclaudio string += 2; 3213f229715Srob } 3223f229715Srob 3233f229715Srob return ibuf; 324b5355054Sclaudio 325b5355054Sclaudio fail: 326b5355054Sclaudio ibuf_free(ibuf); 327b5355054Sclaudio return NULL; 3283f229715Srob } 3293f229715Srob 3303f229715Srob void 3313f229715Srob print_hex(uint8_t *buf, off_t offset, size_t length) 3323f229715Srob { 3333f229715Srob unsigned int i; 3343f229715Srob 3353f229715Srob if (log_getverbose() < 3 || !length) 3363f229715Srob return; 3373f229715Srob 3383f229715Srob for (i = 0; i < length; i++) { 3393f229715Srob if (i && (i % 4) == 0) { 3403f229715Srob if ((i % 32) == 0) 3413f229715Srob print_debug("\n"); 3423f229715Srob else 3433f229715Srob print_debug(" "); 3443f229715Srob } 3453f229715Srob print_debug("%02x", buf[offset + i]); 3463f229715Srob } 3473f229715Srob print_debug("\n"); 3483f229715Srob } 3493f229715Srob 3503f229715Srob void 3513f229715Srob print_debug(const char *emsg, ...) 3523f229715Srob { 3533f229715Srob va_list ap; 3543f229715Srob 3553f229715Srob if (log_getverbose() > 2) { 3563f229715Srob va_start(ap, emsg); 3573f229715Srob vfprintf(stderr, emsg, ap); 3583f229715Srob va_end(ap); 3593f229715Srob } 3603f229715Srob } 361