1 /* $OpenBSD: config.c,v 1.51 2026/05/19 05:04:11 rsadowski Exp $ */
4 * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
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.
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.
19 #include <sys/types.h>
20 #include <sys/queue.h>
35 config_init(struct relayd *env)
37 struct privsep *ps = env->sc_ps;
40 /* Global configuration */
41 if (privsep_process == PROC_PARENT) {
42 env->sc_conf.timeout.tv_sec = CHECK_TIMEOUT / 1000;
43 env->sc_conf.timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
44 env->sc_conf.interval.tv_sec = CHECK_INTERVAL;
45 env->sc_conf.interval.tv_usec = 0;
46 env->sc_conf.prefork_relay = RELAY_NUMPROC;
47 env->sc_conf.statinterval.tv_sec = RELAY_STATINTERVAL;
48 env->sc_ps->ps_csock.cs_name = RELAYD_SOCKET;
51 ps->ps_what[PROC_PARENT] = CONFIG_ALL;
52 ps->ps_what[PROC_PFE] = CONFIG_ALL & ~(CONFIG_PROTOS|CONFIG_CERTS);
53 ps->ps_what[PROC_HCE] = CONFIG_TABLES;
54 ps->ps_what[PROC_CA] = CONFIG_RELAYS|CONFIG_CERTS;
55 ps->ps_what[PROC_RELAY] = CONFIG_RELAYS|CONFIG_CERTS|
56 CONFIG_TABLES|CONFIG_PROTOS|CONFIG_CA_ENGINE;
58 /* Other configuration */
59 what = ps->ps_what[privsep_process];
60 if (what & CONFIG_TABLES) {
62 calloc(1, sizeof(*env->sc_tables))) == NULL)
64 TAILQ_INIT(env->sc_tables);
66 memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
67 env->sc_empty_table.conf.id = EMPTY_TABLE;
68 env->sc_empty_table.conf.flags |= F_DISABLE;
69 (void)strlcpy(env->sc_empty_table.conf.name, "empty",
70 sizeof(env->sc_empty_table.conf.name));
73 if (what & CONFIG_RDRS) {
75 calloc(1, sizeof(*env->sc_rdrs))) == NULL)
77 TAILQ_INIT(env->sc_rdrs);
80 if (what & CONFIG_RELAYS) {
82 calloc(1, sizeof(*env->sc_relays))) == NULL)
84 TAILQ_INIT(env->sc_relays);
87 calloc(1, sizeof(*env->sc_certs))) == NULL)
89 TAILQ_INIT(env->sc_certs);
92 calloc(1, sizeof(*env->sc_pkeys))) == NULL)
94 TAILQ_INIT(env->sc_pkeys);
96 if (what & CONFIG_PROTOS) {
98 calloc(1, sizeof(*env->sc_protos))) == NULL)
100 TAILQ_INIT(env->sc_protos);
102 bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
103 env->sc_proto_default.id = EMPTY_ID;
104 env->sc_proto_default.flags = F_USED;
105 env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
106 env->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
107 env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT;
108 TAILQ_INIT(&env->sc_proto_default.tlscerts);
109 (void)strlcpy(env->sc_proto_default.tlsciphers,
111 sizeof(env->sc_proto_default.tlsciphers));
112 (void)strlcpy(env->sc_proto_default.tlsecdhecurves,
113 TLSECDHECURVES_DEFAULT,
114 sizeof(env->sc_proto_default.tlsecdhecurves));
115 (void)strlcpy(env->sc_proto_default.tlsdhparams,
117 sizeof(env->sc_proto_default.tlsdhparams));
118 env->sc_proto_default.type = RELAY_PROTO_TCP;
119 (void)strlcpy(env->sc_proto_default.name, "default",
120 sizeof(env->sc_proto_default.name));
122 if (what & CONFIG_RTS) {
124 calloc(1, sizeof(*env->sc_rts))) == NULL)
126 TAILQ_INIT(env->sc_rts);
128 if (what & CONFIG_ROUTES) {
129 if ((env->sc_routes =
130 calloc(1, sizeof(*env->sc_routes))) == NULL)
132 TAILQ_INIT(env->sc_routes);
139 config_purge(struct relayd *env, u_int reset)
141 struct privsep *ps = env->sc_ps;
144 struct address *virt;
145 struct protocol *proto;
146 struct relay_rule *rule;
150 struct ca_pkey *pkey;
151 struct keyname *keyname;
154 what = ps->ps_what[privsep_process] & reset;
156 if (what & CONFIG_TABLES && env->sc_tables != NULL) {
157 while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
158 purge_table(env, env->sc_tables, table);
159 env->sc_tablecount = 0;
161 if (what & CONFIG_RDRS && env->sc_rdrs != NULL) {
162 while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
163 TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
164 while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
165 TAILQ_REMOVE(&rdr->virts, virt, entry);
170 env->sc_rdrcount = 0;
172 if (what & CONFIG_RELAYS && env->sc_pkeys != NULL) {
173 while ((pkey = TAILQ_FIRST(env->sc_pkeys)) != NULL) {
174 TAILQ_REMOVE(env->sc_pkeys, pkey, pkey_entry);
178 if (what & CONFIG_RELAYS && env->sc_relays != NULL) {
179 while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL)
180 purge_relay(env, rlay);
181 env->sc_relaycount = 0;
183 if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
184 while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
185 TAILQ_REMOVE(env->sc_protos, proto, entry);
186 while ((rule = TAILQ_FIRST(&proto->rules)) != NULL)
187 rule_delete(&proto->rules, rule);
188 proto->rulecount = 0;
190 free(proto->tlscapass);
192 TAILQ_FIRST(&proto->tlscerts)) != NULL) {
193 TAILQ_REMOVE(&proto->tlscerts, keyname, entry);
199 env->sc_protocount = 0;
201 if (what & CONFIG_RTS && env->sc_rts != NULL) {
202 while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) {
203 TAILQ_REMOVE(env->sc_rts, rt, rt_entry);
204 while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) {
205 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
206 TAILQ_REMOVE(env->sc_routes, nr, nr_route);
208 env->sc_routecount--;
212 env->sc_routercount = 0;
214 if (what & CONFIG_ROUTES && env->sc_routes != NULL) {
215 while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) {
216 if ((rt = nr->nr_router) != NULL)
217 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
218 TAILQ_REMOVE(env->sc_routes, nr, nr_route);
221 env->sc_routecount = 0;
226 config_setreset(struct relayd *env, u_int reset)
228 struct privsep *ps = env->sc_ps;
231 for (id = 0; id < PROC_MAX; id++) {
232 if ((reset & ps->ps_what[id]) == 0 ||
233 id == privsep_process)
235 proc_compose(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
238 * XXX Make sure that the reset message is sent
239 * immediately by flushing the imsg output buffer, before
240 * sending any other imsg that potentially include an fd.
241 * This should better be fixed in the imsg API itself.
243 proc_flush_imsg(ps, id, -1);
250 config_getreset(struct relayd *env, struct imsg *imsg)
254 IMSG_SIZE_CHECK(imsg, &mode);
255 memcpy(&mode, imsg->data, sizeof(mode));
257 config_purge(env, mode);
263 config_getcfg(struct relayd *env, struct imsg *imsg)
265 struct privsep *ps = env->sc_ps;
270 if (IMSG_DATA_SIZE(imsg) != sizeof(struct relayd_config))
271 return (0); /* ignore */
273 /* Update runtime flags */
274 memcpy(&env->sc_conf, imsg->data, sizeof(env->sc_conf));
276 what = ps->ps_what[privsep_process];
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,
291 if (env->sc_conf.flags & (F_TLS|F_TLSCLIENT)) {
292 if (what & CONFIG_CA_ENGINE)
296 if (privsep_process != PROC_PARENT)
297 proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL, 0);
303 config_settable(struct relayd *env, struct table *tb)
305 struct privsep *ps = env->sc_ps;
310 for (id = 0; id < PROC_MAX; id++) {
311 if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
312 id == privsep_process)
315 /* XXX need to send table to pfe for control socket */
316 if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
319 DPRINTF("%s: sending table %s %d to %s", __func__,
320 tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
323 iov[c].iov_base = &tb->conf;
324 iov[c++].iov_len = sizeof(tb->conf);
325 if (tb->sendbuf != NULL) {
326 iov[c].iov_base = tb->sendbuf;
327 iov[c++].iov_len = strlen(tb->sendbuf);
330 proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
332 TAILQ_FOREACH(host, &tb->hosts, entry) {
333 proc_compose(ps, id, IMSG_CFG_HOST,
334 &host->conf, sizeof(host->conf));
342 config_gettable(struct relayd *env, struct imsg *imsg)
346 u_int8_t *p = imsg->data;
349 if ((tb = calloc(1, sizeof(*tb))) == NULL)
352 IMSG_SIZE_CHECK(imsg, &tb->conf);
353 memcpy(&tb->conf, p, sizeof(tb->conf));
354 s = sizeof(tb->conf);
356 sb = IMSG_DATA_SIZE(imsg) - s;
358 if ((tb->sendbuf = get_string(p + s, sb)) == NULL) {
363 if (tb->conf.check == CHECK_BINSEND_EXPECT) {
364 tb->sendbinbuf = string2binary(tb->sendbuf);
365 if (tb->sendbinbuf == NULL) {
371 TAILQ_INIT(&tb->hosts);
372 TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
374 env->sc_tablecount++;
376 DPRINTF("%s: %s %d received table %d (%s)", __func__,
377 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
378 tb->conf.id, tb->conf.name);
384 config_gethost(struct relayd *env, struct imsg *imsg)
389 if ((host = calloc(1, sizeof(*host))) == NULL)
392 IMSG_SIZE_CHECK(imsg, &host->conf);
393 memcpy(&host->conf, imsg->data, sizeof(host->conf));
395 if (host_find(env, host->conf.id) != NULL) {
396 log_debug("%s: host %d already exists",
397 __func__, host->conf.id);
402 if ((tb = table_find(env, host->conf.tableid)) == NULL) {
404 "received host for unknown table %d", __func__,
410 host->tablename = tb->conf.name;
413 SLIST_INIT(&host->children);
414 TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
415 TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry);
417 DPRINTF("%s: %s %d received host %s for table %s", __func__,
418 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
419 host->conf.name, tb->conf.name);
425 config_setrdr(struct relayd *env, struct rdr *rdr)
427 struct privsep *ps = env->sc_ps;
428 struct address *virt;
431 for (id = 0; id < PROC_MAX; id++) {
432 if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
433 id == privsep_process)
436 DPRINTF("%s: sending rdr %s to %s", __func__,
437 rdr->conf.name, ps->ps_title[id]);
439 proc_compose(ps, id, IMSG_CFG_RDR,
440 &rdr->conf, sizeof(rdr->conf));
442 TAILQ_FOREACH(virt, &rdr->virts, entry) {
443 virt->rdrid = rdr->conf.id;
444 proc_compose(ps, id, IMSG_CFG_VIRT,
445 virt, sizeof(*virt));
453 config_getrdr(struct relayd *env, struct imsg *imsg)
457 if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
460 IMSG_SIZE_CHECK(imsg, &rdr->conf);
461 memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
463 if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
464 log_debug("%s: table not found", __func__);
468 if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
469 rdr->conf.backup_id = EMPTY_TABLE;
470 rdr->backup = &env->sc_empty_table;
473 TAILQ_INIT(&rdr->virts);
474 TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
478 DPRINTF("%s: %s %d received rdr %s", __func__,
479 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
486 config_getvirt(struct relayd *env, struct imsg *imsg)
489 struct address *virt;
491 IMSG_SIZE_CHECK(imsg, virt);
493 if ((virt = calloc(1, sizeof(*virt))) == NULL)
495 memcpy(virt, imsg->data, sizeof(*virt));
497 if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
498 log_debug("%s: rdr not found", __func__);
503 TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
505 DPRINTF("%s: %s %d received address for rdr %s", __func__,
506 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
513 config_setrt(struct relayd *env, struct router *rt)
515 struct privsep *ps = env->sc_ps;
519 for (id = 0; id < PROC_MAX; id++) {
520 if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
521 id == privsep_process)
524 DPRINTF("%s: sending router %s to %s tbl %d", __func__,
525 rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
527 proc_compose(ps, id, IMSG_CFG_ROUTER,
528 &rt->rt_conf, sizeof(rt->rt_conf));
530 TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
531 proc_compose(ps, id, IMSG_CFG_ROUTE,
532 &nr->nr_conf, sizeof(nr->nr_conf));
540 config_getrt(struct relayd *env, struct imsg *imsg)
544 if ((rt = calloc(1, sizeof(*rt))) == NULL)
547 IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
548 memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
550 if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
551 log_debug("%s: table not found", __func__);
556 TAILQ_INIT(&rt->rt_netroutes);
557 TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
559 env->sc_routercount++;
561 DPRINTF("%s: %s %d received router %s", __func__,
562 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
569 config_getroute(struct relayd *env, struct imsg *imsg)
574 if ((nr = calloc(1, sizeof(*nr))) == NULL)
577 IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
578 memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
580 if (route_find(env, nr->nr_conf.id) != NULL) {
581 log_debug("%s: route %d already exists",
582 __func__, nr->nr_conf.id);
587 if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
588 log_debug("%s: received route for unknown router", __func__);
595 TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
596 TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
598 env->sc_routecount++;
600 DPRINTF("%s: %s %d received route %d for router %s", __func__,
601 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
602 nr->nr_conf.id, rt->rt_conf.name);
608 config_setproto(struct relayd *env, struct protocol *proto)
610 struct privsep *ps = env->sc_ps;
612 struct iovec iov[IOV_MAX];
615 for (id = 0; id < PROC_MAX; id++) {
616 if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
617 id == privsep_process)
620 DPRINTF("%s: sending protocol %s to %s", __func__,
621 proto->name, ps->ps_title[id]);
624 iov[c].iov_base = proto;
625 iov[c++].iov_len = sizeof(*proto);
627 if (proto->style != NULL) {
628 iov[c].iov_base = proto->style;
629 iov[c++].iov_len = strlen(proto->style) + 1;
632 proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
639 config_setrule(struct relayd *env, struct protocol *proto)
641 struct privsep *ps = env->sc_ps;
642 struct relay_rule *rule;
643 struct iovec iov[IOV_MAX];
647 for (id = 0; id < PROC_MAX; id++) {
648 if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
649 id == privsep_process)
652 DPRINTF("%s: sending rules %s to %s", __func__,
653 proto->name, ps->ps_title[id]);
655 /* Now send all the rules */
656 TAILQ_FOREACH(rule, &proto->rules, rule_entry) {
657 rule->rule_protoid = proto->id;
658 bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
660 iov[c].iov_base = rule;
661 iov[c++].iov_len = sizeof(*rule);
662 for (i = 1; i < KEY_TYPE_MAX; i++) {
663 if (rule->rule_kv[i].kv_key != NULL) {
664 rule->rule_ctl.kvlen[i].key =
665 strlen(rule->rule_kv[i].kv_key);
667 rule->rule_kv[i].kv_key;
669 rule->rule_ctl.kvlen[i].key;
671 rule->rule_ctl.kvlen[i].key = -1;
672 if (rule->rule_kv[i].kv_value != NULL) {
673 rule->rule_ctl.kvlen[i].value =
674 strlen(rule->rule_kv[i].kv_value);
676 rule->rule_kv[i].kv_value;
678 rule->rule_ctl.kvlen[i].value;
680 rule->rule_ctl.kvlen[i].value = -1;
683 proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
691 config_getproto(struct relayd *env, struct imsg *imsg)
693 struct protocol *proto;
696 u_int8_t *p = imsg->data;
698 if ((proto = calloc(1, sizeof(*proto))) == NULL)
701 IMSG_SIZE_CHECK(imsg, proto);
702 memcpy(proto, p, sizeof(*proto));
705 styl = IMSG_DATA_SIZE(imsg) - s;
708 if ((proto->style = get_string(p + s, styl - 1)) == NULL) {
714 TAILQ_INIT(&proto->rules);
715 TAILQ_INIT(&proto->tlscerts);
716 proto->tlscapass = NULL;
718 TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
720 env->sc_protocount++;
722 DPRINTF("%s: %s %d received protocol %s", __func__,
723 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
730 config_getrule(struct relayd *env, struct imsg *imsg)
732 struct protocol *proto;
733 struct relay_rule *rule;
735 u_int8_t *p = imsg->data;
738 if ((rule = calloc(1, sizeof(*rule))) == NULL)
741 IMSG_SIZE_CHECK(imsg, rule);
742 memcpy(rule, p, sizeof(*rule));
744 len = IMSG_DATA_SIZE(imsg) - s;
746 if ((proto = proto_find(env, rule->rule_protoid)) == NULL) {
751 #define GETKV(_n, _f) { \
752 if (rule->rule_ctl.kvlen[_n]._f >= 0) { \
753 /* Also accept "empty" 0-length strings */ \
754 if ((len < rule->rule_ctl.kvlen[_n]._f) || \
755 (rule->rule_kv[_n].kv_##_f = \
757 rule->rule_ctl.kvlen[_n]._f)) == NULL) { \
761 s += rule->rule_ctl.kvlen[_n]._f; \
762 len -= rule->rule_ctl.kvlen[_n]._f; \
764 DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__, \
765 #_n, #_f, rule->rule_ctl.kvlen[_n]._f, \
766 rule->rule_kv[_n].kv_option, \
767 rule->rule_kv[_n].kv_##_f); \
771 memset(&rule->rule_kv[0], 0, sizeof(struct kv));
772 for (i = 1; i < KEY_TYPE_MAX; i++) {
773 TAILQ_INIT(&rule->rule_kv[i].kv_children);
778 if (rule->rule_labelname[0])
779 rule->rule_label = label_name2id(rule->rule_labelname);
781 if (rule->rule_tagname[0])
782 rule->rule_tag = tag_name2id(rule->rule_tagname);
784 if (rule->rule_taggedname[0])
785 rule->rule_tagged = tag_name2id(rule->rule_taggedname);
787 rule->rule_id = proto->rulecount++;
789 TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry);
791 DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,
792 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
793 rule->rule_id, proto->name);
799 config_setrelayfd(struct privsep *ps, int id, int n,
800 objid_t obj_id, objid_t rlay_id, enum fd_type type, int ofd)
802 struct ctl_relayfd rfd;
806 rfd.relayid = rlay_id;
809 if ((fd = dup(ofd)) == -1)
811 if (proc_compose_imsg(ps, id, n, IMSG_CFG_RELAY_FD, -1, fd,
812 &rfd, sizeof(rfd)) != 0)
819 config_setrelay(struct relayd *env, struct relay *rlay)
821 struct privsep *ps = env->sc_ps;
822 struct ctl_relaytable crt;
823 struct relay_table *rlt;
824 struct relay_config rl;
825 struct relay_cert *cert;
832 /* opens listening sockets etc. */
833 if (relay_privinit(rlay) == -1)
836 for (id = 0; id < PROC_MAX; id++) {
837 what = ps->ps_what[id];
839 if ((what & CONFIG_RELAYS) == 0 || id == privsep_process)
842 DPRINTF("%s: sending relay %s to %s fd %d", __func__,
843 rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
845 memcpy(&rl, &rlay->rl_conf, sizeof(rl));
848 iov[c].iov_base = &rl;
849 iov[c++].iov_len = sizeof(rl);
851 if ((what & CONFIG_CA_ENGINE) == 0 &&
853 iov[c].iov_base = rlay->rl_tls_cakey;
854 iov[c++].iov_len = rl.tls_cakey_len;
856 rl.tls_cakey_len = 0;
858 if (id == PROC_RELAY) {
859 /* XXX imsg code will close the fd after 1st call */
861 proc_range(ps, id, &n, &m);
862 for (n = 0; n < m; n++) {
863 if ((fd = dup(rlay->rl_s)) == -1)
865 if (proc_composev_imsg(ps, id, n,
866 IMSG_CFG_RELAY, -1, fd, iov, c) != 0) {
867 log_warn("%s: failed to compose "
868 "IMSG_CFG_RELAY imsg for `%s'",
869 __func__, rlay->rl_conf.name);
872 /* Prevent fd exhaustion in the parent. */
873 if (proc_flush_imsg(ps, id, n) == -1) {
874 log_warn("%s: failed to flush "
875 "IMSG_CFG_RELAY imsg for `%s'",
876 __func__, rlay->rl_conf.name);
881 if (proc_composev(ps, id,
882 IMSG_CFG_RELAY, iov, c) != 0) {
883 log_warn("%s: failed to compose "
884 "IMSG_CFG_RELAY imsg for `%s'",
885 __func__, rlay->rl_conf.name);
891 TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
892 if (cert->cert_relayid != rlay->rl_conf.id)
895 proc_range(ps, id, &n, &m);
896 for (n = 0; (what & CONFIG_CERTS) && n < m; n++) {
897 if (cert->cert_fd != -1 &&
898 config_setrelayfd(ps, id, n,
899 cert->cert_id, cert->cert_relayid,
900 RELAY_FD_CERT, cert->cert_fd) == -1) {
901 log_warn("%s: fd passing failed for "
906 if (id == PROC_RELAY &&
907 cert->cert_ocsp_fd != -1 &&
908 config_setrelayfd(ps, id, n,
909 cert->cert_id, cert->cert_relayid,
910 RELAY_FD_OCSP, cert->cert_ocsp_fd) == -1) {
911 log_warn("%s: fd passing failed for "
917 cert->cert_key_fd != -1 &&
918 config_setrelayfd(ps, id, n,
919 cert->cert_id, cert->cert_relayid,
920 RELAY_FD_KEY, cert->cert_key_fd) == -1) {
921 log_warn("%s: fd passing failed for "
930 if (what & CONFIG_CERTS) {
932 proc_range(ps, id, &n, &m);
933 for (n = 0; n < m; n++) {
934 if (rlay->rl_tls_ca_fd != -1 &&
935 config_setrelayfd(ps, id, n, 0,
936 rlay->rl_conf.id, RELAY_FD_CACERT,
937 rlay->rl_tls_ca_fd) == -1) {
938 log_warn("%s: fd passing failed for "
943 if (rlay->rl_tls_cacert_fd != -1 &&
944 config_setrelayfd(ps, id, n, 0,
945 rlay->rl_conf.id, RELAY_FD_CAFILE,
946 rlay->rl_tls_cacert_fd) == -1) {
947 log_warn("%s: fd passing failed for "
952 if (rlay->rl_tls_client_ca_fd != -1 &&
953 config_setrelayfd(ps, id, n, 0,
954 rlay->rl_conf.id, RELAY_FD_CLIENTCACERT,
955 rlay->rl_tls_client_ca_fd) == -1) {
956 log_warn("%s: fd passing failed for "
961 /* Prevent fd exhaustion in the parent. */
962 if (proc_flush_imsg(ps, id, n) == -1) {
963 log_warn("%s: failed to flush "
964 "IMSG_CFG_RELAY imsg for `%s'",
965 __func__, rlay->rl_conf.name);
971 if ((what & CONFIG_TABLES) == 0)
974 /* Now send the tables associated to this relay */
975 TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
976 crt.id = rlt->rlt_table->conf.id;
977 crt.relayid = rlay->rl_conf.id;
978 crt.mode = rlt->rlt_mode;
979 crt.flags = rlt->rlt_flags;
982 iov[c].iov_base = &crt;
983 iov[c++].iov_len = sizeof(crt);
985 proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
989 /* Close server socket early to prevent fd exhaustion in the parent. */
990 if (rlay->rl_s != -1) {
994 if (rlay->rl_tls_client_ca_fd != -1) {
995 close(rlay->rl_tls_client_ca_fd);
996 rlay->rl_tls_client_ca_fd = -1;
998 if (rlay->rl_tls_cacert_fd != -1) {
999 close(rlay->rl_tls_cacert_fd);
1000 rlay->rl_tls_cacert_fd = -1;
1002 if (rlay->rl_tls_ca_fd != -1) {
1003 close(rlay->rl_tls_ca_fd);
1004 rlay->rl_tls_ca_fd = -1;
1006 TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
1007 if (cert->cert_relayid != rlay->rl_conf.id)
1010 if (cert->cert_fd != -1) {
1011 close(cert->cert_fd);
1014 if (cert->cert_key_fd != -1) {
1015 close(cert->cert_key_fd);
1016 cert->cert_key_fd = -1;
1018 if (cert->cert_ocsp_fd != -1) {
1019 close(cert->cert_ocsp_fd);
1020 cert->cert_ocsp_fd = -1;
1028 config_getrelay(struct relayd *env, struct imsg *imsg)
1030 struct privsep *ps = env->sc_ps;
1032 u_int8_t *p = imsg->data;
1035 if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
1038 IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
1039 memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
1040 s = sizeof(rlay->rl_conf);
1042 rlay->rl_s = imsg_get_fd(imsg);
1043 rlay->rl_tls_ca_fd = -1;
1044 rlay->rl_tls_cacert_fd = -1;
1045 rlay->rl_tls_client_ca_fd = -1;
1047 if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
1048 if (rlay->rl_conf.proto == EMPTY_ID)
1049 rlay->rl_proto = &env->sc_proto_default;
1050 else if ((rlay->rl_proto =
1051 proto_find(env, rlay->rl_conf.proto)) == NULL) {
1052 log_debug("%s: unknown protocol", __func__);
1057 if ((off_t)(IMSG_DATA_SIZE(imsg) - s) <
1058 (rlay->rl_conf.tls_cakey_len)) {
1059 log_debug("%s: invalid message length", __func__);
1063 if (rlay->rl_conf.tls_cakey_len) {
1064 if ((rlay->rl_tls_cakey = get_data(p + s,
1065 rlay->rl_conf.tls_cakey_len)) == NULL)
1067 s += rlay->rl_conf.tls_cakey_len;
1070 TAILQ_INIT(&rlay->rl_tables);
1071 TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
1073 env->sc_relaycount++;
1075 DPRINTF("%s: %s %d received relay %s", __func__,
1076 ps->ps_title[privsep_process], ps->ps_instance,
1077 rlay->rl_conf.name);
1082 free(rlay->rl_tls_cakey);
1089 config_getrelaytable(struct relayd *env, struct imsg *imsg)
1091 struct relay_table *rlt = NULL;
1092 struct ctl_relaytable crt;
1094 struct table *table;
1095 u_int8_t *p = imsg->data;
1097 IMSG_SIZE_CHECK(imsg, &crt);
1098 memcpy(&crt, p, sizeof(crt));
1100 if ((rlay = relay_find(env, crt.relayid)) == NULL) {
1101 log_debug("%s: unknown relay", __func__);
1105 if ((table = table_find(env, crt.id)) == NULL) {
1106 log_debug("%s: unknown table", __func__);
1110 if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
1113 rlt->rlt_table = table;
1114 rlt->rlt_mode = crt.mode;
1115 rlt->rlt_flags = crt.flags;
1117 TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
1119 DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
1120 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1121 table->conf.name, rlay->rl_conf.name);
1131 config_getrelayfd(struct relayd *env, struct imsg *imsg)
1133 struct ctl_relayfd crfd;
1134 struct relay *rlay = NULL;
1135 struct relay_cert *cert;
1136 u_int8_t *p = imsg->data;
1138 IMSG_SIZE_CHECK(imsg, &crfd);
1139 memcpy(&crfd, p, sizeof(crfd));
1141 switch (crfd.type) {
1145 if ((cert = cert_find(env, crfd.id)) == NULL) {
1146 if ((cert = cert_add(env, crfd.id)) == NULL)
1148 cert->cert_relayid = crfd.relayid;
1152 if ((rlay = relay_find(env, crfd.relayid)) == NULL) {
1153 log_debug("%s: unknown relay", __func__);
1159 switch (crfd.type) {
1161 cert->cert_fd = imsg_get_fd(imsg);
1164 cert->cert_key_fd = imsg_get_fd(imsg);
1167 cert->cert_ocsp_fd = imsg_get_fd(imsg);
1169 case RELAY_FD_CACERT:
1170 rlay->rl_tls_ca_fd = imsg_get_fd(imsg);
1172 case RELAY_FD_CAFILE:
1173 rlay->rl_tls_cacert_fd = imsg_get_fd(imsg);
1175 case RELAY_FD_CLIENTCACERT:
1176 rlay->rl_tls_client_ca_fd = imsg_get_fd(imsg);
1180 DPRINTF("%s: %s %d received relay type %d for relay %s", __func__,
1181 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1182 crfd.type, rlay->rl_conf.name);