xref: /openbsd-src/usr.sbin/relayd/relayd.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: relayd.c,v 1.104 2011/09/04 20:26:58 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2007, 2008 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/wait.h>
24 #include <sys/resource.h>
25 #include <sys/hash.h>
26 
27 #include <net/if.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <fcntl.h>
35 #include <getopt.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <event.h>
39 #include <unistd.h>
40 #include <ctype.h>
41 #include <pwd.h>
42 #include <sha1.h>
43 #include <md5.h>
44 
45 #include <openssl/ssl.h>
46 
47 #include "relayd.h"
48 
49 __dead void	 usage(void);
50 
51 int		 parent_configure(struct relayd *);
52 void		 parent_reload(struct relayd *, u_int, const char *);
53 void		 parent_sig_handler(int, short, void *);
54 void		 parent_shutdown(struct relayd *);
55 int		 parent_dispatch_pfe(int, struct privsep_proc *, struct imsg *);
56 int		 parent_dispatch_hce(int, struct privsep_proc *, struct imsg *);
57 int		 parent_dispatch_relay(int, struct privsep_proc *,
58 		    struct imsg *);
59 int		 bindany(struct ctl_bindany *);
60 
61 struct relayd			*relayd_env;
62 
63 static struct privsep_proc procs[] = {
64 	{ "pfe",	PROC_PFE, parent_dispatch_pfe, pfe },
65 	{ "hce",	PROC_HCE, parent_dispatch_hce, hce },
66 	{ "relay",	PROC_RELAY, parent_dispatch_relay, relay }
67 };
68 
69 void
70 parent_sig_handler(int sig, short event, void *arg)
71 {
72 	struct privsep	*ps = arg;
73 	int		 die = 0, status, fail, id;
74 	pid_t		 pid;
75 	char		*cause;
76 
77 	switch (sig) {
78 	case SIGTERM:
79 	case SIGINT:
80 		die = 1;
81 		/* FALLTHROUGH */
82 	case SIGCHLD:
83 		do {
84 			pid = waitpid(WAIT_ANY, &status, WNOHANG);
85 			if (pid <= 0)
86 				continue;
87 
88 			fail = 0;
89 			if (WIFSIGNALED(status)) {
90 				fail = 1;
91 				asprintf(&cause, "terminated; signal %d",
92 				    WTERMSIG(status));
93 			} else if (WIFEXITED(status)) {
94 				if (WEXITSTATUS(status) != 0) {
95 					fail = 1;
96 					asprintf(&cause, "exited abnormally");
97 				} else
98 					asprintf(&cause, "exited okay");
99 			} else
100 				fatalx("unexpected cause of SIGCHLD");
101 
102 			die = 1;
103 
104 			for (id = 0; id < PROC_MAX; id++)
105 				if (pid == ps->ps_pid[id]) {
106 					log_warnx("lost child: %s %s",
107 					    ps->ps_title[id], cause);
108 					break;
109 				}
110 
111 			free(cause);
112 		} while (pid > 0 || (pid == -1 && errno == EINTR));
113 
114 		if (die)
115 			parent_shutdown(ps->ps_env);
116 		break;
117 	case SIGHUP:
118 		log_info("%s: reload requested with SIGHUP", __func__);
119 
120 		/*
121 		 * This is safe because libevent uses async signal handlers
122 		 * that run in the event loop and not in signal context.
123 		 */
124 		parent_reload(ps->ps_env, CONFIG_RELOAD, NULL);
125 		break;
126 	case SIGPIPE:
127 		/* ignore */
128 		break;
129 	default:
130 		fatalx("unexpected signal");
131 	}
132 }
133 
134 /* __dead is for lint */
135 __dead void
136 usage(void)
137 {
138 	extern char	*__progname;
139 
140 	fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
141 	    __progname);
142 	exit(1);
143 }
144 
145 int
146 main(int argc, char *argv[])
147 {
148 	int			 c;
149 	int			 debug = 0, verbose = 0;
150 	u_int32_t		 opts = 0;
151 	struct relayd		*env;
152 	struct privsep		*ps;
153 	const char		*conffile = CONF_FILE;
154 
155 	while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
156 		switch (c) {
157 		case 'd':
158 			debug = 2;
159 			break;
160 		case 'D':
161 			if (cmdline_symset(optarg) < 0)
162 				log_warnx("could not parse macro definition %s",
163 				    optarg);
164 			break;
165 		case 'n':
166 			debug = 2;
167 			opts |= RELAYD_OPT_NOACTION;
168 			break;
169 		case 'f':
170 			conffile = optarg;
171 			break;
172 		case 'v':
173 			verbose++;
174 			opts |= RELAYD_OPT_VERBOSE;
175 			break;
176 		default:
177 			usage();
178 		}
179 	}
180 
181 	log_init(debug ? debug : 1);	/* log to stderr until daemonized */
182 
183 	argc -= optind;
184 	argv += optind;
185 	if (argc > 0)
186 		usage();
187 
188 	if ((env = calloc(1, sizeof(*env))) == NULL ||
189 	    (ps = calloc(1, sizeof(*ps))) == NULL)
190 		exit(1);
191 
192 	relayd_env = env;
193 	env->sc_ps = ps;
194 	ps->ps_env = env;
195 	env->sc_conffile = conffile;
196 	env->sc_opts = opts;
197 
198 	if (parse_config(env->sc_conffile, env) == -1)
199 		exit(1);
200 
201 	if (debug)
202 		env->sc_opts |= RELAYD_OPT_LOGUPDATE;
203 
204 	if (geteuid())
205 		errx(1, "need root privileges");
206 
207 	if ((ps->ps_pw =  getpwnam(RELAYD_USER)) == NULL)
208 		errx(1, "unknown user %s", RELAYD_USER);
209 
210 	/* Configure the control socket */
211 	ps->ps_csock.cs_name = RELAYD_SOCKET;
212 
213 	log_init(debug);
214 	log_verbose(verbose);
215 
216 	if (!debug && daemon(1, 0) == -1)
217 		err(1, "failed to daemonize");
218 
219 	if (env->sc_opts & RELAYD_OPT_NOACTION)
220 		ps->ps_noaction = 1;
221 	else
222 		log_info("startup");
223 
224 	ps->ps_instances[PROC_RELAY] = env->sc_prefork_relay;
225 	proc_init(ps, procs, nitems(procs));
226 
227 	setproctitle("parent");
228 
229 	event_init();
230 
231 	signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
232 	signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
233 	signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
234 	signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
235 	signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
236 
237 	signal_add(&ps->ps_evsigint, NULL);
238 	signal_add(&ps->ps_evsigterm, NULL);
239 	signal_add(&ps->ps_evsigchld, NULL);
240 	signal_add(&ps->ps_evsighup, NULL);
241 	signal_add(&ps->ps_evsigpipe, NULL);
242 
243 	proc_config(ps, procs, nitems(procs));
244 
245 	if (load_config(env->sc_conffile, env) == -1) {
246 		proc_kill(env->sc_ps);
247 		exit(1);
248 	}
249 
250 	if (env->sc_opts & RELAYD_OPT_NOACTION) {
251 		fprintf(stderr, "configuration OK\n");
252 		proc_kill(env->sc_ps);
253 		exit(0);
254 	}
255 
256 	if (env->sc_flags & (F_SSL|F_SSLCLIENT))
257 		ssl_init(env);
258 
259 	if (parent_configure(env) == -1)
260 		fatalx("configuration failed");
261 
262 	init_routes(env);
263 
264 	event_dispatch();
265 
266 	parent_shutdown(env);
267 	/* NOTREACHED */
268 
269 	return (0);
270 }
271 
272 int
273 parent_configure(struct relayd *env)
274 {
275 	struct table		*tb;
276 	struct rdr		*rdr;
277 	struct router		*rt;
278 	struct protocol		*proto;
279 	struct relay		*rlay;
280 	int			 id;
281 	struct ctl_flags	 cf;
282 	int			 s, ret = -1;
283 
284 	TAILQ_FOREACH(tb, env->sc_tables, entry)
285 		config_settable(env, tb);
286 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
287 		config_setrdr(env, rdr);
288 	TAILQ_FOREACH(rt, env->sc_rts, rt_entry)
289 		config_setrt(env, rt);
290 	TAILQ_FOREACH(proto, env->sc_protos, entry)
291 		config_setproto(env, proto);
292 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
293 		config_setrelay(env, rlay);
294 
295 	for (id = 0; id < PROC_MAX; id++) {
296 		if (id == privsep_process)
297 			continue;
298 		cf.cf_opts = env->sc_opts;
299 		cf.cf_flags = env->sc_flags;
300 
301 		if ((env->sc_flags & F_NEEDPF) && id == PROC_PFE) {
302 			/* Send pf socket to the pf engine */
303 			if ((s = open(PF_SOCKET, O_RDWR)) == -1) {
304 				log_debug("%s: cannot open pf socket",
305 				    __func__);
306 				goto done;
307 			}
308 		} else
309 			s = -1;
310 
311 		env->sc_reload++;
312 		proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s,
313 		    &cf, sizeof(cf));
314 	}
315 
316 	ret = 0;
317 
318  done:
319 	config_purge(env, CONFIG_ALL);
320 	return (ret);
321 }
322 
323 void
324 parent_reload(struct relayd *env, u_int reset, const char *filename)
325 {
326 	if (env->sc_reload) {
327 		log_debug("%s: already in progress: %d pending",
328 		    __func__, env->sc_reload);
329 		return;
330 	}
331 
332 	/* Switch back to the default config file */
333 	if (filename == NULL || *filename == '\0')
334 		filename = env->sc_conffile;
335 
336 	log_debug("%s: level %d config file %s", __func__, reset, filename);
337 
338 	config_purge(env, CONFIG_ALL);
339 
340 	if (reset == CONFIG_RELOAD) {
341 		if (load_config(filename, env) == -1) {
342 			log_debug("%s: failed to load config file %s",
343 			    __func__, filename);
344 		}
345 
346 		config_setreset(env, CONFIG_ALL);
347 
348 		if (parent_configure(env) == -1) {
349 			log_debug("%s: failed to commit config from %s",
350 			    __func__, filename);
351 		}
352 	} else
353 		config_setreset(env, reset);
354 }
355 
356 void
357 parent_shutdown(struct relayd *env)
358 {
359 	config_purge(env, CONFIG_ALL);
360 
361 	proc_kill(env->sc_ps);
362 	control_cleanup(&env->sc_ps->ps_csock);
363 	carp_demote_shutdown();
364 	if (env->sc_flags & F_DEMOTE)
365 		carp_demote_reset(env->sc_demote_group, 128);
366 
367 	free(env->sc_ps);
368 	free(env);
369 
370 	log_info("parent terminating, pid %d", getpid());
371 
372 	exit(0);
373 }
374 
375 int
376 parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
377 {
378 	struct relayd		*env = p->p_env;
379 	struct ctl_demote	 demote;
380 	struct ctl_netroute	 crt;
381 	u_int			 v;
382 	char			*str = NULL;
383 
384 	switch (imsg->hdr.type) {
385 	case IMSG_DEMOTE:
386 		IMSG_SIZE_CHECK(imsg, &demote);
387 		memcpy(&demote, imsg->data, sizeof(demote));
388 		carp_demote_set(demote.group, demote.level);
389 		break;
390 	case IMSG_RTMSG:
391 		IMSG_SIZE_CHECK(imsg, &crt);
392 		memcpy(&crt, imsg->data, sizeof(crt));
393 		pfe_route(env, &crt);
394 		break;
395 	case IMSG_CTL_RESET:
396 		IMSG_SIZE_CHECK(imsg, &v);
397 		memcpy(&v, imsg->data, sizeof(v));
398 		parent_reload(env, v, NULL);
399 		break;
400 	case IMSG_CTL_RELOAD:
401 		if (IMSG_DATA_SIZE(imsg) > 0)
402 			str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
403 		parent_reload(env, CONFIG_RELOAD, str);
404 		if (str != NULL)
405 			free(str);
406 		break;
407 	case IMSG_CTL_SHUTDOWN:
408 		parent_shutdown(env);
409 		break;
410 	case IMSG_CFG_DONE:
411 		if (env->sc_reload)
412 			env->sc_reload--;
413 		break;
414 	default:
415 		return (-1);
416 	}
417 
418 	return (0);
419 }
420 
421 int
422 parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
423 {
424 	struct relayd		*env = p->p_env;
425 	struct privsep		*ps = env->sc_ps;
426 	struct ctl_script	 scr;
427 
428 	switch (imsg->hdr.type) {
429 	case IMSG_SCRIPT:
430 		IMSG_SIZE_CHECK(imsg, &scr);
431 		bcopy(imsg->data, &scr, sizeof(scr));
432 		scr.retval = script_exec(env, &scr);
433 		proc_compose_imsg(ps, PROC_HCE, -1, IMSG_SCRIPT,
434 		    -1, &scr, sizeof(scr));
435 		break;
436 	case IMSG_SNMPSOCK:
437 		(void)snmp_setsock(env, p->p_id);
438 		break;
439 	case IMSG_CFG_DONE:
440 		if (env->sc_reload)
441 			env->sc_reload--;
442 		break;
443 	default:
444 		return (-1);
445 	}
446 
447 	return (0);
448 }
449 
450 int
451 parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
452 {
453 	struct relayd		*env = p->p_env;
454 	struct privsep		*ps = env->sc_ps;
455 	struct ctl_bindany	 bnd;
456 	int			 s;
457 
458 	switch (imsg->hdr.type) {
459 	case IMSG_BINDANY:
460 		IMSG_SIZE_CHECK(imsg, &bnd);
461 		bcopy(imsg->data, &bnd, sizeof(bnd));
462 		if (bnd.bnd_proc > env->sc_prefork_relay)
463 			fatalx("pfe_dispatch_relay: "
464 			    "invalid relay proc");
465 		switch (bnd.bnd_proto) {
466 		case IPPROTO_TCP:
467 		case IPPROTO_UDP:
468 			break;
469 		default:
470 			fatalx("pfe_dispatch_relay: requested socket "
471 			    "for invalid protocol");
472 			/* NOTREACHED */
473 		}
474 		s = bindany(&bnd);
475 		proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc,
476 		    IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
477 		break;
478 	case IMSG_CFG_DONE:
479 		if (env->sc_reload)
480 			env->sc_reload--;
481 		break;
482 	default:
483 		return (-1);
484 	}
485 
486 	return (0);
487 }
488 
489 void
490 purge_tree(struct proto_tree *tree)
491 {
492 	struct protonode	*proot, *pn;
493 
494 	while ((proot = RB_ROOT(tree)) != NULL) {
495 		RB_REMOVE(proto_tree, tree, proot);
496 		if (proot->key != NULL)
497 			free(proot->key);
498 		if (proot->value != NULL)
499 			free(proot->value);
500 		while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) {
501 			SIMPLEQ_REMOVE_HEAD(&proot->head, entry);
502 			if (pn->key != NULL)
503 				free(pn->key);
504 			if (pn->value != NULL)
505 				free(pn->value);
506 			if (pn->label != 0)
507 				pn_unref(pn->label);
508 			free(pn);
509 		}
510 		free(proot);
511 	}
512 }
513 
514 void
515 purge_table(struct tablelist *head, struct table *table)
516 {
517 	struct host		*host;
518 
519 	while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
520 		TAILQ_REMOVE(&table->hosts, host, entry);
521 		if (event_initialized(&host->cte.ev)) {
522 			event_del(&host->cte.ev);
523 			close(host->cte.s);
524 		}
525 		if (host->cte.buf != NULL)
526 			ibuf_free(host->cte.buf);
527 		if (host->cte.ssl != NULL)
528 			SSL_free(host->cte.ssl);
529 		free(host);
530 	}
531 	if (table->sendbuf != NULL)
532 		free(table->sendbuf);
533 	if (table->conf.flags & F_SSL)
534 		SSL_CTX_free(table->ssl_ctx);
535 
536 	if (head != NULL)
537 		TAILQ_REMOVE(head, table, entry);
538 	free(table);
539 }
540 
541 void
542 purge_relay(struct relayd *env, struct relay *rlay)
543 {
544 	struct rsession		*con;
545 
546 	/* shutdown and remove relay */
547 	if (event_initialized(&rlay->rl_ev))
548 		event_del(&rlay->rl_ev);
549 	close(rlay->rl_s);
550 	TAILQ_REMOVE(env->sc_relays, rlay, rl_entry);
551 
552 	/* cleanup sessions */
553 	while ((con =
554 	    SPLAY_ROOT(&rlay->rl_sessions)) != NULL)
555 		relay_close(con, NULL);
556 
557 	/* cleanup relay */
558 	if (rlay->rl_bev != NULL)
559 		bufferevent_free(rlay->rl_bev);
560 	if (rlay->rl_dstbev != NULL)
561 		bufferevent_free(rlay->rl_dstbev);
562 
563 	if (rlay->rl_ssl_ctx != NULL)
564 		SSL_CTX_free(rlay->rl_ssl_ctx);
565 	if (rlay->rl_ssl_cert != NULL)
566 		free(rlay->rl_ssl_cert);
567 	if (rlay->rl_ssl_key != NULL)
568 		free(rlay->rl_ssl_key);
569 	if (rlay->rl_ssl_ca != NULL)
570 		free(rlay->rl_ssl_ca);
571 
572 	free(rlay);
573 }
574 
575 /*
576  * Utility functions
577  */
578 
579 struct host *
580 host_find(struct relayd *env, objid_t id)
581 {
582 	struct table	*table;
583 	struct host	*host;
584 
585 	TAILQ_FOREACH(table, env->sc_tables, entry)
586 		TAILQ_FOREACH(host, &table->hosts, entry)
587 			if (host->conf.id == id)
588 				return (host);
589 	return (NULL);
590 }
591 
592 struct table *
593 table_find(struct relayd *env, objid_t id)
594 {
595 	struct table	*table;
596 
597 	TAILQ_FOREACH(table, env->sc_tables, entry)
598 		if (table->conf.id == id)
599 			return (table);
600 	return (NULL);
601 }
602 
603 struct rdr *
604 rdr_find(struct relayd *env, objid_t id)
605 {
606 	struct rdr	*rdr;
607 
608 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
609 		if (rdr->conf.id == id)
610 			return (rdr);
611 	return (NULL);
612 }
613 
614 struct relay *
615 relay_find(struct relayd *env, objid_t id)
616 {
617 	struct relay	*rlay;
618 
619 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
620 		if (rlay->rl_conf.id == id)
621 			return (rlay);
622 	return (NULL);
623 }
624 
625 struct protocol *
626 proto_find(struct relayd *env, objid_t id)
627 {
628 	struct protocol	*p;
629 
630 	TAILQ_FOREACH(p, env->sc_protos, entry)
631 		if (p->id == id)
632 			return (p);
633 	return (NULL);
634 }
635 
636 struct rsession *
637 session_find(struct relayd *env, objid_t id)
638 {
639 	struct relay		*rlay;
640 	struct rsession		*con;
641 
642 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
643 		SPLAY_FOREACH(con, session_tree, &rlay->rl_sessions)
644 			if (con->se_id == id)
645 				return (con);
646 	return (NULL);
647 }
648 
649 struct netroute *
650 route_find(struct relayd *env, objid_t id)
651 {
652 	struct netroute	*nr;
653 
654 	TAILQ_FOREACH(nr, env->sc_routes, nr_route)
655 		if (nr->nr_conf.id == id)
656 			return (nr);
657 	return (NULL);
658 }
659 
660 struct router *
661 router_find(struct relayd *env, objid_t id)
662 {
663 	struct router	*rt;
664 
665 	TAILQ_FOREACH(rt, env->sc_rts, rt_entry)
666 		if (rt->rt_conf.id == id)
667 			return (rt);
668 	return (NULL);
669 }
670 
671 struct host *
672 host_findbyname(struct relayd *env, const char *name)
673 {
674 	struct table	*table;
675 	struct host	*host;
676 
677 	TAILQ_FOREACH(table, env->sc_tables, entry)
678 		TAILQ_FOREACH(host, &table->hosts, entry)
679 			if (strcmp(host->conf.name, name) == 0)
680 				return (host);
681 	return (NULL);
682 }
683 
684 struct table *
685 table_findbyname(struct relayd *env, const char *name)
686 {
687 	struct table	*table;
688 
689 	TAILQ_FOREACH(table, env->sc_tables, entry)
690 		if (strcmp(table->conf.name, name) == 0)
691 			return (table);
692 	return (NULL);
693 }
694 
695 struct table *
696 table_findbyconf(struct relayd *env, struct table *tb)
697 {
698 	struct table		*table;
699 	struct table_config	 a, b;
700 
701 	bcopy(&tb->conf, &a, sizeof(a));
702 	a.id = a.rdrid = 0;
703 	a.flags &= ~(F_USED|F_BACKUP);
704 
705 	TAILQ_FOREACH(table, env->sc_tables, entry) {
706 		bcopy(&table->conf, &b, sizeof(b));
707 		b.id = b.rdrid = 0;
708 		b.flags &= ~(F_USED|F_BACKUP);
709 
710 		/*
711 		 * Compare two tables and return the existing table if
712 		 * the configuration seems to be the same.
713 		 */
714 		if (bcmp(&a, &b, sizeof(b)) == 0 &&
715 		    ((tb->sendbuf == NULL && table->sendbuf == NULL) ||
716 		    (tb->sendbuf != NULL && table->sendbuf != NULL &&
717 		    strcmp(tb->sendbuf, table->sendbuf) == 0)))
718 			return (table);
719 	}
720 	return (NULL);
721 }
722 
723 struct rdr *
724 rdr_findbyname(struct relayd *env, const char *name)
725 {
726 	struct rdr	*rdr;
727 
728 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
729 		if (strcmp(rdr->conf.name, name) == 0)
730 			return (rdr);
731 	return (NULL);
732 }
733 
734 struct relay *
735 relay_findbyname(struct relayd *env, const char *name)
736 {
737 	struct relay	*rlay;
738 
739 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
740 		if (strcmp(rlay->rl_conf.name, name) == 0)
741 			return (rlay);
742 	return (NULL);
743 }
744 
745 struct relay *
746 relay_findbyaddr(struct relayd *env, struct relay_config *rc)
747 {
748 	struct relay	*rlay;
749 
750 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
751 		if (bcmp(&rlay->rl_conf.ss, &rc->ss, sizeof(rc->ss)) == 0 &&
752 		    rlay->rl_conf.port == rc->port)
753 			return (rlay);
754 	return (NULL);
755 }
756 
757 void
758 event_again(struct event *ev, int fd, short event,
759     void (*fn)(int, short, void *),
760     struct timeval *start, struct timeval *end, void *arg)
761 {
762 	struct timeval tv_next, tv_now, tv;
763 
764 	if (gettimeofday(&tv_now, NULL) == -1)
765 		fatal("event_again: gettimeofday");
766 
767 	bcopy(end, &tv_next, sizeof(tv_next));
768 	timersub(&tv_now, start, &tv_now);
769 	timersub(&tv_next, &tv_now, &tv_next);
770 
771 	bzero(&tv, sizeof(tv));
772 	if (timercmp(&tv_next, &tv, >))
773 		bcopy(&tv_next, &tv, sizeof(tv));
774 
775 	event_del(ev);
776 	event_set(ev, fd, event, fn, arg);
777 	event_add(ev, &tv);
778 }
779 
780 int
781 expand_string(char *label, size_t len, const char *srch, const char *repl)
782 {
783 	char *tmp;
784 	char *p, *q;
785 
786 	if ((tmp = calloc(1, len)) == NULL) {
787 		log_debug("%s: calloc", __func__);
788 		return (-1);
789 	}
790 	p = q = label;
791 	while ((q = strstr(p, srch)) != NULL) {
792 		*q = '\0';
793 		if ((strlcat(tmp, p, len) >= len) ||
794 		    (strlcat(tmp, repl, len) >= len)) {
795 			log_debug("%s: string too long", __func__);
796 			return (-1);
797 		}
798 		q += strlen(srch);
799 		p = q;
800 	}
801 	if (strlcat(tmp, p, len) >= len) {
802 		log_debug("%s: string too long", __func__);
803 		return (-1);
804 	}
805 	(void)strlcpy(label, tmp, len);	/* always fits */
806 	free(tmp);
807 
808 	return (0);
809 }
810 
811 void
812 translate_string(char *str)
813 {
814 	char	*reader;
815 	char	*writer;
816 
817 	reader = writer = str;
818 
819 	while (*reader) {
820 		if (*reader == '\\') {
821 			reader++;
822 			switch (*reader) {
823 			case 'n':
824 				*writer++ = '\n';
825 				break;
826 			case 'r':
827 				*writer++ = '\r';
828 				break;
829 			default:
830 				*writer++ = *reader;
831 			}
832 		} else
833 			*writer++ = *reader;
834 		reader++;
835 	}
836 	*writer = '\0';
837 }
838 
839 char *
840 digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf)
841 {
842 	switch (type) {
843 	case DIGEST_SHA1:
844 		return (SHA1Data(data, len, buf));
845 		break;
846 	case DIGEST_MD5:
847 		return (MD5Data(data, len, buf));
848 		break;
849 	default:
850 		break;
851 	}
852 	return (NULL);
853 }
854 
855 const char *
856 canonicalize_host(const char *host, char *name, size_t len)
857 {
858 	struct sockaddr_in	 sin4;
859 	struct sockaddr_in6	 sin6;
860 	u_int			 i, j;
861 	size_t			 plen;
862 	char			 c;
863 
864 	if (len < 2)
865 		goto fail;
866 
867 	/*
868 	 * Canonicalize an IPv4/6 address
869 	 */
870 	if (inet_pton(AF_INET, host, &sin4) == 1)
871 		return (inet_ntop(AF_INET, &sin4, name, len));
872 	if (inet_pton(AF_INET6, host, &sin6) == 1)
873 		return (inet_ntop(AF_INET6, &sin6, name, len));
874 
875 	/*
876 	 * Canonicalize a hostname
877 	 */
878 
879 	/* 1. remove repeated dots and convert upper case to lower case */
880 	plen = strlen(host);
881 	bzero(name, len);
882 	for (i = j = 0; i < plen; i++) {
883 		if (j >= (len - 1))
884 			goto fail;
885 		c = tolower(host[i]);
886 		if ((c == '.') && (j == 0 || name[j - 1] == '.'))
887 			continue;
888 		name[j++] = c;
889 	}
890 
891 	/* 2. remove trailing dots */
892 	for (i = j; i > 0; i--) {
893 		if (name[i - 1] != '.')
894 			break;
895 		name[i - 1] = '\0';
896 		j--;
897 	}
898 	if (j <= 0)
899 		goto fail;
900 
901 	return (name);
902 
903  fail:
904 	errno = EINVAL;
905 	return (NULL);
906 }
907 
908 struct protonode *
909 protonode_header(enum direction dir, struct protocol *proto,
910     struct protonode *pk)
911 {
912 	struct protonode	*pn;
913 	struct proto_tree	*tree;
914 
915 	if (dir == RELAY_DIR_RESPONSE)
916 		tree = &proto->response_tree;
917 	else
918 		tree = &proto->request_tree;
919 
920 	pn = RB_FIND(proto_tree, tree, pk);
921 	if (pn != NULL)
922 		return (pn);
923 	if ((pn = (struct protonode *)calloc(1, sizeof(*pn))) == NULL) {
924 		log_warn("%s: calloc", __func__);
925 		return (NULL);
926 	}
927 	pn->key = strdup(pk->key);
928 	if (pn->key == NULL) {
929 		free(pn);
930 		log_warn("%s: strdup", __func__);
931 		return (NULL);
932 	}
933 	pn->value = NULL;
934 	pn->action = NODE_ACTION_NONE;
935 	pn->type = pk->type;
936 	SIMPLEQ_INIT(&pn->head);
937 	if (dir == RELAY_DIR_RESPONSE)
938 		pn->id =
939 		    proto->response_nodes++;
940 	else
941 		pn->id = proto->request_nodes++;
942 	if (pn->id == INT_MAX) {
943 		log_warnx("%s: too many protocol "
944 		    "nodes defined", __func__);
945 		return (NULL);
946 	}
947 	RB_INSERT(proto_tree, tree, pn);
948 	return (pn);
949 }
950 
951 int
952 protonode_add(enum direction dir, struct protocol *proto,
953     struct protonode *node)
954 {
955 	struct protonode	*pn, *proot, pk;
956 	struct proto_tree	*tree;
957 
958 	if (dir == RELAY_DIR_RESPONSE)
959 		tree = &proto->response_tree;
960 	else
961 		tree = &proto->request_tree;
962 
963 	if ((pn = calloc(1, sizeof (*pn))) == NULL) {
964 		log_warn("%s: calloc", __func__);
965 		return (-1);
966 	}
967 	bcopy(node, pn, sizeof(*pn));
968 	pn->key = node->key;
969 	pn->value = node->value;
970 	SIMPLEQ_INIT(&pn->head);
971 	if (dir == RELAY_DIR_RESPONSE)
972 		pn->id = proto->response_nodes++;
973 	else
974 		pn->id = proto->request_nodes++;
975 	if (pn->id == INT_MAX) {
976 		log_warnx("%s: too many protocol nodes defined", __func__);
977 		free(pn);
978 		return (-1);
979 	}
980 	if ((proot =
981 	    RB_INSERT(proto_tree, tree, pn)) != NULL) {
982 		/*
983 		 * A protocol node with the same key already
984 		 * exists, append it to a queue behind the
985 		 * existing node->
986 		 */
987 		if (SIMPLEQ_EMPTY(&proot->head))
988 			SIMPLEQ_NEXT(proot, entry) = pn;
989 		SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry);
990 	}
991 	if (node->type == NODE_TYPE_COOKIE)
992 		pk.key = "Cookie";
993 	else if (node->type == NODE_TYPE_URL)
994 		pk.key = "Host";
995 	else
996 		pk.key = "GET";
997 	if (node->type != NODE_TYPE_HEADER) {
998 		pk.type = NODE_TYPE_HEADER;
999 		pn = protonode_header(dir, proto, &pk);
1000 		if (pn == NULL)
1001 			return (-1);
1002 		switch (node->type) {
1003 		case NODE_TYPE_QUERY:
1004 			pn->flags |= PNFLAG_LOOKUP_QUERY;
1005 			break;
1006 		case NODE_TYPE_COOKIE:
1007 			pn->flags |= PNFLAG_LOOKUP_COOKIE;
1008 			break;
1009 		case NODE_TYPE_URL:
1010 			if (node->flags &
1011 			    PNFLAG_LOOKUP_URL_DIGEST)
1012 				pn->flags |= node->flags &
1013 				    PNFLAG_LOOKUP_URL_DIGEST;
1014 			else
1015 				pn->flags |=
1016 				    PNFLAG_LOOKUP_DIGEST(0);
1017 			break;
1018 		default:
1019 			break;
1020 		}
1021 	}
1022 
1023 	return (0);
1024 }
1025 
1026 int
1027 protonode_load(enum direction dir, struct protocol *proto,
1028     struct protonode *node, const char *name)
1029 {
1030 	FILE			*fp;
1031 	char			 buf[BUFSIZ];
1032 	int			 ret = -1;
1033 	struct protonode	 pn;
1034 
1035 	bcopy(node, &pn, sizeof(pn));
1036 	pn.key = pn.value = NULL;
1037 
1038 	if ((fp = fopen(name, "r")) == NULL)
1039 		return (-1);
1040 
1041 	while (fgets(buf, sizeof(buf), fp) != NULL) {
1042 		/* strip whitespace and newline characters */
1043 		buf[strcspn(buf, "\r\n\t ")] = '\0';
1044 		if (!strlen(buf) || buf[0] == '#')
1045 			continue;
1046 		pn.key = strdup(buf);
1047 		if (node->value != NULL)
1048 			pn.value = strdup(node->value);
1049 		if (pn.key == NULL ||
1050 		    (node->value != NULL && pn.value == NULL))
1051 			goto fail;
1052 		if (protonode_add(dir, proto, &pn) == -1)
1053 			goto fail;
1054 		pn.key = pn.value = NULL;
1055 	}
1056 
1057 	ret = 0;
1058  fail:
1059 	if (pn.key != NULL)
1060 		free(pn.key);
1061 	if (pn.value != NULL)
1062 		free(pn.value);
1063 	fclose(fp);
1064 	return (ret);
1065 }
1066 
1067 int
1068 bindany(struct ctl_bindany *bnd)
1069 {
1070 	int	s, v;
1071 
1072 	s = -1;
1073 	v = 1;
1074 
1075 	if (relay_socket_af(&bnd->bnd_ss, bnd->bnd_port) == -1)
1076 		goto fail;
1077 	if ((s = socket(bnd->bnd_ss.ss_family,
1078 	    bnd->bnd_proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM,
1079 	    bnd->bnd_proto)) == -1)
1080 		goto fail;
1081 	if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
1082 	    &v, sizeof(v)) == -1)
1083 		goto fail;
1084 	if (bind(s, (struct sockaddr *)&bnd->bnd_ss,
1085 	    bnd->bnd_ss.ss_len) == -1)
1086 		goto fail;
1087 
1088 	return (s);
1089 
1090  fail:
1091 	if (s != -1)
1092 		close(s);
1093 	return (-1);
1094 }
1095 
1096 int
1097 map6to4(struct sockaddr_storage *in6)
1098 {
1099 	struct sockaddr_storage	 out4;
1100 	struct sockaddr_in	*sin4 = (struct sockaddr_in *)&out4;
1101 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)in6;
1102 
1103 	bzero(sin4, sizeof(*sin4));
1104 	sin4->sin_len = sizeof(*sin4);
1105 	sin4->sin_family = AF_INET;
1106 	sin4->sin_port = sin6->sin6_port;
1107 
1108 	bcopy(&sin6->sin6_addr.s6_addr[12], &sin4->sin_addr.s_addr,
1109 	    sizeof(sin4->sin_addr));
1110 
1111 	if (sin4->sin_addr.s_addr == INADDR_ANY ||
1112 	    sin4->sin_addr.s_addr == INADDR_BROADCAST ||
1113 	    IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
1114 		return (-1);
1115 
1116 	bcopy(&out4, in6, sizeof(*in6));
1117 
1118 	return (0);
1119 }
1120 
1121 int
1122 map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map)
1123 {
1124 	struct sockaddr_storage	 out6;
1125 	struct sockaddr_in	*sin4 = (struct sockaddr_in *)in4;
1126 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)&out6;
1127 	struct sockaddr_in6	*map6 = (struct sockaddr_in6 *)map;
1128 
1129 	if (sin4->sin_addr.s_addr == INADDR_ANY ||
1130 	    sin4->sin_addr.s_addr == INADDR_BROADCAST ||
1131 	    IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
1132 		return (-1);
1133 
1134 	bcopy(map6, sin6, sizeof(*sin6));
1135 	sin6->sin6_len = sizeof(*sin6);
1136 	sin6->sin6_family = AF_INET6;
1137 	sin6->sin6_port = sin4->sin_port;
1138 
1139 	bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12],
1140 	    sizeof(sin4->sin_addr));
1141 
1142 	bcopy(&out6, in4, sizeof(*in4));
1143 
1144 	return (0);
1145 }
1146 
1147 void
1148 socket_rlimit(int maxfd)
1149 {
1150 	struct rlimit	 rl;
1151 
1152 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
1153 		fatal("socket_rlimit: failed to get resource limit");
1154 	log_debug("%s: max open files %d", __func__, rl.rlim_max);
1155 
1156 	/*
1157 	 * Allow the maximum number of open file descriptors for this
1158 	 * login class (which should be the class "daemon" by default).
1159 	 */
1160 	if (maxfd == -1)
1161 		rl.rlim_cur = rl.rlim_max;
1162 	else
1163 		rl.rlim_cur = MAX(rl.rlim_max, (rlim_t)maxfd);
1164 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
1165 		fatal("socket_rlimit: failed to set resource limit");
1166 }
1167 
1168 char *
1169 get_string(u_int8_t *ptr, size_t len)
1170 {
1171 	size_t	 i;
1172 	char	*str;
1173 
1174 	for (i = 0; i < len; i++)
1175 		if (!(isprint((char)ptr[i]) || isspace((char)ptr[i])))
1176 			break;
1177 
1178 	if ((str = calloc(1, i + 1)) == NULL)
1179 		return (NULL);
1180 	memcpy(str, ptr, i);
1181 
1182 	return (str);
1183 }
1184 
1185 void *
1186 get_data(u_int8_t *ptr, size_t len)
1187 {
1188 	u_int8_t	*data;
1189 
1190 	if ((data = calloc(1, len)) == NULL)
1191 		return (NULL);
1192 	memcpy(data, ptr, len);
1193 
1194 	return (data);
1195 }
1196