Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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