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