xref: /openbsd-src/usr.sbin/relayd/util.c (revision 7350f337b9e3eb4461d99580e625c7ef148d107c)
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