1 /* $OpenBSD: util.c,v 1.2 2019/05/13 09:54:07 reyk 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_SEND_EXPECT: 172 return ("send expect"); 173 case CHECK_SCRIPT: 174 return ("script"); 175 }; 176 /* NOTREACHED */ 177 return ("invalid"); 178 } 179 180 #ifdef DEBUG 181 const char * 182 relay_state(enum relay_state state) 183 { 184 switch (state) { 185 case STATE_INIT: 186 return ("init"); 187 case STATE_PENDING: 188 return ("pending"); 189 case STATE_PRECONNECT: 190 return ("preconnect"); 191 case STATE_CONNECTED: 192 return ("connected"); 193 case STATE_CLOSED: 194 return ("closed"); 195 case STATE_DONE: 196 return ("done"); 197 }; 198 /* NOTREACHED */ 199 return ("invalid"); 200 } 201 #endif 202 203 const char * 204 print_availability(u_long cnt, u_long up) 205 { 206 static char buf[BUFSIZ]; 207 208 if (cnt == 0) 209 return (""); 210 bzero(buf, sizeof(buf)); 211 snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100); 212 return (buf); 213 } 214 215 const char * 216 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 217 { 218 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 219 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 220 buf[0] = '\0'; 221 return (NULL); 222 } 223 return (buf); 224 } 225 226 const char * 227 print_time(struct timeval *a, struct timeval *b, char *buf, size_t len) 228 { 229 struct timeval tv; 230 u_long h, sec, min; 231 232 timerclear(&tv); 233 timersub(a, b, &tv); 234 sec = tv.tv_sec % 60; 235 min = tv.tv_sec / 60 % 60; 236 h = tv.tv_sec / 60 / 60; 237 238 snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec); 239 return (buf); 240 } 241 242 const char * 243 printb_flags(const u_int32_t v, const char *bits) 244 { 245 static char buf[2][BUFSIZ]; 246 static int idx = 0; 247 int i, any = 0; 248 char c, *p, *r; 249 250 p = r = buf[++idx % 2]; 251 bzero(p, BUFSIZ); 252 253 if (bits) { 254 bits++; 255 while ((i = *bits++)) { 256 if (v & (1 << (i - 1))) { 257 if (any) { 258 *p++ = ','; 259 *p++ = ' '; 260 } 261 any = 1; 262 for (; (c = *bits) > 32; bits++) { 263 if (c == '_') 264 *p++ = ' '; 265 else 266 *p++ = tolower((u_char)c); 267 } 268 } else 269 for (; *bits > 32; bits++) 270 ; 271 } 272 } 273 274 return (r); 275 } 276 277 void 278 getmonotime(struct timeval *tv) 279 { 280 struct timespec ts; 281 282 if (clock_gettime(CLOCK_MONOTONIC, &ts)) 283 fatal("clock_gettime"); 284 285 TIMESPEC_TO_TIMEVAL(tv, &ts); 286 } 287