xref: /openbsd-src/usr.sbin/relayd/config.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: config.c,v 1.30 2016/09/02 14:45:51 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/time.h>
22 #include <sys/uio.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <string.h>
29 #include <imsg.h>
30 
31 #include "relayd.h"
32 
33 int
34 config_init(struct relayd *env)
35 {
36 	struct privsep	*ps = env->sc_ps;
37 	u_int		 what;
38 
39 	/* Global configuration */
40 	if (privsep_process == PROC_PARENT) {
41 		env->sc_conf.timeout.tv_sec = CHECK_TIMEOUT / 1000;
42 		env->sc_conf.timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
43 		env->sc_conf.interval.tv_sec = CHECK_INTERVAL;
44 		env->sc_conf.interval.tv_usec = 0;
45 		env->sc_conf.prefork_relay = RELAY_NUMPROC;
46 		env->sc_conf.statinterval.tv_sec = RELAY_STATINTERVAL;
47 	}
48 
49 	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
50 	ps->ps_what[PROC_PFE] = CONFIG_ALL & ~CONFIG_PROTOS;
51 	ps->ps_what[PROC_HCE] = CONFIG_TABLES;
52 	ps->ps_what[PROC_CA] = CONFIG_RELAYS;
53 	ps->ps_what[PROC_RELAY] = CONFIG_RELAYS|
54 	    CONFIG_TABLES|CONFIG_PROTOS|CONFIG_CA_ENGINE;
55 
56 	/* Other configuration */
57 	what = ps->ps_what[privsep_process];
58 	if (what & CONFIG_TABLES) {
59 		if ((env->sc_tables =
60 		    calloc(1, sizeof(*env->sc_tables))) == NULL)
61 			return (-1);
62 		TAILQ_INIT(env->sc_tables);
63 
64 		memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
65 		env->sc_empty_table.conf.id = EMPTY_TABLE;
66 		env->sc_empty_table.conf.flags |= F_DISABLE;
67 		(void)strlcpy(env->sc_empty_table.conf.name, "empty",
68 		    sizeof(env->sc_empty_table.conf.name));
69 
70 	}
71 	if (what & CONFIG_RDRS) {
72 		if ((env->sc_rdrs =
73 		    calloc(1, sizeof(*env->sc_rdrs))) == NULL)
74 			return (-1);
75 		TAILQ_INIT(env->sc_rdrs);
76 
77 	}
78 	if (what & CONFIG_RELAYS) {
79 		if ((env->sc_relays =
80 		    calloc(1, sizeof(*env->sc_relays))) == NULL)
81 			return (-1);
82 		TAILQ_INIT(env->sc_relays);
83 		if ((env->sc_pkeys =
84 		    calloc(1, sizeof(*env->sc_pkeys))) == NULL)
85 			return (-1);
86 		TAILQ_INIT(env->sc_pkeys);
87 	}
88 	if (what & CONFIG_PROTOS) {
89 		if ((env->sc_protos =
90 		    calloc(1, sizeof(*env->sc_protos))) == NULL)
91 			return (-1);
92 		TAILQ_INIT(env->sc_protos);
93 
94 		bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
95 		env->sc_proto_default.id = EMPTY_ID;
96 		env->sc_proto_default.flags = F_USED;
97 		env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
98 		env->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
99 		env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT;
100 		(void)strlcpy(env->sc_proto_default.tlsciphers,
101 		    TLSCIPHERS_DEFAULT,
102 		    sizeof(env->sc_proto_default.tlsciphers));
103 		env->sc_proto_default.tlsecdhcurve = TLSECDHCURVE_DEFAULT;
104 		env->sc_proto_default.tlsdhparams = TLSDHPARAMS_DEFAULT;
105 		env->sc_proto_default.type = RELAY_PROTO_TCP;
106 		(void)strlcpy(env->sc_proto_default.name, "default",
107 		    sizeof(env->sc_proto_default.name));
108 	}
109 	if (what & CONFIG_RTS) {
110 		if ((env->sc_rts =
111 		    calloc(1, sizeof(*env->sc_rts))) == NULL)
112 			return (-1);
113 		TAILQ_INIT(env->sc_rts);
114 	}
115 	if (what & CONFIG_ROUTES) {
116 		if ((env->sc_routes =
117 		    calloc(1, sizeof(*env->sc_routes))) == NULL)
118 			return (-1);
119 		TAILQ_INIT(env->sc_routes);
120 	}
121 
122 	return (0);
123 }
124 
125 void
126 config_purge(struct relayd *env, u_int reset)
127 {
128 	struct privsep		*ps = env->sc_ps;
129 	struct table		*table;
130 	struct rdr		*rdr;
131 	struct address		*virt;
132 	struct protocol		*proto;
133 	struct relay_rule	*rule;
134 	struct relay		*rlay;
135 	struct netroute		*nr;
136 	struct router		*rt;
137 	struct ca_pkey		*pkey;
138 	u_int			 what;
139 
140 	what = ps->ps_what[privsep_process] & reset;
141 
142 	if (what & CONFIG_TABLES && env->sc_tables != NULL) {
143 		while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
144 			purge_table(env, env->sc_tables, table);
145 		env->sc_tablecount = 0;
146 	}
147 	if (what & CONFIG_RDRS && env->sc_rdrs != NULL) {
148 		while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
149 			TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
150 			while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
151 				TAILQ_REMOVE(&rdr->virts, virt, entry);
152 				free(virt);
153 			}
154 			free(rdr);
155 		}
156 		env->sc_rdrcount = 0;
157 	}
158 	if (what & CONFIG_RELAYS && env->sc_pkeys != NULL) {
159 		while ((pkey = TAILQ_FIRST(env->sc_pkeys)) != NULL) {
160 			TAILQ_REMOVE(env->sc_pkeys, pkey, pkey_entry);
161 			free(pkey);
162 		}
163 	}
164 	if (what & CONFIG_RELAYS && env->sc_relays != NULL) {
165 		while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL)
166 			purge_relay(env, rlay);
167 		env->sc_relaycount = 0;
168 	}
169 	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
170 		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
171 			TAILQ_REMOVE(env->sc_protos, proto, entry);
172 			while ((rule = TAILQ_FIRST(&proto->rules)) != NULL)
173 				rule_delete(&proto->rules, rule);
174 			proto->rulecount = 0;
175 		}
176 	}
177 	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
178 		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
179 			TAILQ_REMOVE(env->sc_protos, proto, entry);
180 			free(proto->style);
181 			free(proto->tlscapass);
182 			free(proto);
183 		}
184 		env->sc_protocount = 0;
185 	}
186 	if (what & CONFIG_RTS && env->sc_rts != NULL) {
187 		while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) {
188 			TAILQ_REMOVE(env->sc_rts, rt, rt_entry);
189 			while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) {
190 				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
191 				TAILQ_REMOVE(env->sc_routes, nr, nr_route);
192 				free(nr);
193 				env->sc_routecount--;
194 			}
195 			free(rt);
196 		}
197 		env->sc_routercount = 0;
198 	}
199 	if (what & CONFIG_ROUTES && env->sc_routes != NULL) {
200 		while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) {
201 			if ((rt = nr->nr_router) != NULL)
202 				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
203 			TAILQ_REMOVE(env->sc_routes, nr, nr_route);
204 			free(nr);
205 		}
206 		env->sc_routecount = 0;
207 	}
208 }
209 
210 int
211 config_setreset(struct relayd *env, u_int reset)
212 {
213 	struct privsep	*ps = env->sc_ps;
214 	int		 id;
215 
216 	for (id = 0; id < PROC_MAX; id++) {
217 		if ((reset & ps->ps_what[id]) == 0 ||
218 		    id == privsep_process)
219 			continue;
220 		proc_compose(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
221 	}
222 
223 	return (0);
224 }
225 
226 int
227 config_getreset(struct relayd *env, struct imsg *imsg)
228 {
229 	u_int		 mode;
230 
231 	IMSG_SIZE_CHECK(imsg, &mode);
232 	memcpy(&mode, imsg->data, sizeof(mode));
233 
234 	config_purge(env, mode);
235 
236 	return (0);
237 }
238 
239 int
240 config_getcfg(struct relayd *env, struct imsg *imsg)
241 {
242 	struct privsep		*ps = env->sc_ps;
243 	struct table		*tb;
244 	struct host		*h, *ph;
245 	u_int			 what;
246 
247 	if (IMSG_DATA_SIZE(imsg) != sizeof(struct relayd_config))
248 		return (0); /* ignore */
249 
250 	/* Update runtime flags */
251 	memcpy(&env->sc_conf, imsg->data, sizeof(env->sc_conf));
252 
253 	what = ps->ps_what[privsep_process];
254 
255 	if (what & CONFIG_TABLES) {
256 		/* Update the tables */
257 		TAILQ_FOREACH(tb, env->sc_tables, entry) {
258 			TAILQ_FOREACH(h, &tb->hosts, entry) {
259 				if (h->conf.parentid && (ph = host_find(env,
260 				    h->conf.parentid)) != NULL) {
261 					SLIST_INSERT_HEAD(&ph->children,
262 					    h, child);
263 				}
264 			}
265 		}
266 	}
267 
268 	if (env->sc_conf.flags & (F_TLS|F_TLSCLIENT)) {
269 		ssl_init(env);
270 		if (what & CONFIG_CA_ENGINE)
271 			ca_engine_init(env);
272 	}
273 
274 	if (privsep_process != PROC_PARENT)
275 		proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL, 0);
276 
277 	return (0);
278 }
279 
280 int
281 config_settable(struct relayd *env, struct table *tb)
282 {
283 	struct privsep	*ps = env->sc_ps;
284 	struct host	*host;
285 	int		 id, c;
286 	struct iovec	 iov[2];
287 
288 	for (id = 0; id < PROC_MAX; id++) {
289 		if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
290 		    id == privsep_process)
291 			continue;
292 
293 		/* XXX need to send table to pfe for control socket */
294 		if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
295 			continue;
296 
297 		DPRINTF("%s: sending table %s %d to %s", __func__,
298 		    tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
299 
300 		c = 0;
301 		iov[c].iov_base = &tb->conf;
302 		iov[c++].iov_len = sizeof(tb->conf);
303 		if (tb->sendbuf != NULL) {
304 			iov[c].iov_base = tb->sendbuf;
305 			iov[c++].iov_len = strlen(tb->sendbuf);
306 		}
307 
308 		proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
309 
310 		TAILQ_FOREACH(host, &tb->hosts, entry) {
311 			proc_compose(ps, id, IMSG_CFG_HOST,
312 			    &host->conf, sizeof(host->conf));
313 		}
314 	}
315 
316 	return (0);
317 }
318 
319 int
320 config_gettable(struct relayd *env, struct imsg *imsg)
321 {
322 	struct table		*tb;
323 	size_t			 sb;
324 	u_int8_t		*p = imsg->data;
325 	size_t			 s;
326 
327 	if ((tb = calloc(1, sizeof(*tb))) == NULL)
328 		return (-1);
329 
330 	IMSG_SIZE_CHECK(imsg, &tb->conf);
331 	memcpy(&tb->conf, p, sizeof(tb->conf));
332 	s = sizeof(tb->conf);
333 
334 	sb = IMSG_DATA_SIZE(imsg) - s;
335 	if (sb > 0) {
336 		if ((tb->sendbuf = get_string(p + s, sb)) == NULL) {
337 			free(tb);
338 			return (-1);
339 		}
340 	}
341 
342 	TAILQ_INIT(&tb->hosts);
343 	TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
344 
345 	env->sc_tablecount++;
346 
347 	DPRINTF("%s: %s %d received table %d (%s)", __func__,
348 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
349 	    tb->conf.id, tb->conf.name);
350 
351 	return (0);
352 }
353 
354 int
355 config_gethost(struct relayd *env, struct imsg *imsg)
356 {
357 	struct table		*tb;
358 	struct host		*host;
359 
360 	if ((host = calloc(1, sizeof(*host))) == NULL)
361 		return (-1);
362 
363 	IMSG_SIZE_CHECK(imsg, &host->conf);
364 	memcpy(&host->conf, imsg->data, sizeof(host->conf));
365 
366 	if (host_find(env, host->conf.id) != NULL) {
367 		log_debug("%s: host %d already exists",
368 		    __func__, host->conf.id);
369 		free(host);
370 		return (-1);
371 	}
372 
373 	if ((tb = table_find(env, host->conf.tableid)) == NULL) {
374 		log_debug("%s: "
375 		    "received host for unknown table %d", __func__,
376 		    host->conf.tableid);
377 		free(host);
378 		return (-1);
379 	}
380 
381 	host->tablename = tb->conf.name;
382 	host->cte.s = -1;
383 
384 	SLIST_INIT(&host->children);
385 	TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
386 	TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry);
387 
388 	DPRINTF("%s: %s %d received host %s for table %s", __func__,
389 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
390 	    host->conf.name, tb->conf.name);
391 
392 	return (0);
393 }
394 
395 int
396 config_setrdr(struct relayd *env, struct rdr *rdr)
397 {
398 	struct privsep	*ps = env->sc_ps;
399 	struct address	*virt;
400 	int		 id;
401 
402 	for (id = 0; id < PROC_MAX; id++) {
403 		if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
404 		    id == privsep_process)
405 			continue;
406 
407 		DPRINTF("%s: sending rdr %s to %s", __func__,
408 		    rdr->conf.name, ps->ps_title[id]);
409 
410 		proc_compose(ps, id, IMSG_CFG_RDR,
411 		    &rdr->conf, sizeof(rdr->conf));
412 
413 		TAILQ_FOREACH(virt, &rdr->virts, entry) {
414 			virt->rdrid = rdr->conf.id;
415 			proc_compose(ps, id, IMSG_CFG_VIRT,
416 			    virt, sizeof(*virt));
417 		}
418 	}
419 
420 	return (0);
421 }
422 
423 int
424 config_getrdr(struct relayd *env, struct imsg *imsg)
425 {
426 	struct rdr		*rdr;
427 
428 	if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
429 		return (-1);
430 
431 	IMSG_SIZE_CHECK(imsg, &rdr->conf);
432 	memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
433 
434 	if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
435 		log_debug("%s: table not found", __func__);
436 		free(rdr);
437 		return (-1);
438 	}
439 	if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
440 		rdr->conf.backup_id = EMPTY_TABLE;
441 		rdr->backup = &env->sc_empty_table;
442 	}
443 
444 	TAILQ_INIT(&rdr->virts);
445 	TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
446 
447 	env->sc_rdrcount++;
448 
449 	DPRINTF("%s: %s %d received rdr %s", __func__,
450 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
451 	    rdr->conf.name);
452 
453 	return (0);
454 }
455 
456 int
457 config_getvirt(struct relayd *env, struct imsg *imsg)
458 {
459 	struct rdr	*rdr;
460 	struct address	*virt;
461 
462 	IMSG_SIZE_CHECK(imsg, virt);
463 
464 	if ((virt = calloc(1, sizeof(*virt))) == NULL)
465 		return (-1);
466 	memcpy(virt, imsg->data, sizeof(*virt));
467 
468 	if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
469 		log_debug("%s: rdr not found", __func__);
470 		free(virt);
471 		return (-1);
472 	}
473 
474 	TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
475 
476 	DPRINTF("%s: %s %d received address for rdr %s", __func__,
477 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
478 	    rdr->conf.name);
479 
480 	return (0);
481 }
482 
483 int
484 config_setrt(struct relayd *env, struct router *rt)
485 {
486 	struct privsep	*ps = env->sc_ps;
487 	struct netroute	*nr;
488 	int		 id;
489 
490 	for (id = 0; id < PROC_MAX; id++) {
491 		if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
492 		    id == privsep_process)
493 			continue;
494 
495 		DPRINTF("%s: sending router %s to %s tbl %d", __func__,
496 		    rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
497 
498 		proc_compose(ps, id, IMSG_CFG_ROUTER,
499 		    &rt->rt_conf, sizeof(rt->rt_conf));
500 
501 		TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
502 			proc_compose(ps, id, IMSG_CFG_ROUTE,
503 			    &nr->nr_conf, sizeof(nr->nr_conf));
504 		}
505 	}
506 
507 	return (0);
508 }
509 
510 int
511 config_getrt(struct relayd *env, struct imsg *imsg)
512 {
513 	struct router		*rt;
514 
515 	if ((rt = calloc(1, sizeof(*rt))) == NULL)
516 		return (-1);
517 
518 	IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
519 	memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
520 
521 	if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
522 		log_debug("%s: table not found", __func__);
523 		free(rt);
524 		return (-1);
525 	}
526 
527 	TAILQ_INIT(&rt->rt_netroutes);
528 	TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
529 
530 	env->sc_routercount++;
531 
532 	DPRINTF("%s: %s %d received router %s", __func__,
533 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
534 	    rt->rt_conf.name);
535 
536 	return (0);
537 }
538 
539 int
540 config_getroute(struct relayd *env, struct imsg *imsg)
541 {
542 	struct router		*rt;
543 	struct netroute		*nr;
544 
545 	if ((nr = calloc(1, sizeof(*nr))) == NULL)
546 		return (-1);
547 
548 	IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
549 	memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
550 
551 	if (route_find(env, nr->nr_conf.id) != NULL) {
552 		log_debug("%s: route %d already exists",
553 		    __func__, nr->nr_conf.id);
554 		free(nr);
555 		return (-1);
556 	}
557 
558 	if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
559 		log_debug("%s: received route for unknown router", __func__);
560 		free(nr);
561 		return (-1);
562 	}
563 
564 	nr->nr_router = rt;
565 
566 	TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
567 	TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
568 
569 	env->sc_routecount++;
570 
571 	DPRINTF("%s: %s %d received route %d for router %s", __func__,
572 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
573 	    nr->nr_conf.id, rt->rt_conf.name);
574 
575 	return (0);
576 }
577 
578 int
579 config_setproto(struct relayd *env, struct protocol *proto)
580 {
581 	struct privsep		*ps = env->sc_ps;
582 	int			 id;
583 	struct iovec		 iov[IOV_MAX];
584 	size_t			 c;
585 
586 	for (id = 0; id < PROC_MAX; id++) {
587 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
588 		    id == privsep_process)
589 			continue;
590 
591 		DPRINTF("%s: sending protocol %s to %s", __func__,
592 		    proto->name, ps->ps_title[id]);
593 
594 		c = 0;
595 		iov[c].iov_base = proto;
596 		iov[c++].iov_len = sizeof(*proto);
597 
598 		if (proto->style != NULL) {
599 			iov[c].iov_base = proto->style;
600 			iov[c++].iov_len = strlen(proto->style);
601 		}
602 
603 		proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
604 	}
605 
606 	return (0);
607 }
608 
609 int
610 config_setrule(struct relayd *env, struct protocol *proto)
611 {
612 	struct privsep		*ps = env->sc_ps;
613 	struct relay_rule	*rule;
614 	struct iovec		 iov[IOV_MAX];
615 	int			 id;
616 	size_t			 c, i;
617 
618 	for (id = 0; id < PROC_MAX; id++) {
619 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
620 		    id == privsep_process)
621 			continue;
622 
623 		DPRINTF("%s: sending rules %s to %s", __func__,
624 		    proto->name, ps->ps_title[id]);
625 
626 		/* Now send all the rules */
627 		TAILQ_FOREACH(rule, &proto->rules, rule_entry) {
628 			rule->rule_protoid = proto->id;
629 			bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
630 			c = 0;
631 			iov[c].iov_base = rule;
632 			iov[c++].iov_len = sizeof(*rule);
633 			for (i = 1; i < KEY_TYPE_MAX; i++) {
634 				if (rule->rule_kv[i].kv_key != NULL) {
635 					rule->rule_ctl.kvlen[i].key =
636 					    strlen(rule->rule_kv[i].kv_key);
637 					iov[c].iov_base =
638 					    rule->rule_kv[i].kv_key;
639 					iov[c++].iov_len =
640 					    rule->rule_ctl.kvlen[i].key;
641 				} else
642 					rule->rule_ctl.kvlen[i].key = -1;
643 				if (rule->rule_kv[i].kv_value != NULL) {
644 					rule->rule_ctl.kvlen[i].value =
645 					    strlen(rule->rule_kv[i].kv_value);
646 					iov[c].iov_base =
647 					    rule->rule_kv[i].kv_value;
648 					iov[c++].iov_len =
649 					    rule->rule_ctl.kvlen[i].value;
650 				} else
651 					rule->rule_ctl.kvlen[i].value = -1;
652 			}
653 
654 			proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
655 		}
656 	}
657 
658 	return (0);
659 }
660 
661 int
662 config_getproto(struct relayd *env, struct imsg *imsg)
663 {
664 	struct protocol		*proto;
665 	size_t			 styl;
666 	size_t			 s;
667 	u_int8_t		*p = imsg->data;
668 
669 	if ((proto = calloc(1, sizeof(*proto))) == NULL)
670 		return (-1);
671 
672 	IMSG_SIZE_CHECK(imsg, proto);
673 	memcpy(proto, p, sizeof(*proto));
674 	s = sizeof(*proto);
675 
676 	styl = IMSG_DATA_SIZE(imsg) - s;
677 	if (styl > 0) {
678 		if ((proto->style = get_string(p + s, styl)) == NULL) {
679 			free(proto);
680 			return (-1);
681 		}
682 	}
683 
684 	TAILQ_INIT(&proto->rules);
685 	proto->tlscapass = NULL;
686 
687 	TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
688 
689 	env->sc_protocount++;
690 
691 	DPRINTF("%s: %s %d received protocol %s", __func__,
692 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
693 	    proto->name);
694 
695 	return (0);
696 }
697 
698 int
699 config_getrule(struct relayd *env, struct imsg *imsg)
700 {
701 	struct protocol		*proto;
702 	struct relay_rule	*rule;
703 	size_t			 s, i;
704 	u_int8_t		*p = imsg->data;
705 	ssize_t			 len;
706 
707 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
708 		return (-1);
709 
710 	IMSG_SIZE_CHECK(imsg, rule);
711 	memcpy(rule, p, sizeof(*rule));
712 	s = sizeof(*rule);
713 	len = IMSG_DATA_SIZE(imsg) - s;
714 
715 	if ((proto = proto_find(env, rule->rule_protoid)) == NULL) {
716 		free(rule);
717 		return (-1);
718 	}
719 
720 #define GETKV(_n, _f)	{						\
721 	if (rule->rule_ctl.kvlen[_n]._f >= 0) {				\
722 		/* Also accept "empty" 0-length strings */		\
723 		if ((len < rule->rule_ctl.kvlen[_n]._f) ||		\
724 		    (rule->rule_kv[_n].kv_##_f =			\
725 		    get_string(p + s,					\
726 		    rule->rule_ctl.kvlen[_n]._f)) == NULL) {		\
727 			free(rule);					\
728 			return (-1);					\
729 		}							\
730 		s += rule->rule_ctl.kvlen[_n]._f;			\
731 		len -= rule->rule_ctl.kvlen[_n]._f;			\
732 									\
733 		DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__,	\
734 		    #_n, #_f, rule->rule_ctl.kvlen[_n]._f,		\
735 		    rule->rule_kv[_n].kv_option,			\
736 		    rule->rule_kv[_n].kv_##_f);				\
737 	}								\
738 }
739 
740 	memset(&rule->rule_kv[0], 0, sizeof(struct kv));
741 	for (i = 1; i < KEY_TYPE_MAX; i++) {
742 		TAILQ_INIT(&rule->rule_kv[i].kv_children);
743 		GETKV(i, key);
744 		GETKV(i, value);
745 	}
746 
747 	if (rule->rule_labelname[0])
748 		rule->rule_label = label_name2id(rule->rule_labelname);
749 
750 	if (rule->rule_tagname[0])
751 		rule->rule_tag = tag_name2id(rule->rule_tagname);
752 
753 	if (rule->rule_taggedname[0])
754 		rule->rule_tagged = tag_name2id(rule->rule_taggedname);
755 
756 	rule->rule_id = proto->rulecount++;
757 
758 	TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry);
759 
760 	DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,
761 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
762 	    rule->rule_id, proto->name);
763 
764 	return (0);
765 }
766 
767 int
768 config_setrelay(struct relayd *env, struct relay *rlay)
769 {
770 	struct privsep		*ps = env->sc_ps;
771 	struct ctl_relaytable	 crt;
772 	struct relay_table	*rlt;
773 	struct relay_config	 rl;
774 	int			 id;
775 	int			 fd, n, m;
776 	struct iovec		 iov[6];
777 	size_t			 c;
778 	u_int			 what;
779 
780 	/* opens listening sockets etc. */
781 	if (relay_privinit(rlay) == -1)
782 		return (-1);
783 
784 	for (id = 0; id < PROC_MAX; id++) {
785 		what = ps->ps_what[id];
786 
787 		if ((what & CONFIG_RELAYS) == 0 || id == privsep_process)
788 			continue;
789 
790 		DPRINTF("%s: sending relay %s to %s fd %d", __func__,
791 		    rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
792 
793 		memcpy(&rl, &rlay->rl_conf, sizeof(rl));
794 
795 		c = 0;
796 		iov[c].iov_base = &rl;
797 		iov[c++].iov_len = sizeof(rl);
798 		if (rl.tls_cert_len) {
799 			iov[c].iov_base = rlay->rl_tls_cert;
800 			iov[c++].iov_len = rl.tls_cert_len;
801 		}
802 		if ((what & CONFIG_CA_ENGINE) == 0 &&
803 		    rl.tls_key_len) {
804 			iov[c].iov_base = rlay->rl_tls_key;
805 			iov[c++].iov_len = rl.tls_key_len;
806 		} else
807 			rl.tls_key_len = 0;
808 		if (rl.tls_ca_len) {
809 			iov[c].iov_base = rlay->rl_tls_ca;
810 			iov[c++].iov_len = rl.tls_ca_len;
811 		}
812 		if (rl.tls_cacert_len) {
813 			iov[c].iov_base = rlay->rl_tls_cacert;
814 			iov[c++].iov_len = rl.tls_cacert_len;
815 		}
816 		if ((what & CONFIG_CA_ENGINE) == 0 &&
817 		    rl.tls_cakey_len) {
818 			iov[c].iov_base = rlay->rl_tls_cakey;
819 			iov[c++].iov_len = rl.tls_cakey_len;
820 		} else
821 			rl.tls_cakey_len = 0;
822 
823 		if (id == PROC_RELAY) {
824 			/* XXX imsg code will close the fd after 1st call */
825 			n = -1;
826 			proc_range(ps, id, &n, &m);
827 			for (n = 0; n < m; n++) {
828 				if ((fd = dup(rlay->rl_s)) == -1)
829 					return (-1);
830 				proc_composev_imsg(ps, id, n,
831 				    IMSG_CFG_RELAY, -1, fd, iov, c);
832 			}
833 		} else {
834 			proc_composev(ps, id, IMSG_CFG_RELAY, iov, c);
835 		}
836 
837 		if ((what & CONFIG_TABLES) == 0)
838 			continue;
839 
840 		/* Now send the tables associated to this relay */
841 		TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
842 			crt.id = rlt->rlt_table->conf.id;
843 			crt.relayid = rlay->rl_conf.id;
844 			crt.mode = rlt->rlt_mode;
845 			crt.flags = rlt->rlt_flags;
846 
847 			c = 0;
848 			iov[c].iov_base = &crt;
849 			iov[c++].iov_len = sizeof(crt);
850 
851 			proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
852 		}
853 	}
854 
855 	close(rlay->rl_s);
856 	rlay->rl_s = -1;
857 
858 	return (0);
859 }
860 
861 int
862 config_getrelay(struct relayd *env, struct imsg *imsg)
863 {
864 	struct privsep		*ps = env->sc_ps;
865 	struct relay		*rlay;
866 	u_int8_t		*p = imsg->data;
867 	size_t			 s;
868 
869 	if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
870 		return (-1);
871 
872 	IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
873 	memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
874 	s = sizeof(rlay->rl_conf);
875 
876 	rlay->rl_s = imsg->fd;
877 
878 	if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
879 		if (rlay->rl_conf.proto == EMPTY_ID)
880 			rlay->rl_proto = &env->sc_proto_default;
881 		else if ((rlay->rl_proto =
882 		    proto_find(env, rlay->rl_conf.proto)) == NULL) {
883 			log_debug("%s: unknown protocol", __func__);
884 			goto fail;
885 		}
886 	}
887 
888 	if ((off_t)(IMSG_DATA_SIZE(imsg) - s) <
889 	    (rlay->rl_conf.tls_cert_len +
890 	    rlay->rl_conf.tls_key_len +
891 	    rlay->rl_conf.tls_ca_len +
892 	    rlay->rl_conf.tls_cacert_len +
893 	    rlay->rl_conf.tls_cakey_len)) {
894 		log_debug("%s: invalid message length", __func__);
895 		goto fail;
896 	}
897 
898 	if (rlay->rl_conf.tls_cert_len) {
899 		if ((rlay->rl_tls_cert = get_data(p + s,
900 		    rlay->rl_conf.tls_cert_len)) == NULL)
901 			goto fail;
902 		s += rlay->rl_conf.tls_cert_len;
903 	}
904 	if (rlay->rl_conf.tls_key_len) {
905 		if ((rlay->rl_tls_key = get_data(p + s,
906 		    rlay->rl_conf.tls_key_len)) == NULL)
907 			goto fail;
908 		s += rlay->rl_conf.tls_key_len;
909 	}
910 	if (rlay->rl_conf.tls_ca_len) {
911 		if ((rlay->rl_tls_ca = get_data(p + s,
912 		    rlay->rl_conf.tls_ca_len)) == NULL)
913 			goto fail;
914 		s += rlay->rl_conf.tls_ca_len;
915 	}
916 	if (rlay->rl_conf.tls_cacert_len) {
917 		if ((rlay->rl_tls_cacert = get_data(p + s,
918 		    rlay->rl_conf.tls_cacert_len)) == NULL)
919 			goto fail;
920 		s += rlay->rl_conf.tls_cacert_len;
921 	}
922 	if (rlay->rl_conf.tls_cakey_len) {
923 		if ((rlay->rl_tls_cakey = get_data(p + s,
924 		    rlay->rl_conf.tls_cakey_len)) == NULL)
925 			goto fail;
926 		s += rlay->rl_conf.tls_cakey_len;
927 	}
928 
929 	TAILQ_INIT(&rlay->rl_tables);
930 	TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
931 
932 	env->sc_relaycount++;
933 
934 	DPRINTF("%s: %s %d received relay %s", __func__,
935 	    ps->ps_title[privsep_process], ps->ps_instance,
936 	    rlay->rl_conf.name);
937 
938 	return (0);
939 
940  fail:
941 	free(rlay->rl_tls_cert);
942 	free(rlay->rl_tls_key);
943 	free(rlay->rl_tls_ca);
944 	close(rlay->rl_s);
945 	free(rlay);
946 	return (-1);
947 }
948 
949 int
950 config_getrelaytable(struct relayd *env, struct imsg *imsg)
951 {
952 	struct relay_table	*rlt = NULL;
953 	struct ctl_relaytable	 crt;
954 	struct relay		*rlay;
955 	struct table		*table;
956 	u_int8_t		*p = imsg->data;
957 
958 	IMSG_SIZE_CHECK(imsg, &crt);
959 	memcpy(&crt, p, sizeof(crt));
960 
961 	if ((rlay = relay_find(env, crt.relayid)) == NULL) {
962 		log_debug("%s: unknown relay", __func__);
963 		goto fail;
964 	}
965 
966 	if ((table = table_find(env, crt.id)) == NULL) {
967 		log_debug("%s: unknown table", __func__);
968 		goto fail;
969 	}
970 
971 	if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
972 		goto fail;
973 
974 	rlt->rlt_table = table;
975 	rlt->rlt_mode = crt.mode;
976 	rlt->rlt_flags = crt.flags;
977 
978 	TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
979 
980 	DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
981 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
982 	    table->conf.name, rlay->rl_conf.name);
983 
984 	return (0);
985 
986  fail:
987 	free(rlt);
988 	return (-1);
989 }
990