Bug Summary

File:src/usr.sbin/relayd/relayd.c
Warning:line 1460, column 6
Although the value stored to 'q' is used in the enclosing expression, the value is never actually read from 'q'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name relayd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/relayd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/relayd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/relayd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/relayd/relayd.c
1/* $OpenBSD: relayd.c,v 1.187 2021/07/12 15:09:21 beck Exp $ */
2
3/*
4 * Copyright (c) 2007 - 2016 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <sys/queue.h>
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/wait.h>
25#include <sys/resource.h>
26
27#include <netinet/in.h>
28#include <arpa/inet.h>
29
30#include <signal.h>
31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <fcntl.h>
35#include <getopt.h>
36#include <fnmatch.h>
37#include <syslog.h>
38#include <err.h>
39#include <errno(*__errno()).h>
40#include <event.h>
41#include <unistd.h>
42#include <ctype.h>
43#include <pwd.h>
44#include <sha1.h>
45#include <md5.h>
46
47#include <tls.h>
48
49#include "relayd.h"
50
51#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
52
53__dead__attribute__((__noreturn__)) void usage(void);
54
55int parent_configure(struct relayd *);
56void parent_configure_done(struct relayd *);
57void parent_reload(struct relayd *, u_int, const char *);
58void parent_sig_handler(int, short, void *);
59void parent_shutdown(struct relayd *);
60int parent_dispatch_pfe(int, struct privsep_proc *, struct imsg *);
61int parent_dispatch_hce(int, struct privsep_proc *, struct imsg *);
62int parent_dispatch_relay(int, struct privsep_proc *,
63 struct imsg *);
64int parent_dispatch_ca(int, struct privsep_proc *,
65 struct imsg *);
66int bindany(struct ctl_bindany *);
67void parent_tls_ticket_rekey(int, short, void *);
68
69struct relayd *relayd_env;
70
71static struct privsep_proc procs[] = {
72 { "pfe", PROC_PFE, parent_dispatch_pfe, pfe },
73 { "hce", PROC_HCE, parent_dispatch_hce, hce },
74 { "relay", PROC_RELAY, parent_dispatch_relay, relay },
75 { "ca", PROC_CA, parent_dispatch_ca, ca }
76};
77
78enum privsep_procid privsep_process;
79
80void
81parent_sig_handler(int sig, short event, void *arg)
82{
83 struct privsep *ps = arg;
84
85 switch (sig) {
86 case SIGTERM15:
87 case SIGINT2:
88 parent_shutdown(ps->ps_env);
89 break;
90 case SIGHUP1:
91 log_info("%s: reload requested with SIGHUP", __func__);
92
93 /*
94 * This is safe because libevent uses async signal handlers
95 * that run in the event loop and not in signal context.
96 */
97 parent_reload(ps->ps_env, CONFIG_RELOAD0x00, NULL((void*)0));
98 break;
99 case SIGPIPE13:
100 case SIGUSR130:
101 /* ignore */
102 break;
103 default:
104 fatalx("unexpected signal");
105 }
106}
107
108__dead__attribute__((__noreturn__)) void
109usage(void)
110{
111 extern char *__progname;
112
113 fprintf(stderr(&__sF[2]), "usage: %s [-dnv] [-D macro=value] [-f file]\n",
114 __progname);
115 exit(1);
116}
117
118int
119main(int argc, char *argv[])
120{
121 int c;
122 int debug = 0, verbose = 0;
123 u_int32_t opts = 0;
124 struct relayd *env;
125 struct privsep *ps;
126 const char *conffile = CONF_FILE"/etc/relayd.conf";
127 enum privsep_procid proc_id = PROC_PARENT;
128 int proc_instance = 0;
129 const char *errp, *title = NULL((void*)0);
130 int argc0 = argc;
131
132 while ((c = getopt(argc, argv, "dD:nI:P:f:v")) != -1) {
133 switch (c) {
134 case 'd':
135 debug = 2;
136 break;
137 case 'D':
138 if (cmdline_symset(optarg) < 0)
139 log_warnx("could not parse macro definition %s",
140 optarg);
141 break;
142 case 'n':
143 debug = 2;
144 opts |= RELAYD_OPT_NOACTION0x04;
145 break;
146 case 'f':
147 conffile = optarg;
148 break;
149 case 'v':
150 verbose++;
151 opts |= RELAYD_OPT_VERBOSE0x01;
152 break;
153 case 'P':
154 title = optarg;
155 proc_id = proc_getid(procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), title);
156 if (proc_id == PROC_MAX)
157 fatalx("invalid process name");
158 break;
159 case 'I':
160 proc_instance = strtonum(optarg, 0,
161 PROC_MAX_INSTANCES32, &errp);
162 if (errp)
163 fatalx("invalid process instance");
164 break;
165 default:
166 usage();
167 }
168 }
169
170 /* log to stderr until daemonized */
171 log_init(debug ? debug : 1, LOG_DAEMON(3<<3));
172
173 argc -= optind;
174 if (argc > 0)
175 usage();
176
177 if ((env = calloc(1, sizeof(*env))) == NULL((void*)0) ||
178 (ps = calloc(1, sizeof(*ps))) == NULL((void*)0))
179 exit(1);
180
181 relayd_env = env;
182 env->sc_ps = ps;
183 ps->ps_env = env;
184 TAILQ_INIT(&ps->ps_rcsocks)do { (&ps->ps_rcsocks)->tqh_first = ((void*)0); (&
ps->ps_rcsocks)->tqh_last = &(&ps->ps_rcsocks
)->tqh_first; } while (0)
;
185 env->sc_conffile = conffile;
186 env->sc_conf.opts = opts;
187 TAILQ_INIT(&env->sc_hosts)do { (&env->sc_hosts)->tqh_first = ((void*)0); (&
env->sc_hosts)->tqh_last = &(&env->sc_hosts)
->tqh_first; } while (0)
;
188 TAILQ_INIT(&env->sc_sessions)do { (&env->sc_sessions)->tqh_first = ((void*)0); (
&env->sc_sessions)->tqh_last = &(&env->sc_sessions
)->tqh_first; } while (0)
;
189 env->sc_rtable = getrtable();
190 /* initialize the TLS session id to a random key for all relay procs */
191 arc4random_buf(env->sc_conf.tls_sid, sizeof(env->sc_conf.tls_sid));
192
193 if (parse_config(env->sc_conffile, env) == -1)
194 exit(1);
195
196 if (debug)
197 env->sc_conf.opts |= RELAYD_OPT_LOGUPDATE0x08;
198
199 if (geteuid())
200 errx(1, "need root privileges");
201
202 if ((ps->ps_pw = getpwnam(RELAYD_USER"_relayd")) == NULL((void*)0))
203 errx(1, "unknown user %s", RELAYD_USER"_relayd");
204
205 log_init(debug, LOG_DAEMON(3<<3));
206 log_setverbose(verbose);
207
208 if (env->sc_conf.opts & RELAYD_OPT_NOACTION0x04)
209 ps->ps_noaction = 1;
210
211 ps->ps_instances[PROC_RELAY] = env->sc_conf.prefork_relay;
212 ps->ps_instances[PROC_CA] = env->sc_conf.prefork_relay;
213 ps->ps_instance = proc_instance;
214 if (title != NULL((void*)0))
215 ps->ps_title[proc_id] = title;
216
217 /* only the parent returns */
218 proc_init(ps, procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), debug, argc0, argv, proc_id);
219
220 log_procinit("parent");
221 if (!debug && daemon(1, 0) == -1)
222 err(1, "failed to daemonize");
223
224 if (ps->ps_noaction == 0)
225 log_info("startup");
226
227 if (unveil("/", "rx") == -1)
228 err(1, "unveil /");
229 if (unveil(NULL((void*)0), NULL((void*)0)) == -1)
230 err(1, "unveil");
231
232 event_init();
233
234 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps)event_set(&ps->ps_evsigint, 2, 0x08|0x10, parent_sig_handler
, ps)
;
235 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps)event_set(&ps->ps_evsigterm, 15, 0x08|0x10, parent_sig_handler
, ps)
;
236 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps)event_set(&ps->ps_evsighup, 1, 0x08|0x10, parent_sig_handler
, ps)
;
237 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps)event_set(&ps->ps_evsigpipe, 13, 0x08|0x10, parent_sig_handler
, ps)
;
238 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps)event_set(&ps->ps_evsigusr1, 30, 0x08|0x10, parent_sig_handler
, ps)
;
239
240 signal_add(&ps->ps_evsigint, NULL)event_add(&ps->ps_evsigint, ((void*)0));
241 signal_add(&ps->ps_evsigterm, NULL)event_add(&ps->ps_evsigterm, ((void*)0));
242 signal_add(&ps->ps_evsighup, NULL)event_add(&ps->ps_evsighup, ((void*)0));
243 signal_add(&ps->ps_evsigpipe, NULL)event_add(&ps->ps_evsigpipe, ((void*)0));
244 signal_add(&ps->ps_evsigusr1, NULL)event_add(&ps->ps_evsigusr1, ((void*)0));
245
246 proc_connect(ps);
247
248 relay_http(NULL((void*)0));
249 if (load_config(env->sc_conffile, env) == -1) {
250 proc_kill(env->sc_ps);
251 exit(1);
252 }
253
254 if (env->sc_conf.opts & RELAYD_OPT_NOACTION0x04) {
255 fprintf(stderr(&__sF[2]), "configuration OK\n");
256 proc_kill(env->sc_ps);
257 exit(0);
258 }
259
260 if (env->sc_conf.flags & (F_TLS0x00000800|F_TLSCLIENT0x00200000))
261 ssl_init(env);
262
263 /* rekey the TLS tickets before pushing the config */
264 parent_tls_ticket_rekey(0, 0, env);
265 if (parent_configure(env) == -1)
266 fatalx("configuration failed");
267
268 init_routes(env);
269
270 event_dispatch();
271
272 parent_shutdown(env);
273 /* NOTREACHED */
274
275 return (0);
276}
277
278int
279parent_configure(struct relayd *env)
280{
281 struct table *tb;
282 struct rdr *rdr;
283 struct router *rt;
284 struct protocol *proto;
285 struct relay *rlay;
286 int id;
287 int ret = -1;
288
289 TAILQ_FOREACH(tb, env->sc_tables, entry)for((tb) = ((env->sc_tables)->tqh_first); (tb) != ((void
*)0); (tb) = ((tb)->entry.tqe_next))
290 config_settable(env, tb);
291 TAILQ_FOREACH(rdr, env->sc_rdrs, entry)for((rdr) = ((env->sc_rdrs)->tqh_first); (rdr) != ((void
*)0); (rdr) = ((rdr)->entry.tqe_next))
292 config_setrdr(env, rdr);
293 TAILQ_FOREACH(rt, env->sc_rts, rt_entry)for((rt) = ((env->sc_rts)->tqh_first); (rt) != ((void*)
0); (rt) = ((rt)->rt_entry.tqe_next))
294 config_setrt(env, rt);
295 TAILQ_FOREACH(proto, env->sc_protos, entry)for((proto) = ((env->sc_protos)->tqh_first); (proto) !=
((void*)0); (proto) = ((proto)->entry.tqe_next))
296 config_setproto(env, proto);
297 TAILQ_FOREACH(proto, env->sc_protos, entry)for((proto) = ((env->sc_protos)->tqh_first); (proto) !=
((void*)0); (proto) = ((proto)->entry.tqe_next))
298 config_setrule(env, proto);
299 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)for((rlay) = ((env->sc_relays)->tqh_first); (rlay) != (
(void*)0); (rlay) = ((rlay)->rl_entry.tqe_next))
{
300 /* Check for TLS Inspection */
301 if ((rlay->rl_conf.flags & (F_TLS0x00000800|F_TLSCLIENT0x00200000)) ==
302 (F_TLS0x00000800|F_TLSCLIENT0x00200000) && rlay->rl_tls_cacert_fd != -1)
303 rlay->rl_conf.flags |= F_TLSINSPECT0x04000000;
304
305 config_setrelay(env, rlay);
306 }
307
308 /* HCE, PFE, CA and the relays need to reload their config. */
309 env->sc_reload = 2 + (2 * env->sc_conf.prefork_relay);
310
311 for (id = 0; id < PROC_MAX; id++) {
312 if (id == privsep_process)
313 continue;
314 proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, -1,
315 -1, &env->sc_conf, sizeof(env->sc_conf));
316 }
317
318 ret = 0;
319
320 config_purge(env, CONFIG_ALL0xff & ~CONFIG_RELAYS0x04);
321 return (ret);
322}
323
324void
325parent_reload(struct relayd *env, u_int reset, const char *filename)
326{
327 if (env->sc_reload) {
328 log_debug("%s: already in progress: %d pending",
329 __func__, env->sc_reload);
330 return;
331 }
332
333 /* Switch back to the default config file */
334 if (filename == NULL((void*)0) || *filename == '\0')
335 filename = env->sc_conffile;
336
337 log_debug("%s: level %d config file %s", __func__, reset, filename);
338
339 config_purge(env, CONFIG_ALL0xff);
340
341 if (reset == CONFIG_RELOAD0x00) {
342 if (load_config(filename, env) == -1) {
343 log_debug("%s: failed to load config file %s",
344 __func__, filename);
345 }
346
347 config_setreset(env, CONFIG_ALL0xff);
348
349 if (parent_configure(env) == -1) {
350 log_debug("%s: failed to commit config from %s",
351 __func__, filename);
352 }
353 } else
354 config_setreset(env, reset);
355}
356
357void
358parent_configure_done(struct relayd *env)
359{
360 int id;
361
362 if (env->sc_reload == 0) {
363 log_warnx("%s: configuration already finished", __func__);
364 return;
365 }
366
367 env->sc_reload--;
368 if (env->sc_reload == 0) {
369 for (id = 0; id < PROC_MAX; id++) {
370 if (id == privsep_process)
371 continue;
372
373 proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL((void*)0), 0);
374 }
375 }
376}
377
378void
379parent_shutdown(struct relayd *env)
380{
381 config_purge(env, CONFIG_ALL0xff);
382
383 proc_kill(env->sc_ps);
384 control_cleanup(&env->sc_ps->ps_csock);
385 carp_demote_shutdown();
386
387 free(env->sc_ps);
388 free(env);
389
390 log_info("parent terminating, pid %d", getpid());
391
392 exit(0);
393}
394
395int
396parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
397{
398 struct privsep *ps = p->p_ps;
399 struct relayd *env = ps->ps_env;
400 struct ctl_demote demote;
401 struct ctl_netroute crt;
402 u_int v;
403 char *str = NULL((void*)0);
404
405 switch (imsg->hdr.type) {
406 case IMSG_DEMOTE:
407 IMSG_SIZE_CHECK(imsg, &demote)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&demote)) fatalx("bad length imsg received"); } while (
0)
;
408 memcpy(&demote, imsg->data, sizeof(demote));
409 carp_demote_set(demote.group, demote.level);
410 break;
411 case IMSG_RTMSG:
412 IMSG_SIZE_CHECK(imsg, &crt)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&crt)) fatalx("bad length imsg received"); } while (0)
;
413 memcpy(&crt, imsg->data, sizeof(crt));
414 pfe_route(env, &crt);
415 break;
416 case IMSG_CTL_RESET:
417 IMSG_SIZE_CHECK(imsg, &v)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&v)) fatalx("bad length imsg received"); } while (0)
;
418 memcpy(&v, imsg->data, sizeof(v));
419 parent_reload(env, v, NULL((void*)0));
420 break;
421 case IMSG_CTL_RELOAD:
422 if (IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) > 0)
423 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)));
424 parent_reload(env, CONFIG_RELOAD0x00, str);
425 free(str);
426 break;
427 case IMSG_CTL_SHUTDOWN:
428 parent_shutdown(env);
429 break;
430 case IMSG_CFG_DONE:
431 parent_configure_done(env);
432 break;
433 case IMSG_AGENTXSOCK:
434 (void)agentx_setsock(env, p->p_id);
435 break;
436 default:
437 return (-1);
438 }
439
440 return (0);
441}
442
443int
444parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
445{
446 struct privsep *ps = p->p_ps;
447 struct relayd *env = ps->ps_env;
448 struct ctl_script scr;
449
450 switch (imsg->hdr.type) {
451 case IMSG_SCRIPT:
452 IMSG_SIZE_CHECK(imsg, &scr)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&scr)) fatalx("bad length imsg received"); } while (0)
;
453 bcopy(imsg->data, &scr, sizeof(scr));
454 scr.retval = script_exec(env, &scr);
455 proc_compose(ps, PROC_HCE, IMSG_SCRIPT, &scr, sizeof(scr));
456 break;
457 case IMSG_CFG_DONE:
458 parent_configure_done(env);
459 break;
460 default:
461 return (-1);
462 }
463
464 return (0);
465}
466
467int
468parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
469{
470 struct privsep *ps = p->p_ps;
471 struct relayd *env = ps->ps_env;
472 struct ctl_bindany bnd;
473 int s;
474
475 switch (imsg->hdr.type) {
476 case IMSG_BINDANY:
477 IMSG_SIZE_CHECK(imsg, &bnd)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&bnd)) fatalx("bad length imsg received"); } while (0)
;
478 bcopy(imsg->data, &bnd, sizeof(bnd));
479 if (bnd.bnd_proc > env->sc_conf.prefork_relay)
480 fatalx("%s: invalid relay proc", __func__);
481 switch (bnd.bnd_proto) {
482 case IPPROTO_TCP6:
483 case IPPROTO_UDP17:
484 break;
485 default:
486 fatalx("%s: requested socket "
487 "for invalid protocol", __func__);
488 /* NOTREACHED */
489 }
490 s = bindany(&bnd);
491 proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc,
492 IMSG_BINDANY, -1, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
493 break;
494 case IMSG_CFG_DONE:
495 parent_configure_done(env);
496 break;
497 default:
498 return (-1);
499 }
500
501 return (0);
502}
503
504int
505parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
506{
507 struct privsep *ps = p->p_ps;
508 struct relayd *env = ps->ps_env;
509
510 switch (imsg->hdr.type) {
511 case IMSG_CFG_DONE:
512 parent_configure_done(env);
513 break;
514 default:
515 return (-1);
516 }
517
518 return (0);
519}
520
521void
522purge_table(struct relayd *env, struct tablelist *head, struct table *table)
523{
524 struct host *host;
525
526 while ((host = TAILQ_FIRST(&table->hosts)((&table->hosts)->tqh_first)) != NULL((void*)0)) {
527 TAILQ_REMOVE(&table->hosts, host, entry)do { if (((host)->entry.tqe_next) != ((void*)0)) (host)->
entry.tqe_next->entry.tqe_prev = (host)->entry.tqe_prev
; else (&table->hosts)->tqh_last = (host)->entry
.tqe_prev; *(host)->entry.tqe_prev = (host)->entry.tqe_next
; ; ; } while (0)
;
528 TAILQ_REMOVE(&env->sc_hosts, host, globalentry)do { if (((host)->globalentry.tqe_next) != ((void*)0)) (host
)->globalentry.tqe_next->globalentry.tqe_prev = (host)->
globalentry.tqe_prev; else (&env->sc_hosts)->tqh_last
= (host)->globalentry.tqe_prev; *(host)->globalentry.tqe_prev
= (host)->globalentry.tqe_next; ; ; } while (0)
;
529 if (event_initialized(&host->cte.ev)((&host->cte.ev)->ev_flags & 0x80)) {
530 event_del(&host->cte.ev);
531 close(host->cte.s);
532 }
533 ibuf_free(host->cte.buf);
534 tls_free(host->cte.tls);
535 free(host);
536 }
537 free(table->sendbuf);
538 ibuf_free(table->sendbinbuf);
539 tls_config_free(table->tls_cfg);
540
541 if (head != NULL((void*)0))
542 TAILQ_REMOVE(head, table, entry)do { if (((table)->entry.tqe_next) != ((void*)0)) (table)->
entry.tqe_next->entry.tqe_prev = (table)->entry.tqe_prev
; else (head)->tqh_last = (table)->entry.tqe_prev; *(table
)->entry.tqe_prev = (table)->entry.tqe_next; ; ; } while
(0)
;
543 free(table);
544}
545
546void
547purge_key(char **key, off_t len)
548{
549 freezero(*key, len);
550
551 *key = NULL((void*)0);
552}
553
554void
555purge_relay(struct relayd *env, struct relay *rlay)
556{
557 struct rsession *con;
558 struct relay_table *rlt;
559 struct relay_cert *cert, *tmpcert;
560
561 /* shutdown and remove relay */
562 if (event_initialized(&rlay->rl_ev)((&rlay->rl_ev)->ev_flags & 0x80))
563 event_del(&rlay->rl_ev);
564 close(rlay->rl_s);
565 TAILQ_REMOVE(env->sc_relays, rlay, rl_entry)do { if (((rlay)->rl_entry.tqe_next) != ((void*)0)) (rlay)
->rl_entry.tqe_next->rl_entry.tqe_prev = (rlay)->rl_entry
.tqe_prev; else (env->sc_relays)->tqh_last = (rlay)->
rl_entry.tqe_prev; *(rlay)->rl_entry.tqe_prev = (rlay)->
rl_entry.tqe_next; ; ; } while (0)
;
566
567 /* cleanup sessions */
568 while ((con =
569 SPLAY_ROOT(&rlay->rl_sessions)(&rlay->rl_sessions)->sph_root) != NULL((void*)0))
570 relay_close(con, NULL((void*)0), 0);
571
572 /* cleanup relay */
573 if (rlay->rl_bev != NULL((void*)0))
574 bufferevent_free(rlay->rl_bev);
575 if (rlay->rl_dstbev != NULL((void*)0))
576 bufferevent_free(rlay->rl_dstbev);
577
578 purge_key(&rlay->rl_tls_cakey, rlay->rl_conf.tls_cakey_len);
579
580 if (rlay->rl_tls_pkey != NULL((void*)0)) {
581 EVP_PKEY_free(rlay->rl_tls_pkey);
582 rlay->rl_tls_pkey = NULL((void*)0);
583 }
584 if (rlay->rl_tls_cacertx509 != NULL((void*)0)) {
585 X509_free(rlay->rl_tls_cacertx509);
586 rlay->rl_tls_cacertx509 = NULL((void*)0);
587 }
588 if (rlay->rl_tls_capkey != NULL((void*)0)) {
589 EVP_PKEY_free(rlay->rl_tls_capkey);
590 rlay->rl_tls_capkey = NULL((void*)0);
591 }
592
593 tls_free(rlay->rl_tls_ctx);
594 tls_config_free(rlay->rl_tls_cfg);
595 tls_config_free(rlay->rl_tls_client_cfg);
596
597 while ((rlt = TAILQ_FIRST(&rlay->rl_tables)((&rlay->rl_tables)->tqh_first))) {
598 TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry)do { if (((rlt)->rlt_entry.tqe_next) != ((void*)0)) (rlt)->
rlt_entry.tqe_next->rlt_entry.tqe_prev = (rlt)->rlt_entry
.tqe_prev; else (&rlay->rl_tables)->tqh_last = (rlt
)->rlt_entry.tqe_prev; *(rlt)->rlt_entry.tqe_prev = (rlt
)->rlt_entry.tqe_next; ; ; } while (0)
;
599 free(rlt);
600 }
601
602 TAILQ_FOREACH_SAFE(cert, env->sc_certs, cert_entry, tmpcert)for ((cert) = ((env->sc_certs)->tqh_first); (cert) != (
(void*)0) && ((tmpcert) = ((cert)->cert_entry.tqe_next
), 1); (cert) = (tmpcert))
{
603 if (rlay->rl_conf.id != cert->cert_relayid)
604 continue;
605 if (cert->cert_fd != -1)
606 close(cert->cert_fd);
607 if (cert->cert_key_fd != -1)
608 close(cert->cert_key_fd);
609 if (cert->cert_ocsp_fd != -1)
610 close(cert->cert_ocsp_fd);
611 if (cert->cert_pkey != NULL((void*)0))
612 EVP_PKEY_free(cert->cert_pkey);
613 TAILQ_REMOVE(env->sc_certs, cert, cert_entry)do { if (((cert)->cert_entry.tqe_next) != ((void*)0)) (cert
)->cert_entry.tqe_next->cert_entry.tqe_prev = (cert)->
cert_entry.tqe_prev; else (env->sc_certs)->tqh_last = (
cert)->cert_entry.tqe_prev; *(cert)->cert_entry.tqe_prev
= (cert)->cert_entry.tqe_next; ; ; } while (0)
;
614 free(cert);
615 }
616
617 free(rlay);
618}
619
620struct kv *
621kv_add(struct kvtree *keys, char *key, char *value, int unique)
622{
623 struct kv *kv, *oldkv;
624
625 if (key == NULL((void*)0))
626 return (NULL((void*)0));
627 if ((kv = calloc(1, sizeof(*kv))) == NULL((void*)0))
628 return (NULL((void*)0));
629 if ((kv->kv_key = strdup(key)) == NULL((void*)0))
630 goto fail;
631 if (value != NULL((void*)0) &&
632 (kv->kv_value = strdup(value)) == NULL((void*)0))
633 goto fail;
634 TAILQ_INIT(&kv->kv_children)do { (&kv->kv_children)->tqh_first = ((void*)0); (&
kv->kv_children)->tqh_last = &(&kv->kv_children
)->tqh_first; } while (0)
;
635
636 if ((oldkv = RB_INSERT(kvtree, keys, kv)kvtree_RB_INSERT(keys, kv)) != NULL((void*)0)) {
637 /*
638 * return error if the key should occur only once,
639 * or add it to a list attached to the key's node.
640 */
641 if (unique)
642 goto fail;
643 TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry)do { (kv)->kv_entry.tqe_next = ((void*)0); (kv)->kv_entry
.tqe_prev = (&oldkv->kv_children)->tqh_last; *(&
oldkv->kv_children)->tqh_last = (kv); (&oldkv->kv_children
)->tqh_last = &(kv)->kv_entry.tqe_next; } while (0)
;
644 kv->kv_parent = oldkv;
645 }
646
647 return (kv);
648 fail:
649 free(kv->kv_key);
650 free(kv->kv_value);
651 free(kv);
652 return (NULL((void*)0));
653}
654
655int
656kv_set(struct kv *kv, char *fmt, ...)
657{
658 va_list ap;
659 char *value = NULL((void*)0);
660 struct kv *ckv;
661
662 va_start(ap, fmt)__builtin_va_start(ap, fmt);
663 if (vasprintf(&value, fmt, ap) == -1)
664 return (-1);
665 va_end(ap)__builtin_va_end(ap);
666
667 /* Remove all children */
668 while ((ckv = TAILQ_FIRST(&kv->kv_children)((&kv->kv_children)->tqh_first)) != NULL((void*)0)) {
669 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry)do { if (((ckv)->kv_entry.tqe_next) != ((void*)0)) (ckv)->
kv_entry.tqe_next->kv_entry.tqe_prev = (ckv)->kv_entry.
tqe_prev; else (&kv->kv_children)->tqh_last = (ckv)
->kv_entry.tqe_prev; *(ckv)->kv_entry.tqe_prev = (ckv)->
kv_entry.tqe_next; ; ; } while (0)
;
670 kv_free(ckv);
671 free(ckv);
672 }
673
674 /* Set the new value */
675 free(kv->kv_value);
676 kv->kv_value = value;
677
678 return (0);
679}
680
681int
682kv_setkey(struct kv *kv, char *fmt, ...)
683{
684 va_list ap;
685 char *key = NULL((void*)0);
686
687 va_start(ap, fmt)__builtin_va_start(ap, fmt);
688 if (vasprintf(&key, fmt, ap) == -1)
689 return (-1);
690 va_end(ap)__builtin_va_end(ap);
691
692 free(kv->kv_key);
693 kv->kv_key = key;
694
695 return (0);
696}
697
698void
699kv_delete(struct kvtree *keys, struct kv *kv)
700{
701 struct kv *ckv;
702
703 RB_REMOVE(kvtree, keys, kv)kvtree_RB_REMOVE(keys, kv);
704
705 /* Remove all children */
706 while ((ckv = TAILQ_FIRST(&kv->kv_children)((&kv->kv_children)->tqh_first)) != NULL((void*)0)) {
707 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry)do { if (((ckv)->kv_entry.tqe_next) != ((void*)0)) (ckv)->
kv_entry.tqe_next->kv_entry.tqe_prev = (ckv)->kv_entry.
tqe_prev; else (&kv->kv_children)->tqh_last = (ckv)
->kv_entry.tqe_prev; *(ckv)->kv_entry.tqe_prev = (ckv)->
kv_entry.tqe_next; ; ; } while (0)
;
708 kv_free(ckv);
709 free(ckv);
710 }
711
712 kv_free(kv);
713 free(kv);
714}
715
716struct kv *
717kv_extend(struct kvtree *keys, struct kv *kv, char *value)
718{
719 char *newvalue;
720
721 if (kv == NULL((void*)0)) {
722 return (NULL((void*)0));
723 } else if (kv->kv_value != NULL((void*)0)) {
724 if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1)
725 return (NULL((void*)0));
726
727 free(kv->kv_value);
728 kv->kv_value = newvalue;
729 } else if ((kv->kv_value = strdup(value)) == NULL((void*)0))
730 return (NULL((void*)0));
731
732 return (kv);
733}
734
735void
736kv_purge(struct kvtree *keys)
737{
738 struct kv *kv;
739
740 while ((kv = RB_MIN(kvtree, keys)kvtree_RB_MINMAX(keys, -1)) != NULL((void*)0))
741 kv_delete(keys, kv);
742}
743
744void
745kv_free(struct kv *kv)
746{
747 /*
748 * This function does not clear memory referenced by
749 * kv_children or stuff on the tailqs. Use kv_delete() instead.
750 */
751
752 free(kv->kv_key);
753 free(kv->kv_value);
754 memset(kv, 0, sizeof(*kv));
755}
756
757struct kv *
758kv_inherit(struct kv *dst, struct kv *src)
759{
760 memset(dst, 0, sizeof(*dst));
761 memcpy(dst, src, sizeof(*dst));
762 TAILQ_INIT(&dst->kv_children)do { (&dst->kv_children)->tqh_first = ((void*)0); (
&dst->kv_children)->tqh_last = &(&dst->kv_children
)->tqh_first; } while (0)
;
763
764 if (src->kv_key != NULL((void*)0)) {
765 if ((dst->kv_key = strdup(src->kv_key)) == NULL((void*)0)) {
766 kv_free(dst);
767 return (NULL((void*)0));
768 }
769 }
770 if (src->kv_value != NULL((void*)0)) {
771 if ((dst->kv_value = strdup(src->kv_value)) == NULL((void*)0)) {
772 kv_free(dst);
773 return (NULL((void*)0));
774 }
775 }
776
777 if (src->kv_match != NULL((void*)0))
778 dst->kv_match = src->kv_match;
779 if (src->kv_matchtree != NULL((void*)0))
780 dst->kv_matchtree = src->kv_matchtree;
781
782 return (dst);
783}
784
785int
786kv_log(struct rsession *con, struct kv *kv, u_int16_t labelid,
787 enum direction dir)
788{
789 char *msg;
790
791 if (con->se_log == NULL((void*)0))
792 return (0);
793 if (asprintf(&msg, " %s%s%s%s%s%s%s",
794 dir == RELAY_DIR_REQUEST ? "[" : "{",
795 labelid == 0 ? "" : label_id2name(labelid),
796 labelid == 0 ? "" : ", ",
797 kv->kv_key == NULL((void*)0) ? "(unknown)" : kv->kv_key,
798 kv->kv_value == NULL((void*)0) ? "" : ": ",
799 kv->kv_value == NULL((void*)0) ? "" : kv->kv_value,
800 dir == RELAY_DIR_REQUEST ? "]" : "}") == -1)
801 return (-1);
802 if (evbuffer_add(con->se_log, msg, strlen(msg)) == -1) {
803 free(msg);
804 return (-1);
805 }
806 free(msg);
807 con->se_haslog = 1;
808 return (0);
809}
810
811struct kv *
812kv_find(struct kvtree *keys, struct kv *kv)
813{
814 struct kv *match;
815 const char *key;
816
817 if (kv->kv_flags & KV_FLAG_GLOBBING0x04) {
818 /* Test header key using shell globbing rules */
819 key = kv->kv_key == NULL((void*)0) ? "" : kv->kv_key;
820 RB_FOREACH(match, kvtree, keys)for ((match) = kvtree_RB_MINMAX(keys, -1); (match) != ((void*
)0); (match) = kvtree_RB_NEXT(match))
{
821 if (fnmatch(key, match->kv_key, FNM_CASEFOLD0x10) == 0)
822 break;
823 }
824 } else {
825 /* Fast tree-based lookup only works without globbing */
826 match = RB_FIND(kvtree, keys, kv)kvtree_RB_FIND(keys, kv);
827 }
828
829 return (match);
830}
831
832struct kv *
833kv_find_value(struct kvtree *keys, char *key, const char *value,
834 const char *delim)
835{
836 struct kv *match, kv;
837 char *val = NULL((void*)0), *next, *ptr;
838 size_t len;
839
840 kv.kv_key = key;
841 if ((match = RB_FIND(kvtree, keys, &kv)kvtree_RB_FIND(keys, &kv)) == NULL((void*)0))
842 return (NULL((void*)0));
843
844 if (match->kv_value == NULL((void*)0))
845 return (NULL((void*)0));
846
847 if (delim == NULL((void*)0)) {
848 if (strcasecmp(match->kv_value, value) == 0)
849 goto done;
850 } else {
851 if ((val = strdup(match->kv_value)) == NULL((void*)0))
852 return (NULL((void*)0));
853 for (next = ptr = val; ptr != NULL((void*)0);
854 ptr = strsep(&next, delim)) {
855 /* strip whitespace */
856 ptr += strspn(ptr, " \t");
857 len = strcspn(ptr, " \t");
858 if (strncasecmp(ptr, value, len) == 0)
859 goto done;
860 }
861 }
862
863 /* not matched */
864 match = NULL((void*)0);
865 done:
866#ifdef DEBUG
867 if (match != NULL((void*)0))
868 DPRINTF("%s: matched %s: %s", __func__, key, value)do {} while(0);
869#endif
870 free(val);
871 return (match);
872}
873
874int
875kv_cmp(struct kv *a, struct kv *b)
876{
877 return (strcasecmp(a->kv_key, b->kv_key));
878}
879
880RB_GENERATE(kvtree, kv, kv_node, kv_cmp)void kvtree_RB_INSERT_COLOR(struct kvtree *head, struct kv *elm
) { struct kv *parent, *gparent, *tmp; while ((parent = (elm)
->kv_node.rbe_parent) && (parent)->kv_node.rbe_color
== 1) { gparent = (parent)->kv_node.rbe_parent; if (parent
== (gparent)->kv_node.rbe_left) { tmp = (gparent)->kv_node
.rbe_right; if (tmp && (tmp)->kv_node.rbe_color ==
1) { (tmp)->kv_node.rbe_color = 0; do { (parent)->kv_node
.rbe_color = 0; (gparent)->kv_node.rbe_color = 1; } while (
0); elm = gparent; continue; } if ((parent)->kv_node.rbe_right
== elm) { do { (tmp) = (parent)->kv_node.rbe_right; if ((
(parent)->kv_node.rbe_right = (tmp)->kv_node.rbe_left))
{ ((tmp)->kv_node.rbe_left)->kv_node.rbe_parent = (parent
); } do {} while (0); if (((tmp)->kv_node.rbe_parent = (parent
)->kv_node.rbe_parent)) { if ((parent) == ((parent)->kv_node
.rbe_parent)->kv_node.rbe_left) ((parent)->kv_node.rbe_parent
)->kv_node.rbe_left = (tmp); else ((parent)->kv_node.rbe_parent
)->kv_node.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->kv_node.rbe_left = (parent); (parent)->kv_node
.rbe_parent = (tmp); do {} while (0); if (((tmp)->kv_node.
rbe_parent)) do {} while (0); } while (0); tmp = parent; parent
= elm; elm = tmp; } do { (parent)->kv_node.rbe_color = 0;
(gparent)->kv_node.rbe_color = 1; } while (0); do { (tmp)
= (gparent)->kv_node.rbe_left; if (((gparent)->kv_node
.rbe_left = (tmp)->kv_node.rbe_right)) { ((tmp)->kv_node
.rbe_right)->kv_node.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->kv_node.rbe_parent = (gparent)->kv_node
.rbe_parent)) { if ((gparent) == ((gparent)->kv_node.rbe_parent
)->kv_node.rbe_left) ((gparent)->kv_node.rbe_parent)->
kv_node.rbe_left = (tmp); else ((gparent)->kv_node.rbe_parent
)->kv_node.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->kv_node.rbe_right = (gparent); (gparent)->
kv_node.rbe_parent = (tmp); do {} while (0); if (((tmp)->kv_node
.rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent
)->kv_node.rbe_left; if (tmp && (tmp)->kv_node.
rbe_color == 1) { (tmp)->kv_node.rbe_color = 0; do { (parent
)->kv_node.rbe_color = 0; (gparent)->kv_node.rbe_color =
1; } while (0); elm = gparent; continue; } if ((parent)->
kv_node.rbe_left == elm) { do { (tmp) = (parent)->kv_node.
rbe_left; if (((parent)->kv_node.rbe_left = (tmp)->kv_node
.rbe_right)) { ((tmp)->kv_node.rbe_right)->kv_node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->kv_node.rbe_parent
= (parent)->kv_node.rbe_parent)) { if ((parent) == ((parent
)->kv_node.rbe_parent)->kv_node.rbe_left) ((parent)->
kv_node.rbe_parent)->kv_node.rbe_left = (tmp); else ((parent
)->kv_node.rbe_parent)->kv_node.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->kv_node.rbe_right = (
parent); (parent)->kv_node.rbe_parent = (tmp); do {} while
(0); if (((tmp)->kv_node.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
kv_node.rbe_color = 0; (gparent)->kv_node.rbe_color = 1; }
while (0); do { (tmp) = (gparent)->kv_node.rbe_right; if (
((gparent)->kv_node.rbe_right = (tmp)->kv_node.rbe_left
)) { ((tmp)->kv_node.rbe_left)->kv_node.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->kv_node.rbe_parent = (gparent
)->kv_node.rbe_parent)) { if ((gparent) == ((gparent)->
kv_node.rbe_parent)->kv_node.rbe_left) ((gparent)->kv_node
.rbe_parent)->kv_node.rbe_left = (tmp); else ((gparent)->
kv_node.rbe_parent)->kv_node.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->kv_node.rbe_left = (gparent
); (gparent)->kv_node.rbe_parent = (tmp); do {} while (0);
if (((tmp)->kv_node.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->kv_node.rbe_color = 0; } void
kvtree_RB_REMOVE_COLOR(struct kvtree *head, struct kv *parent
, struct kv *elm) { struct kv *tmp; while ((elm == ((void*)0)
|| (elm)->kv_node.rbe_color == 0) && elm != (head
)->rbh_root) { if ((parent)->kv_node.rbe_left == elm) {
tmp = (parent)->kv_node.rbe_right; if ((tmp)->kv_node.
rbe_color == 1) { do { (tmp)->kv_node.rbe_color = 0; (parent
)->kv_node.rbe_color = 1; } while (0); do { (tmp) = (parent
)->kv_node.rbe_right; if (((parent)->kv_node.rbe_right =
(tmp)->kv_node.rbe_left)) { ((tmp)->kv_node.rbe_left)->
kv_node.rbe_parent = (parent); } do {} while (0); if (((tmp)->
kv_node.rbe_parent = (parent)->kv_node.rbe_parent)) { if (
(parent) == ((parent)->kv_node.rbe_parent)->kv_node.rbe_left
) ((parent)->kv_node.rbe_parent)->kv_node.rbe_left = (tmp
); else ((parent)->kv_node.rbe_parent)->kv_node.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->kv_node
.rbe_left = (parent); (parent)->kv_node.rbe_parent = (tmp)
; do {} while (0); if (((tmp)->kv_node.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->kv_node.rbe_right; } if
(((tmp)->kv_node.rbe_left == ((void*)0) || ((tmp)->kv_node
.rbe_left)->kv_node.rbe_color == 0) && ((tmp)->
kv_node.rbe_right == ((void*)0) || ((tmp)->kv_node.rbe_right
)->kv_node.rbe_color == 0)) { (tmp)->kv_node.rbe_color =
1; elm = parent; parent = (elm)->kv_node.rbe_parent; } else
{ if ((tmp)->kv_node.rbe_right == ((void*)0) || ((tmp)->
kv_node.rbe_right)->kv_node.rbe_color == 0) { struct kv *oleft
; if ((oleft = (tmp)->kv_node.rbe_left)) (oleft)->kv_node
.rbe_color = 0; (tmp)->kv_node.rbe_color = 1; do { (oleft)
= (tmp)->kv_node.rbe_left; if (((tmp)->kv_node.rbe_left
= (oleft)->kv_node.rbe_right)) { ((oleft)->kv_node.rbe_right
)->kv_node.rbe_parent = (tmp); } do {} while (0); if (((oleft
)->kv_node.rbe_parent = (tmp)->kv_node.rbe_parent)) { if
((tmp) == ((tmp)->kv_node.rbe_parent)->kv_node.rbe_left
) ((tmp)->kv_node.rbe_parent)->kv_node.rbe_left = (oleft
); else ((tmp)->kv_node.rbe_parent)->kv_node.rbe_right =
(oleft); } else (head)->rbh_root = (oleft); (oleft)->kv_node
.rbe_right = (tmp); (tmp)->kv_node.rbe_parent = (oleft); do
{} while (0); if (((oleft)->kv_node.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->kv_node.rbe_right; } (tmp
)->kv_node.rbe_color = (parent)->kv_node.rbe_color; (parent
)->kv_node.rbe_color = 0; if ((tmp)->kv_node.rbe_right)
((tmp)->kv_node.rbe_right)->kv_node.rbe_color = 0; do {
(tmp) = (parent)->kv_node.rbe_right; if (((parent)->kv_node
.rbe_right = (tmp)->kv_node.rbe_left)) { ((tmp)->kv_node
.rbe_left)->kv_node.rbe_parent = (parent); } do {} while (
0); if (((tmp)->kv_node.rbe_parent = (parent)->kv_node.
rbe_parent)) { if ((parent) == ((parent)->kv_node.rbe_parent
)->kv_node.rbe_left) ((parent)->kv_node.rbe_parent)->
kv_node.rbe_left = (tmp); else ((parent)->kv_node.rbe_parent
)->kv_node.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->kv_node.rbe_left = (parent); (parent)->kv_node
.rbe_parent = (tmp); do {} while (0); if (((tmp)->kv_node.
rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root
; break; } } else { tmp = (parent)->kv_node.rbe_left; if (
(tmp)->kv_node.rbe_color == 1) { do { (tmp)->kv_node.rbe_color
= 0; (parent)->kv_node.rbe_color = 1; } while (0); do { (
tmp) = (parent)->kv_node.rbe_left; if (((parent)->kv_node
.rbe_left = (tmp)->kv_node.rbe_right)) { ((tmp)->kv_node
.rbe_right)->kv_node.rbe_parent = (parent); } do {} while (
0); if (((tmp)->kv_node.rbe_parent = (parent)->kv_node.
rbe_parent)) { if ((parent) == ((parent)->kv_node.rbe_parent
)->kv_node.rbe_left) ((parent)->kv_node.rbe_parent)->
kv_node.rbe_left = (tmp); else ((parent)->kv_node.rbe_parent
)->kv_node.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->kv_node.rbe_right = (parent); (parent)->
kv_node.rbe_parent = (tmp); do {} while (0); if (((tmp)->kv_node
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
kv_node.rbe_left; } if (((tmp)->kv_node.rbe_left == ((void
*)0) || ((tmp)->kv_node.rbe_left)->kv_node.rbe_color ==
0) && ((tmp)->kv_node.rbe_right == ((void*)0) || (
(tmp)->kv_node.rbe_right)->kv_node.rbe_color == 0)) { (
tmp)->kv_node.rbe_color = 1; elm = parent; parent = (elm)->
kv_node.rbe_parent; } else { if ((tmp)->kv_node.rbe_left ==
((void*)0) || ((tmp)->kv_node.rbe_left)->kv_node.rbe_color
== 0) { struct kv *oright; if ((oright = (tmp)->kv_node.rbe_right
)) (oright)->kv_node.rbe_color = 0; (tmp)->kv_node.rbe_color
= 1; do { (oright) = (tmp)->kv_node.rbe_right; if (((tmp)
->kv_node.rbe_right = (oright)->kv_node.rbe_left)) { ((
oright)->kv_node.rbe_left)->kv_node.rbe_parent = (tmp);
} do {} while (0); if (((oright)->kv_node.rbe_parent = (tmp
)->kv_node.rbe_parent)) { if ((tmp) == ((tmp)->kv_node.
rbe_parent)->kv_node.rbe_left) ((tmp)->kv_node.rbe_parent
)->kv_node.rbe_left = (oright); else ((tmp)->kv_node.rbe_parent
)->kv_node.rbe_right = (oright); } else (head)->rbh_root
= (oright); (oright)->kv_node.rbe_left = (tmp); (tmp)->
kv_node.rbe_parent = (oright); do {} while (0); if (((oright)
->kv_node.rbe_parent)) do {} while (0); } while (0); tmp =
(parent)->kv_node.rbe_left; } (tmp)->kv_node.rbe_color
= (parent)->kv_node.rbe_color; (parent)->kv_node.rbe_color
= 0; if ((tmp)->kv_node.rbe_left) ((tmp)->kv_node.rbe_left
)->kv_node.rbe_color = 0; do { (tmp) = (parent)->kv_node
.rbe_left; if (((parent)->kv_node.rbe_left = (tmp)->kv_node
.rbe_right)) { ((tmp)->kv_node.rbe_right)->kv_node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->kv_node.rbe_parent
= (parent)->kv_node.rbe_parent)) { if ((parent) == ((parent
)->kv_node.rbe_parent)->kv_node.rbe_left) ((parent)->
kv_node.rbe_parent)->kv_node.rbe_left = (tmp); else ((parent
)->kv_node.rbe_parent)->kv_node.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->kv_node.rbe_right = (
parent); (parent)->kv_node.rbe_parent = (tmp); do {} while
(0); if (((tmp)->kv_node.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
kv_node.rbe_color = 0; } struct kv * kvtree_RB_REMOVE(struct kvtree
*head, struct kv *elm) { struct kv *child, *parent, *old = elm
; int color; if ((elm)->kv_node.rbe_left == ((void*)0)) child
= (elm)->kv_node.rbe_right; else if ((elm)->kv_node.rbe_right
== ((void*)0)) child = (elm)->kv_node.rbe_left; else { struct
kv *left; elm = (elm)->kv_node.rbe_right; while ((left = (
elm)->kv_node.rbe_left)) elm = left; child = (elm)->kv_node
.rbe_right; parent = (elm)->kv_node.rbe_parent; color = (elm
)->kv_node.rbe_color; if (child) (child)->kv_node.rbe_parent
= parent; if (parent) { if ((parent)->kv_node.rbe_left ==
elm) (parent)->kv_node.rbe_left = child; else (parent)->
kv_node.rbe_right = child; do {} while (0); } else (head)->
rbh_root = child; if ((elm)->kv_node.rbe_parent == old) parent
= elm; (elm)->kv_node = (old)->kv_node; if ((old)->
kv_node.rbe_parent) { if (((old)->kv_node.rbe_parent)->
kv_node.rbe_left == old) ((old)->kv_node.rbe_parent)->kv_node
.rbe_left = elm; else ((old)->kv_node.rbe_parent)->kv_node
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; ((old)->kv_node.rbe_left)->kv_node.rbe_parent =
elm; if ((old)->kv_node.rbe_right) ((old)->kv_node.rbe_right
)->kv_node.rbe_parent = elm; if (parent) { left = parent; do
{ do {} while (0); } while ((left = (left)->kv_node.rbe_parent
)); } goto color; } parent = (elm)->kv_node.rbe_parent; color
= (elm)->kv_node.rbe_color; if (child) (child)->kv_node
.rbe_parent = parent; if (parent) { if ((parent)->kv_node.
rbe_left == elm) (parent)->kv_node.rbe_left = child; else (
parent)->kv_node.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) kvtree_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct kv * kvtree_RB_INSERT
(struct kvtree *head, struct kv *elm) { struct kv *tmp; struct
kv *parent = ((void*)0); int comp = 0; tmp = (head)->rbh_root
; while (tmp) { parent = tmp; comp = (kv_cmp)(elm, parent); if
(comp < 0) tmp = (tmp)->kv_node.rbe_left; else if (comp
> 0) tmp = (tmp)->kv_node.rbe_right; else return (tmp)
; } do { (elm)->kv_node.rbe_parent = parent; (elm)->kv_node
.rbe_left = (elm)->kv_node.rbe_right = ((void*)0); (elm)->
kv_node.rbe_color = 1; } while (0); if (parent != ((void*)0))
{ if (comp < 0) (parent)->kv_node.rbe_left = elm; else
(parent)->kv_node.rbe_right = elm; do {} while (0); } else
(head)->rbh_root = elm; kvtree_RB_INSERT_COLOR(head, elm)
; return (((void*)0)); } struct kv * kvtree_RB_FIND(struct kvtree
*head, struct kv *elm) { struct kv *tmp = (head)->rbh_root
; int comp; while (tmp) { comp = kv_cmp(elm, tmp); if (comp <
0) tmp = (tmp)->kv_node.rbe_left; else if (comp > 0) tmp
= (tmp)->kv_node.rbe_right; else return (tmp); } return (
((void*)0)); } struct kv * kvtree_RB_NFIND(struct kvtree *head
, struct kv *elm) { struct kv *tmp = (head)->rbh_root; struct
kv *res = ((void*)0); int comp; while (tmp) { comp = kv_cmp(
elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->kv_node
.rbe_left; } else if (comp > 0) tmp = (tmp)->kv_node.rbe_right
; else return (tmp); } return (res); } struct kv * kvtree_RB_NEXT
(struct kv *elm) { if ((elm)->kv_node.rbe_right) { elm = (
elm)->kv_node.rbe_right; while ((elm)->kv_node.rbe_left
) elm = (elm)->kv_node.rbe_left; } else { if ((elm)->kv_node
.rbe_parent && (elm == ((elm)->kv_node.rbe_parent)
->kv_node.rbe_left)) elm = (elm)->kv_node.rbe_parent; else
{ while ((elm)->kv_node.rbe_parent && (elm == ((elm
)->kv_node.rbe_parent)->kv_node.rbe_right)) elm = (elm)
->kv_node.rbe_parent; elm = (elm)->kv_node.rbe_parent; }
} return (elm); } struct kv * kvtree_RB_PREV(struct kv *elm)
{ if ((elm)->kv_node.rbe_left) { elm = (elm)->kv_node.
rbe_left; while ((elm)->kv_node.rbe_right) elm = (elm)->
kv_node.rbe_right; } else { if ((elm)->kv_node.rbe_parent &&
(elm == ((elm)->kv_node.rbe_parent)->kv_node.rbe_right
)) elm = (elm)->kv_node.rbe_parent; else { while ((elm)->
kv_node.rbe_parent && (elm == ((elm)->kv_node.rbe_parent
)->kv_node.rbe_left)) elm = (elm)->kv_node.rbe_parent; elm
= (elm)->kv_node.rbe_parent; } } return (elm); } struct kv
* kvtree_RB_MINMAX(struct kvtree *head, int val) { struct kv
*tmp = (head)->rbh_root; struct kv *parent = ((void*)0); while
(tmp) { parent = tmp; if (val < 0) tmp = (tmp)->kv_node
.rbe_left; else tmp = (tmp)->kv_node.rbe_right; } return (
parent); }
;
881
882int
883rule_add(struct protocol *proto, struct relay_rule *rule, const char *rulefile)
884{
885 struct relay_rule *r = NULL((void*)0);
886 struct kv *kv = NULL((void*)0);
887 FILE *fp = NULL((void*)0);
888 char buf[BUFSIZ1024];
889 int ret = -1;
890 u_int i;
891
892 for (i = 0; i < KEY_TYPE_MAX; i++) {
893 kv = &rule->rule_kv[i];
894 if (kv->kv_type != i)
895 continue;
896
897 switch (kv->kv_option) {
898 case KEY_OPTION_LOG:
899 /* log action needs a key or a file to be specified */
900 if (kv->kv_key == NULL((void*)0) && rulefile == NULL((void*)0) &&
901 (kv->kv_key = strdup("*")) == NULL((void*)0))
902 goto fail;
903 break;
904 default:
905 break;
906 }
907
908 switch (kv->kv_type) {
909 case KEY_TYPE_QUERY:
910 case KEY_TYPE_PATH:
911 case KEY_TYPE_URL:
912 if (rule->rule_dir != RELAY_DIR_REQUEST)
913 goto fail;
914 break;
915 default:
916 break;
917 }
918
919 if (kv->kv_value != NULL((void*)0) && strchr(kv->kv_value, '$') != NULL((void*)0))
920 kv->kv_flags |= KV_FLAG_MACRO0x01;
921 if (kv->kv_key != NULL((void*)0) && strpbrk(kv->kv_key, "*?[") != NULL((void*)0))
922 kv->kv_flags |= KV_FLAG_GLOBBING0x04;
923 }
924
925 if (rulefile == NULL((void*)0)) {
926 TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry)do { (rule)->rule_entry.tqe_next = ((void*)0); (rule)->
rule_entry.tqe_prev = (&proto->rules)->tqh_last; *(
&proto->rules)->tqh_last = (rule); (&proto->
rules)->tqh_last = &(rule)->rule_entry.tqe_next; } while
(0)
;
927 return (0);
928 }
929
930 if ((fp = fopen(rulefile, "r")) == NULL((void*)0))
931 goto fail;
932
933 while (fgets(buf, sizeof(buf), fp) != NULL((void*)0)) {
934 /* strip whitespace and newline characters */
935 buf[strcspn(buf, "\r\n\t ")] = '\0';
936 if (!strlen(buf) || buf[0] == '#')
937 continue;
938
939 if ((r = rule_inherit(rule)) == NULL((void*)0))
940 goto fail;
941
942 for (i = 0; i < KEY_TYPE_MAX; i++) {
943 kv = &r->rule_kv[i];
944 if (kv->kv_type != i)
945 continue;
946 free(kv->kv_key);
947 if ((kv->kv_key = strdup(buf)) == NULL((void*)0)) {
948 rule_free(r);
949 free(r);
950 goto fail;
951 }
952 }
953
954 TAILQ_INSERT_TAIL(&proto->rules, r, rule_entry)do { (r)->rule_entry.tqe_next = ((void*)0); (r)->rule_entry
.tqe_prev = (&proto->rules)->tqh_last; *(&proto
->rules)->tqh_last = (r); (&proto->rules)->tqh_last
= &(r)->rule_entry.tqe_next; } while (0)
;
955 }
956
957 ret = 0;
958 rule_free(rule);
959 free(rule);
960
961 fail:
962 if (fp != NULL((void*)0))
963 fclose(fp);
964 return (ret);
965}
966
967struct relay_rule *
968rule_inherit(struct relay_rule *rule)
969{
970 struct relay_rule *r;
971 u_int i;
972 struct kv *kv;
973
974 if ((r = calloc(1, sizeof(*r))) == NULL((void*)0))
975 return (NULL((void*)0));
976 memcpy(r, rule, sizeof(*r));
977
978 for (i = 0; i < KEY_TYPE_MAX; i++) {
979 kv = &rule->rule_kv[i];
980 if (kv->kv_type != i)
981 continue;
982 if (kv_inherit(&r->rule_kv[i], kv) == NULL((void*)0)) {
983 free(r);
984 return (NULL((void*)0));
985 }
986 }
987
988 if (r->rule_label > 0)
989 label_ref(r->rule_label);
990 if (r->rule_tag > 0)
991 tag_ref(r->rule_tag);
992 if (r->rule_tagged > 0)
993 tag_ref(r->rule_tagged);
994
995 return (r);
996}
997
998void
999rule_free(struct relay_rule *rule)
1000{
1001 u_int i;
1002
1003 for (i = 0; i < KEY_TYPE_MAX; i++)
1004 kv_free(&rule->rule_kv[i]);
1005 if (rule->rule_label > 0)
1006 label_unref(rule->rule_label);
1007 if (rule->rule_tag > 0)
1008 tag_unref(rule->rule_tag);
1009 if (rule->rule_tagged > 0)
1010 tag_unref(rule->rule_tagged);
1011}
1012
1013void
1014rule_delete(struct relay_rules *rules, struct relay_rule *rule)
1015{
1016 TAILQ_REMOVE(rules, rule, rule_entry)do { if (((rule)->rule_entry.tqe_next) != ((void*)0)) (rule
)->rule_entry.tqe_next->rule_entry.tqe_prev = (rule)->
rule_entry.tqe_prev; else (rules)->tqh_last = (rule)->rule_entry
.tqe_prev; *(rule)->rule_entry.tqe_prev = (rule)->rule_entry
.tqe_next; ; ; } while (0)
;
1017 rule_free(rule);
1018 free(rule);
1019}
1020
1021void
1022rule_settable(struct relay_rules *rules, struct relay_table *rlt)
1023{
1024 struct relay_rule *r;
1025 char pname[TABLE_NAME_SIZE64];
1026
1027 if (rlt->rlt_table == NULL((void*)0) || strlcpy(pname, rlt->rlt_table->conf.name,
1028 sizeof(pname)) >= sizeof(pname))
1029 return;
1030
1031 pname[strcspn(pname, ":")] = '\0';
1032
1033 TAILQ_FOREACH(r, rules, rule_entry)for((r) = ((rules)->tqh_first); (r) != ((void*)0); (r) = (
(r)->rule_entry.tqe_next))
{
1034 if (r->rule_tablename[0] &&
1035 strcmp(pname, r->rule_tablename) == 0)
1036 r->rule_table = rlt;
1037 }
1038}
1039
1040/*
1041 * Utility functions
1042 */
1043
1044struct host *
1045host_find(struct relayd *env, objid_t id)
1046{
1047 struct table *table;
1048 struct host *host;
1049
1050 TAILQ_FOREACH(table, env->sc_tables, entry)for((table) = ((env->sc_tables)->tqh_first); (table) !=
((void*)0); (table) = ((table)->entry.tqe_next))
1051 TAILQ_FOREACH(host, &table->hosts, entry)for((host) = ((&table->hosts)->tqh_first); (host) !=
((void*)0); (host) = ((host)->entry.tqe_next))
1052 if (host->conf.id == id)
1053 return (host);
1054 return (NULL((void*)0));
1055}
1056
1057struct table *
1058table_find(struct relayd *env, objid_t id)
1059{
1060 struct table *table;
1061
1062 TAILQ_FOREACH(table, env->sc_tables, entry)for((table) = ((env->sc_tables)->tqh_first); (table) !=
((void*)0); (table) = ((table)->entry.tqe_next))
1063 if (table->conf.id == id)
1064 return (table);
1065 return (NULL((void*)0));
1066}
1067
1068struct rdr *
1069rdr_find(struct relayd *env, objid_t id)
1070{
1071 struct rdr *rdr;
1072
1073 TAILQ_FOREACH(rdr, env->sc_rdrs, entry)for((rdr) = ((env->sc_rdrs)->tqh_first); (rdr) != ((void
*)0); (rdr) = ((rdr)->entry.tqe_next))
1074 if (rdr->conf.id == id)
1075 return (rdr);
1076 return (NULL((void*)0));
1077}
1078
1079struct relay *
1080relay_find(struct relayd *env, objid_t id)
1081{
1082 struct relay *rlay;
1083
1084 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)for((rlay) = ((env->sc_relays)->tqh_first); (rlay) != (
(void*)0); (rlay) = ((rlay)->rl_entry.tqe_next))
1085 if (rlay->rl_conf.id == id)
1086 return (rlay);
1087 return (NULL((void*)0));
1088}
1089
1090struct protocol *
1091proto_find(struct relayd *env, objid_t id)
1092{
1093 struct protocol *p;
1094
1095 TAILQ_FOREACH(p, env->sc_protos, entry)for((p) = ((env->sc_protos)->tqh_first); (p) != ((void*
)0); (p) = ((p)->entry.tqe_next))
1096 if (p->id == id)
1097 return (p);
1098 return (NULL((void*)0));
1099}
1100
1101struct rsession *
1102session_find(struct relayd *env, objid_t id)
1103{
1104 struct relay *rlay;
1105 struct rsession *con;
1106
1107 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)for((rlay) = ((env->sc_relays)->tqh_first); (rlay) != (
(void*)0); (rlay) = ((rlay)->rl_entry.tqe_next))
1108 SPLAY_FOREACH(con, session_tree, &rlay->rl_sessions)for ((con) = (((&rlay->rl_sessions)->sph_root == ((
void*)0)) ? ((void*)0) : session_tree_SPLAY_MIN_MAX(&rlay
->rl_sessions, -1)); (con) != ((void*)0); (con) = session_tree_SPLAY_NEXT
(&rlay->rl_sessions, con))
1109 if (con->se_id == id)
1110 return (con);
1111 return (NULL((void*)0));
1112}
1113
1114struct netroute *
1115route_find(struct relayd *env, objid_t id)
1116{
1117 struct netroute *nr;
1118
1119 TAILQ_FOREACH(nr, env->sc_routes, nr_route)for((nr) = ((env->sc_routes)->tqh_first); (nr) != ((void
*)0); (nr) = ((nr)->nr_route.tqe_next))
1120 if (nr->nr_conf.id == id)
1121 return (nr);
1122 return (NULL((void*)0));
1123}
1124
1125struct router *
1126router_find(struct relayd *env, objid_t id)
1127{
1128 struct router *rt;
1129
1130 TAILQ_FOREACH(rt, env->sc_rts, rt_entry)for((rt) = ((env->sc_rts)->tqh_first); (rt) != ((void*)
0); (rt) = ((rt)->rt_entry.tqe_next))
1131 if (rt->rt_conf.id == id)
1132 return (rt);
1133 return (NULL((void*)0));
1134}
1135
1136struct host *
1137host_findbyname(struct relayd *env, const char *name)
1138{
1139 struct table *table;
1140 struct host *host;
1141
1142 TAILQ_FOREACH(table, env->sc_tables, entry)for((table) = ((env->sc_tables)->tqh_first); (table) !=
((void*)0); (table) = ((table)->entry.tqe_next))
1143 TAILQ_FOREACH(host, &table->hosts, entry)for((host) = ((&table->hosts)->tqh_first); (host) !=
((void*)0); (host) = ((host)->entry.tqe_next))
1144 if (strcmp(host->conf.name, name) == 0)
1145 return (host);
1146 return (NULL((void*)0));
1147}
1148
1149struct table *
1150table_findbyname(struct relayd *env, const char *name)
1151{
1152 struct table *table;
1153
1154 TAILQ_FOREACH(table, env->sc_tables, entry)for((table) = ((env->sc_tables)->tqh_first); (table) !=
((void*)0); (table) = ((table)->entry.tqe_next))
1155 if (strcmp(table->conf.name, name) == 0)
1156 return (table);
1157 return (NULL((void*)0));
1158}
1159
1160struct table *
1161table_findbyconf(struct relayd *env, struct table *tb)
1162{
1163 struct table *table;
1164 struct table_config a, b;
1165
1166 bcopy(&tb->conf, &a, sizeof(a));
1167 a.id = a.rdrid = 0;
1168 a.flags &= ~(F_USED0x00000004|F_BACKUP0x00000002);
1169
1170 TAILQ_FOREACH(table, env->sc_tables, entry)for((table) = ((env->sc_tables)->tqh_first); (table) !=
((void*)0); (table) = ((table)->entry.tqe_next))
{
1171 bcopy(&table->conf, &b, sizeof(b));
1172 b.id = b.rdrid = 0;
1173 b.flags &= ~(F_USED0x00000004|F_BACKUP0x00000002);
1174
1175 /*
1176 * Compare two tables and return the existing table if
1177 * the configuration seems to be the same.
1178 */
1179 if (bcmp(&a, &b, sizeof(b)) == 0 &&
1180 ((tb->sendbuf == NULL((void*)0) && table->sendbuf == NULL((void*)0)) ||
1181 (tb->sendbuf != NULL((void*)0) && table->sendbuf != NULL((void*)0) &&
1182 strcmp(tb->sendbuf, table->sendbuf) == 0)))
1183 return (table);
1184 }
1185 return (NULL((void*)0));
1186}
1187
1188struct rdr *
1189rdr_findbyname(struct relayd *env, const char *name)
1190{
1191 struct rdr *rdr;
1192
1193 TAILQ_FOREACH(rdr, env->sc_rdrs, entry)for((rdr) = ((env->sc_rdrs)->tqh_first); (rdr) != ((void
*)0); (rdr) = ((rdr)->entry.tqe_next))
1194 if (strcmp(rdr->conf.name, name) == 0)
1195 return (rdr);
1196 return (NULL((void*)0));
1197}
1198
1199struct relay *
1200relay_findbyname(struct relayd *env, const char *name)
1201{
1202 struct relay *rlay;
1203
1204 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)for((rlay) = ((env->sc_relays)->tqh_first); (rlay) != (
(void*)0); (rlay) = ((rlay)->rl_entry.tqe_next))
1205 if (strcmp(rlay->rl_conf.name, name) == 0)
1206 return (rlay);
1207 return (NULL((void*)0));
1208}
1209
1210struct relay *
1211relay_findbyaddr(struct relayd *env, struct relay_config *rc)
1212{
1213 struct relay *rlay;
1214
1215 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)for((rlay) = ((env->sc_relays)->tqh_first); (rlay) != (
(void*)0); (rlay) = ((rlay)->rl_entry.tqe_next))
1216 if (bcmp(&rlay->rl_conf.ss, &rc->ss, sizeof(rc->ss)) == 0 &&
1217 rlay->rl_conf.port == rc->port)
1218 return (rlay);
1219 return (NULL((void*)0));
1220}
1221
1222EVP_PKEY *
1223pkey_find(struct relayd *env, char * hash)
1224{
1225 struct ca_pkey *pkey;
1226
1227 TAILQ_FOREACH(pkey, env->sc_pkeys, pkey_entry)for((pkey) = ((env->sc_pkeys)->tqh_first); (pkey) != ((
void*)0); (pkey) = ((pkey)->pkey_entry.tqe_next))
1228 if (strcmp(hash, pkey->pkey_hash) == 0)
1229 return (pkey->pkey);
1230 return (NULL((void*)0));
1231}
1232
1233struct ca_pkey *
1234pkey_add(struct relayd *env, EVP_PKEY *pkey, char *hash)
1235{
1236 struct ca_pkey *ca_pkey;
1237
1238 if (env->sc_pkeys == NULL((void*)0))
1239 fatalx("pkeys");
1240
1241 if ((ca_pkey = calloc(1, sizeof(*ca_pkey))) == NULL((void*)0))
1242 return (NULL((void*)0));
1243
1244 ca_pkey->pkey = pkey;
1245 if (strlcpy(ca_pkey->pkey_hash, hash, sizeof(ca_pkey->pkey_hash)) >=
1246 sizeof(ca_pkey->pkey_hash)) {
1247 free(ca_pkey);
1248 return (NULL((void*)0));
1249 }
1250
1251 TAILQ_INSERT_TAIL(env->sc_pkeys, ca_pkey, pkey_entry)do { (ca_pkey)->pkey_entry.tqe_next = ((void*)0); (ca_pkey
)->pkey_entry.tqe_prev = (env->sc_pkeys)->tqh_last; *
(env->sc_pkeys)->tqh_last = (ca_pkey); (env->sc_pkeys
)->tqh_last = &(ca_pkey)->pkey_entry.tqe_next; } while
(0)
;
1252
1253 return (ca_pkey);
1254}
1255
1256struct relay_cert *
1257cert_add(struct relayd *env, objid_t id)
1258{
1259 static objid_t last_cert_id = 0;
1260 struct relay_cert *cert;
1261
1262 if ((cert = calloc(1, sizeof(*cert))) == NULL((void*)0))
1263 return (NULL((void*)0));
1264
1265 if (id == 0)
1266 id = ++last_cert_id;
1267 if (id == INT_MAX2147483647) {
1268 log_warnx("too many tls keypairs defined");
1269 free(cert);
1270 return (NULL((void*)0));
1271 }
1272
1273 cert->cert_id = id;
1274 cert->cert_fd = -1;
1275 cert->cert_key_fd = -1;
1276 cert->cert_ocsp_fd = -1;
1277
1278 TAILQ_INSERT_TAIL(env->sc_certs, cert, cert_entry)do { (cert)->cert_entry.tqe_next = ((void*)0); (cert)->
cert_entry.tqe_prev = (env->sc_certs)->tqh_last; *(env->
sc_certs)->tqh_last = (cert); (env->sc_certs)->tqh_last
= &(cert)->cert_entry.tqe_next; } while (0)
;
1279
1280 return (cert);
1281}
1282
1283struct relay_cert *
1284cert_find(struct relayd *env, objid_t id)
1285{
1286 struct relay_cert *cert;
1287
1288 TAILQ_FOREACH(cert, env->sc_certs, cert_entry)for((cert) = ((env->sc_certs)->tqh_first); (cert) != ((
void*)0); (cert) = ((cert)->cert_entry.tqe_next))
1289 if (cert->cert_id == id)
1290 return (cert);
1291 return (NULL((void*)0));
1292}
1293
1294char *
1295relay_load_fd(int fd, off_t *len)
1296{
1297 char *buf = NULL((void*)0);
1298 struct stat st;
1299 off_t size;
1300 ssize_t rv;
1301 int err;
1302
1303 if (fstat(fd, &st) != 0)
1304 goto fail;
1305 size = st.st_size;
1306 if ((buf = calloc(1, size + 1)) == NULL((void*)0))
1307 goto fail;
1308 if ((rv = pread(fd, buf, size, 0)) != size)
1309 goto fail;
1310
1311 close(fd);
1312
1313 *len = size;
1314 return (buf);
1315
1316 fail:
1317 err = errno(*__errno());
1318 free(buf);
1319 close(fd);
1320 errno(*__errno()) = err;
1321 return (NULL((void*)0));
1322}
1323
1324int
1325relay_load_certfiles(struct relayd *env, struct relay *rlay, const char *name)
1326{
1327 char certfile[PATH_MAX1024];
1328 char hbuf[PATH_MAX1024];
1329 struct protocol *proto = rlay->rl_proto;
1330 struct relay_cert *cert;
1331 int useport = htons(rlay->rl_conf.port)(__uint16_t)(__builtin_constant_p(rlay->rl_conf.port) ? (__uint16_t
)(((__uint16_t)(rlay->rl_conf.port) & 0xffU) << 8
| ((__uint16_t)(rlay->rl_conf.port) & 0xff00U) >>
8) : __swap16md(rlay->rl_conf.port))
;
1332 int cert_fd = -1, key_fd = -1, ocsp_fd = -1;
1333
1334 if (rlay->rl_conf.flags & F_TLSCLIENT0x00200000) {
1335 if (strlen(proto->tlsca) && rlay->rl_tls_ca_fd == -1) {
1336 if ((rlay->rl_tls_ca_fd =
1337 open(proto->tlsca, O_RDONLY0x0000)) == -1)
1338 return (-1);
1339 log_debug("%s: using ca %s", __func__, proto->tlsca);
1340 }
1341 if (strlen(proto->tlscacert) && rlay->rl_tls_cacert_fd == -1) {
1342 if ((rlay->rl_tls_cacert_fd =
1343 open(proto->tlscacert, O_RDONLY0x0000)) == -1)
1344 return (-1);
1345 log_debug("%s: using ca certificate %s", __func__,
1346 proto->tlscacert);
1347 }
1348 if (strlen(proto->tlscakey) && !rlay->rl_conf.tls_cakey_len &&
1349 proto->tlscapass != NULL((void*)0)) {
1350 if ((rlay->rl_tls_cakey =
1351 ssl_load_key(env, proto->tlscakey,
1352 &rlay->rl_conf.tls_cakey_len,
1353 proto->tlscapass)) == NULL((void*)0))
1354 return (-1);
1355 log_debug("%s: using ca key %s", __func__,
1356 proto->tlscakey);
1357 }
1358 }
1359
1360 if ((rlay->rl_conf.flags & F_TLS0x00000800) == 0)
1361 return (0);
1362
1363 if (name == NULL((void*)0) &&
1364 print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL((void*)0))
1365 goto fail;
1366 else if (name != NULL((void*)0) &&
1367 strlcpy(hbuf, name, sizeof(hbuf)) >= sizeof(hbuf))
1368 goto fail;
1369
1370 if (snprintf(certfile, sizeof(certfile),
1371 "/etc/ssl/%s:%u.crt", hbuf, useport) == -1)
1372 goto fail;
1373 if ((cert_fd = open(certfile, O_RDONLY0x0000)) == -1) {
1374 if (snprintf(certfile, sizeof(certfile),
1375 "/etc/ssl/%s.crt", hbuf) == -1)
1376 goto fail;
1377 if ((cert_fd = open(certfile, O_RDONLY0x0000)) == -1)
1378 goto fail;
1379 useport = 0;
1380 }
1381 log_debug("%s: using certificate %s", __func__, certfile);
1382
1383 if (useport) {
1384 if (snprintf(certfile, sizeof(certfile),
1385 "/etc/ssl/private/%s:%u.key", hbuf, useport) == -1)
1386 goto fail;
1387 } else {
1388 if (snprintf(certfile, sizeof(certfile),
1389 "/etc/ssl/private/%s.key", hbuf) == -1)
1390 goto fail;
1391 }
1392 if ((key_fd = open(certfile, O_RDONLY0x0000)) == -1)
1393 goto fail;
1394 log_debug("%s: using private key %s", __func__, certfile);
1395
1396 if (useport) {
1397 if (snprintf(certfile, sizeof(certfile),
1398 "/etc/ssl/%s:%u.ocsp", hbuf, useport) == -1)
1399 goto fail;
1400 } else {
1401 if (snprintf(certfile, sizeof(certfile),
1402 "/etc/ssl/%s.ocsp", hbuf) == -1)
1403 goto fail;
1404 }
1405 if ((ocsp_fd = open(certfile, O_RDONLY0x0000)) != -1)
1406 log_debug("%s: using OCSP staple file %s", __func__, certfile);
1407
1408 if ((cert = cert_add(env, 0)) == NULL((void*)0))
1409 goto fail;
1410
1411 cert->cert_relayid = rlay->rl_conf.id;
1412 cert->cert_fd = cert_fd;
1413 cert->cert_key_fd = key_fd;
1414 cert->cert_ocsp_fd = ocsp_fd;
1415
1416 return (0);
1417
1418 fail:
1419 if (cert_fd != -1)
1420 close(cert_fd);
1421 if (key_fd != -1)
1422 close(key_fd);
1423 if (ocsp_fd != -1)
1424 close(ocsp_fd);
1425
1426 return (-1);
1427}
1428
1429void
1430event_again(struct event *ev, int fd, short event,
1431 void (*fn)(int, short, void *),
1432 struct timeval *start, struct timeval *end, void *arg)
1433{
1434 struct timeval tv_next, tv_now, tv;
1435
1436 getmonotime(&tv_now);
1437 bcopy(end, &tv_next, sizeof(tv_next));
1438 timersub(&tv_now, start, &tv_now)do { (&tv_now)->tv_sec = (&tv_now)->tv_sec - (start
)->tv_sec; (&tv_now)->tv_usec = (&tv_now)->tv_usec
- (start)->tv_usec; if ((&tv_now)->tv_usec < 0)
{ (&tv_now)->tv_sec--; (&tv_now)->tv_usec += 1000000
; } } while (0)
;
1439 timersub(&tv_next, &tv_now, &tv_next)do { (&tv_next)->tv_sec = (&tv_next)->tv_sec - (
&tv_now)->tv_sec; (&tv_next)->tv_usec = (&tv_next
)->tv_usec - (&tv_now)->tv_usec; if ((&tv_next)
->tv_usec < 0) { (&tv_next)->tv_sec--; (&tv_next
)->tv_usec += 1000000; } } while (0)
;
1440
1441 bzero(&tv, sizeof(tv));
1442 if (timercmp(&tv_next, &tv, >)(((&tv_next)->tv_sec == (&tv)->tv_sec) ? ((&
tv_next)->tv_usec > (&tv)->tv_usec) : ((&tv_next
)->tv_sec > (&tv)->tv_sec))
)
1443 bcopy(&tv_next, &tv, sizeof(tv));
1444
1445 event_del(ev);
1446 event_set(ev, fd, event, fn, arg);
1447 event_add(ev, &tv);
1448}
1449
1450int
1451expand_string(char *label, size_t len, const char *srch, const char *repl)
1452{
1453 char *tmp;
1454 char *p, *q;
1455
1456 if ((tmp = calloc(1, len)) == NULL((void*)0)) {
1457 log_debug("%s: calloc", __func__);
1458 return (-1);
1459 }
1460 p = q = label;
Although the value stored to 'q' is used in the enclosing expression, the value is never actually read from 'q'
1461 while ((q = strstr(p, srch)) != NULL((void*)0)) {
1462 *q = '\0';
1463 if ((strlcat(tmp, p, len) >= len) ||
1464 (strlcat(tmp, repl, len) >= len)) {
1465 log_debug("%s: string too long", __func__);
1466 free(tmp);
1467 return (-1);
1468 }
1469 q += strlen(srch);
1470 p = q;
1471 }
1472 if (strlcat(tmp, p, len) >= len) {
1473 log_debug("%s: string too long", __func__);
1474 free(tmp);
1475 return (-1);
1476 }
1477 (void)strlcpy(label, tmp, len); /* always fits */
1478 free(tmp);
1479
1480 return (0);
1481}
1482
1483void
1484translate_string(char *str)
1485{
1486 char *reader;
1487 char *writer;
1488
1489 reader = writer = str;
1490
1491 while (*reader) {
1492 if (*reader == '\\') {
1493 reader++;
1494 switch (*reader) {
1495 case 'n':
1496 *writer++ = '\n';
1497 break;
1498 case 'r':
1499 *writer++ = '\r';
1500 break;
1501 default:
1502 *writer++ = *reader;
1503 }
1504 } else
1505 *writer++ = *reader;
1506 reader++;
1507 }
1508 *writer = '\0';
1509}
1510
1511char *
1512digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf)
1513{
1514 switch (type) {
1515 case DIGEST_SHA1:
1516 return (SHA1Data(data, len, buf));
1517 break;
1518 case DIGEST_MD5:
1519 return (MD5Data(data, len, buf));
1520 break;
1521 default:
1522 break;
1523 }
1524 return (NULL((void*)0));
1525}
1526
1527const char *
1528canonicalize_host(const char *host, char *name, size_t len)
1529{
1530 struct sockaddr_in sin4;
1531 struct sockaddr_in6 sin6;
1532 size_t i, j;
1533 size_t plen;
1534 char c;
1535
1536 if (len < 2)
1537 goto fail;
1538
1539 /*
1540 * Canonicalize an IPv4/6 address
1541 */
1542 if (inet_pton(AF_INET2, host, &sin4) == 1)
1543 return (inet_ntop(AF_INET2, &sin4, name, len));
1544 if (inet_pton(AF_INET624, host, &sin6) == 1)
1545 return (inet_ntop(AF_INET624, &sin6, name, len));
1546
1547 /*
1548 * Canonicalize a hostname
1549 */
1550
1551 /* 1. remove repeated dots and convert upper case to lower case */
1552 plen = strlen(host);
1553 bzero(name, len);
1554 for (i = j = 0; i < plen; i++) {
1555 if (j >= (len - 1))
1556 goto fail;
1557 c = tolower((unsigned char)host[i]);
1558 if ((c == '.') && (j == 0 || name[j - 1] == '.'))
1559 continue;
1560 name[j++] = c;
1561 }
1562
1563 /* 2. remove trailing dots */
1564 for (i = j; i > 0; i--) {
1565 if (name[i - 1] != '.')
1566 break;
1567 name[i - 1] = '\0';
1568 j--;
1569 }
1570 if (j <= 0)
1571 goto fail;
1572
1573 return (name);
1574
1575 fail:
1576 errno(*__errno()) = EINVAL22;
1577 return (NULL((void*)0));
1578}
1579
1580int
1581parse_url(const char *url, char **protoptr, char **hostptr, char **pathptr)
1582{
1583 char *p, *proto = NULL((void*)0), *host = NULL((void*)0), *path = NULL((void*)0);
1584
1585 /* return error if it is not a URL */
1586 if ((p = strstr(url, ":/")) == NULL((void*)0) ||
1587 (strcspn(url, ":/") != (size_t)(p - url)))
1588 return (-1);
1589
1590 /* get protocol */
1591 if ((proto = strdup(url)) == NULL((void*)0))
1592 goto fail;
1593 p = proto + (p - url);
1594
1595 /* get host */
1596 p += strspn(p, ":/");
1597 if (*p == '\0' || (host = strdup(p)) == NULL((void*)0))
1598 goto fail;
1599 *p = '\0';
1600
1601 /* find and copy path or default to "/" */
1602 if ((p = strchr(host, '/')) == NULL((void*)0))
1603 p = "/";
1604 if ((path = strdup(p)) == NULL((void*)0))
1605 goto fail;
1606
1607 /* strip path after host */
1608 host[strcspn(host, "/")] = '\0';
1609
1610 DPRINTF("%s: %s proto %s, host %s, path %s", __func__,do {} while(0)
1611 url, proto, host, path)do {} while(0);
1612
1613 *protoptr = proto;
1614 *hostptr = host;
1615 *pathptr = path;
1616
1617 return (0);
1618
1619 fail:
1620 free(proto);
1621 free(host);
1622 free(path);
1623 return (-1);
1624}
1625
1626int
1627bindany(struct ctl_bindany *bnd)
1628{
1629 int s, v;
1630
1631 s = -1;
1632 v = 1;
1633
1634 if (relay_socket_af(&bnd->bnd_ss, bnd->bnd_port) == -1)
1635 goto fail;
1636 if ((s = socket(bnd->bnd_ss.ss_family,
1637 bnd->bnd_proto == IPPROTO_TCP6 ? SOCK_STREAM1 : SOCK_DGRAM2,
1638 bnd->bnd_proto)) == -1)
1639 goto fail;
1640 if (setsockopt(s, SOL_SOCKET0xffff, SO_BINDANY0x1000,
1641 &v, sizeof(v)) == -1)
1642 goto fail;
1643 if (bind(s, (struct sockaddr *)&bnd->bnd_ss,
1644 bnd->bnd_ss.ss_len) == -1)
1645 goto fail;
1646
1647 return (s);
1648
1649 fail:
1650 if (s != -1)
1651 close(s);
1652 return (-1);
1653}
1654
1655int
1656map6to4(struct sockaddr_storage *in6)
1657{
1658 struct sockaddr_storage out4;
1659 struct sockaddr_in *sin4 = (struct sockaddr_in *)&out4;
1660 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)in6;
1661
1662 bzero(sin4, sizeof(*sin4));
1663 sin4->sin_len = sizeof(*sin4);
1664 sin4->sin_family = AF_INET2;
1665 sin4->sin_port = sin6->sin6_port;
1666
1667 bcopy(&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], &sin4->sin_addr.s_addr,
1668 sizeof(sin4->sin_addr));
1669
1670 if (sin4->sin_addr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ||
1671 sin4->sin_addr.s_addr == INADDR_BROADCAST((u_int32_t)(0xffffffff)) ||
1672 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))(((u_int32_t)((__uint32_t)(__builtin_constant_p(sin4->sin_addr
.s_addr) ? (__uint32_t)(((__uint32_t)(sin4->sin_addr.s_addr
) & 0xff) << 24 | ((__uint32_t)(sin4->sin_addr.s_addr
) & 0xff00) << 8 | ((__uint32_t)(sin4->sin_addr.
s_addr) & 0xff0000) >> 8 | ((__uint32_t)(sin4->sin_addr
.s_addr) & 0xff000000) >> 24) : __swap32md(sin4->
sin_addr.s_addr))) & ((u_int32_t)(0xf0000000))) == ((u_int32_t
)(0xe0000000)))
)
1673 return (-1);
1674
1675 bcopy(&out4, in6, sizeof(*in6));
1676
1677 return (0);
1678}
1679
1680int
1681map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map)
1682{
1683 struct sockaddr_storage out6;
1684 struct sockaddr_in *sin4 = (struct sockaddr_in *)in4;
1685 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&out6;
1686 struct sockaddr_in6 *map6 = (struct sockaddr_in6 *)map;
1687
1688 if (sin4->sin_addr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ||
1689 sin4->sin_addr.s_addr == INADDR_BROADCAST((u_int32_t)(0xffffffff)) ||
1690 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))(((u_int32_t)((__uint32_t)(__builtin_constant_p(sin4->sin_addr
.s_addr) ? (__uint32_t)(((__uint32_t)(sin4->sin_addr.s_addr
) & 0xff) << 24 | ((__uint32_t)(sin4->sin_addr.s_addr
) & 0xff00) << 8 | ((__uint32_t)(sin4->sin_addr.
s_addr) & 0xff0000) >> 8 | ((__uint32_t)(sin4->sin_addr
.s_addr) & 0xff000000) >> 24) : __swap32md(sin4->
sin_addr.s_addr))) & ((u_int32_t)(0xf0000000))) == ((u_int32_t
)(0xe0000000)))
)
1691 return (-1);
1692
1693 bcopy(map6, sin6, sizeof(*sin6));
1694 sin6->sin6_len = sizeof(*sin6);
1695 sin6->sin6_family = AF_INET624;
1696 sin6->sin6_port = sin4->sin_port;
1697
1698 bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12],
1699 sizeof(sin4->sin_addr));
1700
1701 bcopy(&out6, in4, sizeof(*in4));
1702
1703 return (0);
1704}
1705
1706void
1707socket_rlimit(int maxfd)
1708{
1709 struct rlimit rl;
1710
1711 if (getrlimit(RLIMIT_NOFILE8, &rl) == -1)
1712 fatal("%s: failed to get resource limit", __func__);
1713 log_debug("%s: max open files %llu", __func__, rl.rlim_max);
1714
1715 /*
1716 * Allow the maximum number of open file descriptors for this
1717 * login class (which should be the class "daemon" by default).
1718 */
1719 if (maxfd == -1)
1720 rl.rlim_cur = rl.rlim_max;
1721 else
1722 rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd)(((rl.rlim_max) > ((rlim_t)maxfd)) ? (rl.rlim_max) : ((rlim_t
)maxfd))
;
1723 if (setrlimit(RLIMIT_NOFILE8, &rl) == -1)
1724 fatal("%s: failed to set resource limit", __func__);
1725}
1726
1727char *
1728get_string(u_int8_t *ptr, size_t len)
1729{
1730 size_t i;
1731
1732 for (i = 0; i < len; i++)
1733 if (!(isprint((unsigned char)ptr[i]) ||
1734 isspace((unsigned char)ptr[i])))
1735 break;
1736
1737 return strndup(ptr, i);
1738}
1739
1740void *
1741get_data(u_int8_t *ptr, size_t len)
1742{
1743 u_int8_t *data;
1744
1745 if ((data = malloc(len)) == NULL((void*)0))
1746 return (NULL((void*)0));
1747 memcpy(data, ptr, len);
1748
1749 return (data);
1750}
1751
1752int
1753sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
1754{
1755 struct sockaddr_in *a4, *b4;
1756 struct sockaddr_in6 *a6, *b6;
1757 u_int32_t av[4], bv[4], mv[4];
1758
1759 if (a->sa_family == AF_UNSPEC0 || b->sa_family == AF_UNSPEC0)
1760 return (0);
1761 else if (a->sa_family > b->sa_family)
1762 return (1);
1763 else if (a->sa_family < b->sa_family)
1764 return (-1);
1765
1766 if (prefixlen == -1)
1767 memset(&mv, 0xff, sizeof(mv));
1768
1769 switch (a->sa_family) {
1770 case AF_INET2:
1771 a4 = (struct sockaddr_in *)a;
1772 b4 = (struct sockaddr_in *)b;
1773
1774 av[0] = a4->sin_addr.s_addr;
1775 bv[0] = b4->sin_addr.s_addr;
1776 if (prefixlen != -1)
1777 mv[0] = prefixlen2mask(prefixlen);
1778
1779 if ((av[0] & mv[0]) > (bv[0] & mv[0]))
1780 return (1);
1781 if ((av[0] & mv[0]) < (bv[0] & mv[0]))
1782 return (-1);
1783 break;
1784 case AF_INET624:
1785 a6 = (struct sockaddr_in6 *)a;
1786 b6 = (struct sockaddr_in6 *)b;
1787
1788 memcpy(&av, &a6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16);
1789 memcpy(&bv, &b6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16);
1790 if (prefixlen != -1)
1791 prefixlen2mask6(prefixlen, mv);
1792
1793 if ((av[3] & mv[3]) > (bv[3] & mv[3]))
1794 return (1);
1795 if ((av[3] & mv[3]) < (bv[3] & mv[3]))
1796 return (-1);
1797 if ((av[2] & mv[2]) > (bv[2] & mv[2]))
1798 return (1);
1799 if ((av[2] & mv[2]) < (bv[2] & mv[2]))
1800 return (-1);
1801 if ((av[1] & mv[1]) > (bv[1] & mv[1]))
1802 return (1);
1803 if ((av[1] & mv[1]) < (bv[1] & mv[1]))
1804 return (-1);
1805 if ((av[0] & mv[0]) > (bv[0] & mv[0]))
1806 return (1);
1807 if ((av[0] & mv[0]) < (bv[0] & mv[0]))
1808 return (-1);
1809 break;
1810 }
1811
1812 return (0);
1813}
1814
1815u_int32_t
1816prefixlen2mask(u_int8_t prefixlen)
1817{
1818 if (prefixlen == 0)
1819 return (0);
1820
1821 if (prefixlen > 32)
1822 prefixlen = 32;
1823
1824 return (htonl(0xffffffff << (32 - prefixlen))(__uint32_t)(__builtin_constant_p(0xffffffff << (32 - prefixlen
)) ? (__uint32_t)(((__uint32_t)(0xffffffff << (32 - prefixlen
)) & 0xff) << 24 | ((__uint32_t)(0xffffffff <<
(32 - prefixlen)) & 0xff00) << 8 | ((__uint32_t)(0xffffffff
<< (32 - prefixlen)) & 0xff0000) >> 8 | ((__uint32_t
)(0xffffffff << (32 - prefixlen)) & 0xff000000) >>
24) : __swap32md(0xffffffff << (32 - prefixlen)))
);
1825}
1826
1827struct in6_addr *
1828prefixlen2mask6(u_int8_t prefixlen, u_int32_t *mask)
1829{
1830 static struct in6_addr s6;
1831 int i;
1832
1833 if (prefixlen > 128)
1834 prefixlen = 128;
1835
1836 bzero(&s6, sizeof(s6));
1837 for (i = 0; i < prefixlen / 8; i++)
1838 s6.s6_addr__u6_addr.__u6_addr8[i] = 0xff;
1839 i = prefixlen % 8;
1840 if (i)
1841 s6.s6_addr__u6_addr.__u6_addr8[prefixlen / 8] = 0xff00 >> i;
1842
1843 memcpy(mask, &s6, sizeof(s6));
1844
1845 return (&s6);
1846}
1847
1848int
1849accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
1850 int reserve, volatile int *counter)
1851{
1852 int ret;
1853 if (getdtablecount() + reserve +
1854 *counter >= getdtablesize()) {
1855 errno(*__errno()) = EMFILE24;
1856 return (-1);
1857 }
1858
1859 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK0x4000)) > -1) {
1860 (*counter)++;
1861 DPRINTF("%s: inflight incremented, now %d",__func__, *counter)do {} while(0);
1862 }
1863 return (ret);
1864}
1865
1866void
1867parent_tls_ticket_rekey(int fd, short events, void *arg)
1868{
1869 static struct event rekeyev;
1870 struct relayd *env = arg;
1871 struct timeval tv;
1872 struct relay_ticket_key key;
1873
1874 log_debug("%s: rekeying tickets", __func__);
1875
1876 key.tt_keyrev = arc4random();
1877 arc4random_buf(key.tt_key, sizeof(key.tt_key));
1878
1879 proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_TLSTICKET_REKEY,
1880 -1, -1, &key, sizeof(key));
1881
1882 evtimer_set(&rekeyev, parent_tls_ticket_rekey, env)event_set(&rekeyev, -1, 0, parent_tls_ticket_rekey, env);
1883 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
1884 tv.tv_sec = TLS_SESSION_LIFETIME(2 * 3600) / 4;
1885 evtimer_add(&rekeyev, &tv)event_add(&rekeyev, &tv);
1886}