Blob


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