Bug Summary

File:src/usr.sbin/relayd/config.c
Warning:line 1058, column 3
Value stored to 's' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name config.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/relayd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/relayd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/relayd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/relayd/config.c
1/* $OpenBSD: config.c,v 1.43 2021/12/05 13:48:14 jsg 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
33int
34config_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_TIMEOUT200 / 1000;
42 env->sc_conf.timeout.tv_usec = (CHECK_TIMEOUT200 % 1000) * 1000;
43 env->sc_conf.interval.tv_sec = CHECK_INTERVAL10;
44 env->sc_conf.interval.tv_usec = 0;
45 env->sc_conf.prefork_relay = RELAY_NUMPROC3;
46 env->sc_conf.statinterval.tv_sec = RELAY_STATINTERVAL60;
47 env->sc_ps->ps_csock.cs_name = RELAYD_SOCKET"/var/run/relayd.sock";
48 }
49
50 ps->ps_what[PROC_PARENT] = CONFIG_ALL0xff;
51 ps->ps_what[PROC_PFE] = CONFIG_ALL0xff & ~(CONFIG_PROTOS0x08|CONFIG_CERTS0x80);
52 ps->ps_what[PROC_HCE] = CONFIG_TABLES0x01;
53 ps->ps_what[PROC_CA] = CONFIG_RELAYS0x04|CONFIG_CERTS0x80;
54 ps->ps_what[PROC_RELAY] = CONFIG_RELAYS0x04|CONFIG_CERTS0x80|
55 CONFIG_TABLES0x01|CONFIG_PROTOS0x08|CONFIG_CA_ENGINE0x40;
56
57 /* Other configuration */
58 what = ps->ps_what[privsep_process];
59 if (what & CONFIG_TABLES0x01) {
60 if ((env->sc_tables =
61 calloc(1, sizeof(*env->sc_tables))) == NULL((void*)0))
62 return (-1);
63 TAILQ_INIT(env->sc_tables)do { (env->sc_tables)->tqh_first = ((void*)0); (env->
sc_tables)->tqh_last = &(env->sc_tables)->tqh_first
; } while (0)
;
64
65 memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
66 env->sc_empty_table.conf.id = EMPTY_TABLE(2147483647 *2U +1U);
67 env->sc_empty_table.conf.flags |= F_DISABLE0x00000001;
68 (void)strlcpy(env->sc_empty_table.conf.name, "empty",
69 sizeof(env->sc_empty_table.conf.name));
70
71 }
72 if (what & CONFIG_RDRS0x02) {
73 if ((env->sc_rdrs =
74 calloc(1, sizeof(*env->sc_rdrs))) == NULL((void*)0))
75 return (-1);
76 TAILQ_INIT(env->sc_rdrs)do { (env->sc_rdrs)->tqh_first = ((void*)0); (env->sc_rdrs
)->tqh_last = &(env->sc_rdrs)->tqh_first; } while
(0)
;
77
78 }
79 if (what & CONFIG_RELAYS0x04) {
80 if ((env->sc_relays =
81 calloc(1, sizeof(*env->sc_relays))) == NULL((void*)0))
82 return (-1);
83 TAILQ_INIT(env->sc_relays)do { (env->sc_relays)->tqh_first = ((void*)0); (env->
sc_relays)->tqh_last = &(env->sc_relays)->tqh_first
; } while (0)
;
84
85 if ((env->sc_certs =
86 calloc(1, sizeof(*env->sc_certs))) == NULL((void*)0))
87 return (-1);
88 TAILQ_INIT(env->sc_certs)do { (env->sc_certs)->tqh_first = ((void*)0); (env->
sc_certs)->tqh_last = &(env->sc_certs)->tqh_first
; } while (0)
;
89
90 if ((env->sc_pkeys =
91 calloc(1, sizeof(*env->sc_pkeys))) == NULL((void*)0))
92 return (-1);
93 TAILQ_INIT(env->sc_pkeys)do { (env->sc_pkeys)->tqh_first = ((void*)0); (env->
sc_pkeys)->tqh_last = &(env->sc_pkeys)->tqh_first
; } while (0)
;
94 }
95 if (what & CONFIG_PROTOS0x08) {
96 if ((env->sc_protos =
97 calloc(1, sizeof(*env->sc_protos))) == NULL((void*)0))
98 return (-1);
99 TAILQ_INIT(env->sc_protos)do { (env->sc_protos)->tqh_first = ((void*)0); (env->
sc_protos)->tqh_last = &(env->sc_protos)->tqh_first
; } while (0)
;
100
101 bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
102 env->sc_proto_default.id = EMPTY_ID(2147483647 *2U +1U);
103 env->sc_proto_default.flags = F_USED0x00000004;
104 env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT0x00;
105 env->sc_proto_default.tcpbacklog = RELAY_BACKLOG10;
106 env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT(0x08|0x10|0x20);
107 TAILQ_INIT(&env->sc_proto_default.tlscerts)do { (&env->sc_proto_default.tlscerts)->tqh_first =
((void*)0); (&env->sc_proto_default.tlscerts)->tqh_last
= &(&env->sc_proto_default.tlscerts)->tqh_first
; } while (0)
;
108 (void)strlcpy(env->sc_proto_default.tlsciphers,
109 TLSCIPHERS_DEFAULT"HIGH:!aNULL",
110 sizeof(env->sc_proto_default.tlsciphers));
111 (void)strlcpy(env->sc_proto_default.tlsecdhecurves,
112 TLSECDHECURVES_DEFAULT"default",
113 sizeof(env->sc_proto_default.tlsecdhecurves));
114 (void)strlcpy(env->sc_proto_default.tlsdhparams,
115 TLSDHPARAM_DEFAULT"none",
116 sizeof(env->sc_proto_default.tlsdhparams));
117 env->sc_proto_default.type = RELAY_PROTO_TCP;
118 (void)strlcpy(env->sc_proto_default.name, "default",
119 sizeof(env->sc_proto_default.name));
120 }
121 if (what & CONFIG_RTS0x20) {
122 if ((env->sc_rts =
123 calloc(1, sizeof(*env->sc_rts))) == NULL((void*)0))
124 return (-1);
125 TAILQ_INIT(env->sc_rts)do { (env->sc_rts)->tqh_first = ((void*)0); (env->sc_rts
)->tqh_last = &(env->sc_rts)->tqh_first; } while
(0)
;
126 }
127 if (what & CONFIG_ROUTES0x10) {
128 if ((env->sc_routes =
129 calloc(1, sizeof(*env->sc_routes))) == NULL((void*)0))
130 return (-1);
131 TAILQ_INIT(env->sc_routes)do { (env->sc_routes)->tqh_first = ((void*)0); (env->
sc_routes)->tqh_last = &(env->sc_routes)->tqh_first
; } while (0)
;
132 }
133
134 return (0);
135}
136
137void
138config_purge(struct relayd *env, u_int reset)
139{
140 struct privsep *ps = env->sc_ps;
141 struct table *table;
142 struct rdr *rdr;
143 struct address *virt;
144 struct protocol *proto;
145 struct relay_rule *rule;
146 struct relay *rlay;
147 struct netroute *nr;
148 struct router *rt;
149 struct ca_pkey *pkey;
150 struct keyname *keyname;
151 u_int what;
152
153 what = ps->ps_what[privsep_process] & reset;
154
155 if (what & CONFIG_TABLES0x01 && env->sc_tables != NULL((void*)0)) {
156 while ((table = TAILQ_FIRST(env->sc_tables)((env->sc_tables)->tqh_first)) != NULL((void*)0))
157 purge_table(env, env->sc_tables, table);
158 env->sc_tablecount = 0;
159 }
160 if (what & CONFIG_RDRS0x02 && env->sc_rdrs != NULL((void*)0)) {
161 while ((rdr = TAILQ_FIRST(env->sc_rdrs)((env->sc_rdrs)->tqh_first)) != NULL((void*)0)) {
162 TAILQ_REMOVE(env->sc_rdrs, rdr, entry)do { if (((rdr)->entry.tqe_next) != ((void*)0)) (rdr)->
entry.tqe_next->entry.tqe_prev = (rdr)->entry.tqe_prev;
else (env->sc_rdrs)->tqh_last = (rdr)->entry.tqe_prev
; *(rdr)->entry.tqe_prev = (rdr)->entry.tqe_next; ; ; }
while (0)
;
163 while ((virt = TAILQ_FIRST(&rdr->virts)((&rdr->virts)->tqh_first)) != NULL((void*)0)) {
164 TAILQ_REMOVE(&rdr->virts, virt, entry)do { if (((virt)->entry.tqe_next) != ((void*)0)) (virt)->
entry.tqe_next->entry.tqe_prev = (virt)->entry.tqe_prev
; else (&rdr->virts)->tqh_last = (virt)->entry.tqe_prev
; *(virt)->entry.tqe_prev = (virt)->entry.tqe_next; ; ;
} while (0)
;
165 free(virt);
166 }
167 free(rdr);
168 }
169 env->sc_rdrcount = 0;
170 }
171 if (what & CONFIG_RELAYS0x04 && env->sc_pkeys != NULL((void*)0)) {
172 while ((pkey = TAILQ_FIRST(env->sc_pkeys)((env->sc_pkeys)->tqh_first)) != NULL((void*)0)) {
173 TAILQ_REMOVE(env->sc_pkeys, pkey, pkey_entry)do { if (((pkey)->pkey_entry.tqe_next) != ((void*)0)) (pkey
)->pkey_entry.tqe_next->pkey_entry.tqe_prev = (pkey)->
pkey_entry.tqe_prev; else (env->sc_pkeys)->tqh_last = (
pkey)->pkey_entry.tqe_prev; *(pkey)->pkey_entry.tqe_prev
= (pkey)->pkey_entry.tqe_next; ; ; } while (0)
;
174 free(pkey);
175 }
176 }
177 if (what & CONFIG_RELAYS0x04 && env->sc_relays != NULL((void*)0)) {
178 while ((rlay = TAILQ_FIRST(env->sc_relays)((env->sc_relays)->tqh_first)) != NULL((void*)0))
179 purge_relay(env, rlay);
180 env->sc_relaycount = 0;
181 }
182 if (what & CONFIG_PROTOS0x08 && env->sc_protos != NULL((void*)0)) {
183 while ((proto = TAILQ_FIRST(env->sc_protos)((env->sc_protos)->tqh_first)) != NULL((void*)0)) {
184 TAILQ_REMOVE(env->sc_protos, proto, entry)do { if (((proto)->entry.tqe_next) != ((void*)0)) (proto)->
entry.tqe_next->entry.tqe_prev = (proto)->entry.tqe_prev
; else (env->sc_protos)->tqh_last = (proto)->entry.tqe_prev
; *(proto)->entry.tqe_prev = (proto)->entry.tqe_next; ;
; } while (0)
;
185 while ((rule = TAILQ_FIRST(&proto->rules)((&proto->rules)->tqh_first)) != NULL((void*)0))
186 rule_delete(&proto->rules, rule);
187 proto->rulecount = 0;
188 }
189 }
190 if (what & CONFIG_PROTOS0x08 && env->sc_protos != NULL((void*)0)) {
191 while ((proto = TAILQ_FIRST(env->sc_protos)((env->sc_protos)->tqh_first)) != NULL((void*)0)) {
192 TAILQ_REMOVE(env->sc_protos, proto, entry)do { if (((proto)->entry.tqe_next) != ((void*)0)) (proto)->
entry.tqe_next->entry.tqe_prev = (proto)->entry.tqe_prev
; else (env->sc_protos)->tqh_last = (proto)->entry.tqe_prev
; *(proto)->entry.tqe_prev = (proto)->entry.tqe_next; ;
; } while (0)
;
193 free(proto->style);
194 free(proto->tlscapass);
195 while ((keyname =
196 TAILQ_FIRST(&proto->tlscerts)((&proto->tlscerts)->tqh_first)) != NULL((void*)0)) {
197 TAILQ_REMOVE(&proto->tlscerts, keyname, entry)do { if (((keyname)->entry.tqe_next) != ((void*)0)) (keyname
)->entry.tqe_next->entry.tqe_prev = (keyname)->entry
.tqe_prev; else (&proto->tlscerts)->tqh_last = (keyname
)->entry.tqe_prev; *(keyname)->entry.tqe_prev = (keyname
)->entry.tqe_next; ; ; } while (0)
;
198 free(keyname->name);
199 free(keyname);
200 }
201 free(proto);
202 }
203 env->sc_protocount = 0;
204 }
205 if (what & CONFIG_RTS0x20 && env->sc_rts != NULL((void*)0)) {
206 while ((rt = TAILQ_FIRST(env->sc_rts)((env->sc_rts)->tqh_first)) != NULL((void*)0)) {
207 TAILQ_REMOVE(env->sc_rts, rt, rt_entry)do { if (((rt)->rt_entry.tqe_next) != ((void*)0)) (rt)->
rt_entry.tqe_next->rt_entry.tqe_prev = (rt)->rt_entry.tqe_prev
; else (env->sc_rts)->tqh_last = (rt)->rt_entry.tqe_prev
; *(rt)->rt_entry.tqe_prev = (rt)->rt_entry.tqe_next; ;
; } while (0)
;
208 while ((nr = TAILQ_FIRST(&rt->rt_netroutes)((&rt->rt_netroutes)->tqh_first)) != NULL((void*)0)) {
209 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry)do { if (((nr)->nr_entry.tqe_next) != ((void*)0)) (nr)->
nr_entry.tqe_next->nr_entry.tqe_prev = (nr)->nr_entry.tqe_prev
; else (&rt->rt_netroutes)->tqh_last = (nr)->nr_entry
.tqe_prev; *(nr)->nr_entry.tqe_prev = (nr)->nr_entry.tqe_next
; ; ; } while (0)
;
210 TAILQ_REMOVE(env->sc_routes, nr, nr_route)do { if (((nr)->nr_route.tqe_next) != ((void*)0)) (nr)->
nr_route.tqe_next->nr_route.tqe_prev = (nr)->nr_route.tqe_prev
; else (env->sc_routes)->tqh_last = (nr)->nr_route.tqe_prev
; *(nr)->nr_route.tqe_prev = (nr)->nr_route.tqe_next; ;
; } while (0)
;
211 free(nr);
212 env->sc_routecount--;
213 }
214 free(rt);
215 }
216 env->sc_routercount = 0;
217 }
218 if (what & CONFIG_ROUTES0x10 && env->sc_routes != NULL((void*)0)) {
219 while ((nr = TAILQ_FIRST(env->sc_routes)((env->sc_routes)->tqh_first)) != NULL((void*)0)) {
220 if ((rt = nr->nr_router) != NULL((void*)0))
221 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry)do { if (((nr)->nr_entry.tqe_next) != ((void*)0)) (nr)->
nr_entry.tqe_next->nr_entry.tqe_prev = (nr)->nr_entry.tqe_prev
; else (&rt->rt_netroutes)->tqh_last = (nr)->nr_entry
.tqe_prev; *(nr)->nr_entry.tqe_prev = (nr)->nr_entry.tqe_next
; ; ; } while (0)
;
222 TAILQ_REMOVE(env->sc_routes, nr, nr_route)do { if (((nr)->nr_route.tqe_next) != ((void*)0)) (nr)->
nr_route.tqe_next->nr_route.tqe_prev = (nr)->nr_route.tqe_prev
; else (env->sc_routes)->tqh_last = (nr)->nr_route.tqe_prev
; *(nr)->nr_route.tqe_prev = (nr)->nr_route.tqe_next; ;
; } while (0)
;
223 free(nr);
224 }
225 env->sc_routecount = 0;
226 }
227}
228
229int
230config_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(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
240
241 /*
242 * XXX Make sure that the reset message is sent
243 * immediately by flushing the imsg output buffer, before
244 * sending any other imsg that potentially include an fd.
245 * This should better be fixed in the imsg API itself.
246 */
247 proc_flush_imsg(ps, id, -1);
248 }
249
250 return (0);
251}
252
253int
254config_getreset(struct relayd *env, struct imsg *imsg)
255{
256 u_int mode;
257
258 IMSG_SIZE_CHECK(imsg, &mode)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&mode)) fatalx("bad length imsg received"); } while (0)
;
259 memcpy(&mode, imsg->data, sizeof(mode));
260
261 config_purge(env, mode);
262
263 return (0);
264}
265
266int
267config_getcfg(struct relayd *env, struct imsg *imsg)
268{
269 struct privsep *ps = env->sc_ps;
270 struct table *tb;
271 struct host *h, *ph;
272 u_int what;
273
274 if (IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct relayd_config))
275 return (0); /* ignore */
276
277 /* Update runtime flags */
278 memcpy(&env->sc_conf, imsg->data, sizeof(env->sc_conf));
279
280 what = ps->ps_what[privsep_process];
281
282 if (what & CONFIG_TABLES0x01) {
283 /* Update the tables */
284 TAILQ_FOREACH(tb, env->sc_tables, entry)for((tb) = ((env->sc_tables)->tqh_first); (tb) != ((void
*)0); (tb) = ((tb)->entry.tqe_next))
{
285 TAILQ_FOREACH(h, &tb->hosts, entry)for((h) = ((&tb->hosts)->tqh_first); (h) != ((void*
)0); (h) = ((h)->entry.tqe_next))
{
286 if (h->conf.parentid && (ph = host_find(env,
287 h->conf.parentid)) != NULL((void*)0)) {
288 SLIST_INSERT_HEAD(&ph->children,do { (h)->child.sle_next = (&ph->children)->slh_first
; (&ph->children)->slh_first = (h); } while (0)
289 h, child)do { (h)->child.sle_next = (&ph->children)->slh_first
; (&ph->children)->slh_first = (h); } while (0)
;
290 }
291 }
292 }
293 }
294
295 if (env->sc_conf.flags & (F_TLS0x00000800|F_TLSCLIENT0x00200000)) {
296 ssl_init(env);
297 if (what & CONFIG_CA_ENGINE0x40)
298 ca_engine_init(env);
299 }
300
301 if (privsep_process != PROC_PARENT)
302 proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL((void*)0), 0);
303
304 return (0);
305}
306
307int
308config_settable(struct relayd *env, struct table *tb)
309{
310 struct privsep *ps = env->sc_ps;
311 struct host *host;
312 int id, c;
313 struct iovec iov[2];
314
315 for (id = 0; id < PROC_MAX; id++) {
316 if ((ps->ps_what[id] & CONFIG_TABLES0x01) == 0 ||
317 id == privsep_process)
318 continue;
319
320 /* XXX need to send table to pfe for control socket */
321 if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
322 continue;
323
324 DPRINTF("%s: sending table %s %d to %s", __func__,do {} while(0)
325 tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id])do {} while(0);
326
327 c = 0;
328 iov[c].iov_base = &tb->conf;
329 iov[c++].iov_len = sizeof(tb->conf);
330 if (tb->sendbuf != NULL((void*)0)) {
331 iov[c].iov_base = tb->sendbuf;
332 iov[c++].iov_len = strlen(tb->sendbuf);
333 }
334
335 proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
336
337 TAILQ_FOREACH(host, &tb->hosts, entry)for((host) = ((&tb->hosts)->tqh_first); (host) != (
(void*)0); (host) = ((host)->entry.tqe_next))
{
338 proc_compose(ps, id, IMSG_CFG_HOST,
339 &host->conf, sizeof(host->conf));
340 }
341 }
342
343 return (0);
344}
345
346int
347config_gettable(struct relayd *env, struct imsg *imsg)
348{
349 struct table *tb;
350 size_t sb;
351 u_int8_t *p = imsg->data;
352 size_t s;
353
354 if ((tb = calloc(1, sizeof(*tb))) == NULL((void*)0))
355 return (-1);
356
357 IMSG_SIZE_CHECK(imsg, &tb->conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&tb->conf)) fatalx("bad length imsg received"); } while
(0)
;
358 memcpy(&tb->conf, p, sizeof(tb->conf));
359 s = sizeof(tb->conf);
360
361 sb = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - s;
362 if (sb > 0) {
363 if ((tb->sendbuf = get_string(p + s, sb)) == NULL((void*)0)) {
364 free(tb);
365 return (-1);
366 }
367 }
368 if (tb->conf.check == CHECK_BINSEND_EXPECT) {
369 tb->sendbinbuf = string2binary(tb->sendbuf);
370 if (tb->sendbinbuf == NULL((void*)0)) {
371 free(tb);
372 return (-1);
373 }
374 }
375
376 TAILQ_INIT(&tb->hosts)do { (&tb->hosts)->tqh_first = ((void*)0); (&tb
->hosts)->tqh_last = &(&tb->hosts)->tqh_first
; } while (0)
;
377 TAILQ_INSERT_TAIL(env->sc_tables, tb, entry)do { (tb)->entry.tqe_next = ((void*)0); (tb)->entry.tqe_prev
= (env->sc_tables)->tqh_last; *(env->sc_tables)->
tqh_last = (tb); (env->sc_tables)->tqh_last = &(tb)
->entry.tqe_next; } while (0)
;
378
379 env->sc_tablecount++;
380
381 DPRINTF("%s: %s %d received table %d (%s)", __func__,do {} while(0)
382 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
383 tb->conf.id, tb->conf.name)do {} while(0);
384
385 return (0);
386}
387
388int
389config_gethost(struct relayd *env, struct imsg *imsg)
390{
391 struct table *tb;
392 struct host *host;
393
394 if ((host = calloc(1, sizeof(*host))) == NULL((void*)0))
395 return (-1);
396
397 IMSG_SIZE_CHECK(imsg, &host->conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&host->conf)) fatalx("bad length imsg received"); } while
(0)
;
398 memcpy(&host->conf, imsg->data, sizeof(host->conf));
399
400 if (host_find(env, host->conf.id) != NULL((void*)0)) {
401 log_debug("%s: host %d already exists",
402 __func__, host->conf.id);
403 free(host);
404 return (-1);
405 }
406
407 if ((tb = table_find(env, host->conf.tableid)) == NULL((void*)0)) {
408 log_debug("%s: "
409 "received host for unknown table %d", __func__,
410 host->conf.tableid);
411 free(host);
412 return (-1);
413 }
414
415 host->tablename = tb->conf.name;
416 host->cte.s = -1;
417
418 SLIST_INIT(&host->children){ ((&host->children)->slh_first) = ((void*)0); };
419 TAILQ_INSERT_TAIL(&tb->hosts, host, entry)do { (host)->entry.tqe_next = ((void*)0); (host)->entry
.tqe_prev = (&tb->hosts)->tqh_last; *(&tb->hosts
)->tqh_last = (host); (&tb->hosts)->tqh_last = &
(host)->entry.tqe_next; } while (0)
;
420 TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry)do { (host)->globalentry.tqe_next = ((void*)0); (host)->
globalentry.tqe_prev = (&env->sc_hosts)->tqh_last; *
(&env->sc_hosts)->tqh_last = (host); (&env->
sc_hosts)->tqh_last = &(host)->globalentry.tqe_next
; } while (0)
;
421
422 DPRINTF("%s: %s %d received host %s for table %s", __func__,do {} while(0)
423 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
424 host->conf.name, tb->conf.name)do {} while(0);
425
426 return (0);
427}
428
429int
430config_setrdr(struct relayd *env, struct rdr *rdr)
431{
432 struct privsep *ps = env->sc_ps;
433 struct address *virt;
434 int id;
435
436 for (id = 0; id < PROC_MAX; id++) {
437 if ((ps->ps_what[id] & CONFIG_RDRS0x02) == 0 ||
438 id == privsep_process)
439 continue;
440
441 DPRINTF("%s: sending rdr %s to %s", __func__,do {} while(0)
442 rdr->conf.name, ps->ps_title[id])do {} while(0);
443
444 proc_compose(ps, id, IMSG_CFG_RDR,
445 &rdr->conf, sizeof(rdr->conf));
446
447 TAILQ_FOREACH(virt, &rdr->virts, entry)for((virt) = ((&rdr->virts)->tqh_first); (virt) != (
(void*)0); (virt) = ((virt)->entry.tqe_next))
{
448 virt->rdrid = rdr->conf.id;
449 proc_compose(ps, id, IMSG_CFG_VIRT,
450 virt, sizeof(*virt));
451 }
452 }
453
454 return (0);
455}
456
457int
458config_getrdr(struct relayd *env, struct imsg *imsg)
459{
460 struct rdr *rdr;
461
462 if ((rdr = calloc(1, sizeof(*rdr))) == NULL((void*)0))
463 return (-1);
464
465 IMSG_SIZE_CHECK(imsg, &rdr->conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&rdr->conf)) fatalx("bad length imsg received"); } while
(0)
;
466 memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
467
468 if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL((void*)0)) {
469 log_debug("%s: table not found", __func__);
470 free(rdr);
471 return (-1);
472 }
473 if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL((void*)0)) {
474 rdr->conf.backup_id = EMPTY_TABLE(2147483647 *2U +1U);
475 rdr->backup = &env->sc_empty_table;
476 }
477
478 TAILQ_INIT(&rdr->virts)do { (&rdr->virts)->tqh_first = ((void*)0); (&rdr
->virts)->tqh_last = &(&rdr->virts)->tqh_first
; } while (0)
;
479 TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry)do { (rdr)->entry.tqe_next = ((void*)0); (rdr)->entry.tqe_prev
= (env->sc_rdrs)->tqh_last; *(env->sc_rdrs)->tqh_last
= (rdr); (env->sc_rdrs)->tqh_last = &(rdr)->entry
.tqe_next; } while (0)
;
480
481 env->sc_rdrcount++;
482
483 DPRINTF("%s: %s %d received rdr %s", __func__,do {} while(0)
484 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
485 rdr->conf.name)do {} while(0);
486
487 return (0);
488}
489
490int
491config_getvirt(struct relayd *env, struct imsg *imsg)
492{
493 struct rdr *rdr;
494 struct address *virt;
495
496 IMSG_SIZE_CHECK(imsg, virt)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*virt)) fatalx("bad length imsg received"); } while (0)
;
497
498 if ((virt = calloc(1, sizeof(*virt))) == NULL((void*)0))
499 return (-1);
500 memcpy(virt, imsg->data, sizeof(*virt));
501
502 if ((rdr = rdr_find(env, virt->rdrid)) == NULL((void*)0)) {
503 log_debug("%s: rdr not found", __func__);
504 free(virt);
505 return (-1);
506 }
507
508 TAILQ_INSERT_TAIL(&rdr->virts, virt, entry)do { (virt)->entry.tqe_next = ((void*)0); (virt)->entry
.tqe_prev = (&rdr->virts)->tqh_last; *(&rdr->
virts)->tqh_last = (virt); (&rdr->virts)->tqh_last
= &(virt)->entry.tqe_next; } while (0)
;
509
510 DPRINTF("%s: %s %d received address for rdr %s", __func__,do {} while(0)
511 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
512 rdr->conf.name)do {} while(0);
513
514 return (0);
515}
516
517int
518config_setrt(struct relayd *env, struct router *rt)
519{
520 struct privsep *ps = env->sc_ps;
521 struct netroute *nr;
522 int id;
523
524 for (id = 0; id < PROC_MAX; id++) {
525 if ((ps->ps_what[id] & CONFIG_RTS0x20) == 0 ||
526 id == privsep_process)
527 continue;
528
529 DPRINTF("%s: sending router %s to %s tbl %d", __func__,do {} while(0)
530 rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable)do {} while(0);
531
532 proc_compose(ps, id, IMSG_CFG_ROUTER,
533 &rt->rt_conf, sizeof(rt->rt_conf));
534
535 TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry)for((nr) = ((&rt->rt_netroutes)->tqh_first); (nr) !=
((void*)0); (nr) = ((nr)->nr_entry.tqe_next))
{
536 proc_compose(ps, id, IMSG_CFG_ROUTE,
537 &nr->nr_conf, sizeof(nr->nr_conf));
538 }
539 }
540
541 return (0);
542}
543
544int
545config_getrt(struct relayd *env, struct imsg *imsg)
546{
547 struct router *rt;
548
549 if ((rt = calloc(1, sizeof(*rt))) == NULL((void*)0))
550 return (-1);
551
552 IMSG_SIZE_CHECK(imsg, &rt->rt_conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&rt->rt_conf)) fatalx("bad length imsg received"); }
while (0)
;
553 memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
554
555 if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL((void*)0)) {
556 log_debug("%s: table not found", __func__);
557 free(rt);
558 return (-1);
559 }
560
561 TAILQ_INIT(&rt->rt_netroutes)do { (&rt->rt_netroutes)->tqh_first = ((void*)0); (
&rt->rt_netroutes)->tqh_last = &(&rt->rt_netroutes
)->tqh_first; } while (0)
;
562 TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry)do { (rt)->rt_entry.tqe_next = ((void*)0); (rt)->rt_entry
.tqe_prev = (env->sc_rts)->tqh_last; *(env->sc_rts)->
tqh_last = (rt); (env->sc_rts)->tqh_last = &(rt)->
rt_entry.tqe_next; } while (0)
;
563
564 env->sc_routercount++;
565
566 DPRINTF("%s: %s %d received router %s", __func__,do {} while(0)
567 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
568 rt->rt_conf.name)do {} while(0);
569
570 return (0);
571}
572
573int
574config_getroute(struct relayd *env, struct imsg *imsg)
575{
576 struct router *rt;
577 struct netroute *nr;
578
579 if ((nr = calloc(1, sizeof(*nr))) == NULL((void*)0))
580 return (-1);
581
582 IMSG_SIZE_CHECK(imsg, &nr->nr_conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&nr->nr_conf)) fatalx("bad length imsg received"); }
while (0)
;
583 memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
584
585 if (route_find(env, nr->nr_conf.id) != NULL((void*)0)) {
586 log_debug("%s: route %d already exists",
587 __func__, nr->nr_conf.id);
588 free(nr);
589 return (-1);
590 }
591
592 if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL((void*)0)) {
593 log_debug("%s: received route for unknown router", __func__);
594 free(nr);
595 return (-1);
596 }
597
598 nr->nr_router = rt;
599
600 TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route)do { (nr)->nr_route.tqe_next = ((void*)0); (nr)->nr_route
.tqe_prev = (env->sc_routes)->tqh_last; *(env->sc_routes
)->tqh_last = (nr); (env->sc_routes)->tqh_last = &
(nr)->nr_route.tqe_next; } while (0)
;
601 TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry)do { (nr)->nr_entry.tqe_next = ((void*)0); (nr)->nr_entry
.tqe_prev = (&rt->rt_netroutes)->tqh_last; *(&rt
->rt_netroutes)->tqh_last = (nr); (&rt->rt_netroutes
)->tqh_last = &(nr)->nr_entry.tqe_next; } while (0)
;
602
603 env->sc_routecount++;
604
605 DPRINTF("%s: %s %d received route %d for router %s", __func__,do {} while(0)
606 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
607 nr->nr_conf.id, rt->rt_conf.name)do {} while(0);
608
609 return (0);
610}
611
612int
613config_setproto(struct relayd *env, struct protocol *proto)
614{
615 struct privsep *ps = env->sc_ps;
616 int id;
617 struct iovec iov[IOV_MAX1024];
618 size_t c;
619
620 for (id = 0; id < PROC_MAX; id++) {
621 if ((ps->ps_what[id] & CONFIG_PROTOS0x08) == 0 ||
622 id == privsep_process)
623 continue;
624
625 DPRINTF("%s: sending protocol %s to %s", __func__,do {} while(0)
626 proto->name, ps->ps_title[id])do {} while(0);
627
628 c = 0;
629 iov[c].iov_base = proto;
630 iov[c++].iov_len = sizeof(*proto);
631
632 if (proto->style != NULL((void*)0)) {
633 iov[c].iov_base = proto->style;
634 iov[c++].iov_len = strlen(proto->style) + 1;
635 }
636
637 proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
638 }
639
640 return (0);
641}
642
643int
644config_setrule(struct relayd *env, struct protocol *proto)
645{
646 struct privsep *ps = env->sc_ps;
647 struct relay_rule *rule;
648 struct iovec iov[IOV_MAX1024];
649 int id;
650 size_t c, i;
651
652 for (id = 0; id < PROC_MAX; id++) {
653 if ((ps->ps_what[id] & CONFIG_PROTOS0x08) == 0 ||
654 id == privsep_process)
655 continue;
656
657 DPRINTF("%s: sending rules %s to %s", __func__,do {} while(0)
658 proto->name, ps->ps_title[id])do {} while(0);
659
660 /* Now send all the rules */
661 TAILQ_FOREACH(rule, &proto->rules, rule_entry)for((rule) = ((&proto->rules)->tqh_first); (rule) !=
((void*)0); (rule) = ((rule)->rule_entry.tqe_next))
{
662 rule->rule_protoid = proto->id;
663 bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
664 c = 0;
665 iov[c].iov_base = rule;
666 iov[c++].iov_len = sizeof(*rule);
667 for (i = 1; i < KEY_TYPE_MAX; i++) {
668 if (rule->rule_kv[i].kv_key != NULL((void*)0)) {
669 rule->rule_ctl.kvlen[i].key =
670 strlen(rule->rule_kv[i].kv_key);
671 iov[c].iov_base =
672 rule->rule_kv[i].kv_key;
673 iov[c++].iov_len =
674 rule->rule_ctl.kvlen[i].key;
675 } else
676 rule->rule_ctl.kvlen[i].key = -1;
677 if (rule->rule_kv[i].kv_value != NULL((void*)0)) {
678 rule->rule_ctl.kvlen[i].value =
679 strlen(rule->rule_kv[i].kv_value);
680 iov[c].iov_base =
681 rule->rule_kv[i].kv_value;
682 iov[c++].iov_len =
683 rule->rule_ctl.kvlen[i].value;
684 } else
685 rule->rule_ctl.kvlen[i].value = -1;
686 }
687
688 proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
689 }
690 }
691
692 return (0);
693}
694
695int
696config_getproto(struct relayd *env, struct imsg *imsg)
697{
698 struct protocol *proto;
699 size_t styl;
700 size_t s;
701 u_int8_t *p = imsg->data;
702
703 if ((proto = calloc(1, sizeof(*proto))) == NULL((void*)0))
704 return (-1);
705
706 IMSG_SIZE_CHECK(imsg, proto)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*proto)) fatalx("bad length imsg received"); } while (0)
;
707 memcpy(proto, p, sizeof(*proto));
708 s = sizeof(*proto);
709
710 styl = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - s;
711 proto->style = NULL((void*)0);
712 if (styl > 0) {
713 if ((proto->style = get_string(p + s, styl - 1)) == NULL((void*)0)) {
714 free(proto);
715 return (-1);
716 }
717 }
718
719 TAILQ_INIT(&proto->rules)do { (&proto->rules)->tqh_first = ((void*)0); (&
proto->rules)->tqh_last = &(&proto->rules)->
tqh_first; } while (0)
;
720 TAILQ_INIT(&proto->tlscerts)do { (&proto->tlscerts)->tqh_first = ((void*)0); (&
proto->tlscerts)->tqh_last = &(&proto->tlscerts
)->tqh_first; } while (0)
;
721 proto->tlscapass = NULL((void*)0);
722
723 TAILQ_INSERT_TAIL(env->sc_protos, proto, entry)do { (proto)->entry.tqe_next = ((void*)0); (proto)->entry
.tqe_prev = (env->sc_protos)->tqh_last; *(env->sc_protos
)->tqh_last = (proto); (env->sc_protos)->tqh_last = &
(proto)->entry.tqe_next; } while (0)
;
724
725 env->sc_protocount++;
726
727 DPRINTF("%s: %s %d received protocol %s", __func__,do {} while(0)
728 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
729 proto->name)do {} while(0);
730
731 return (0);
732}
733
734int
735config_getrule(struct relayd *env, struct imsg *imsg)
736{
737 struct protocol *proto;
738 struct relay_rule *rule;
739 size_t s, i;
740 u_int8_t *p = imsg->data;
741 ssize_t len;
742
743 if ((rule = calloc(1, sizeof(*rule))) == NULL((void*)0))
744 return (-1);
745
746 IMSG_SIZE_CHECK(imsg, rule)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*rule)) fatalx("bad length imsg received"); } while (0)
;
747 memcpy(rule, p, sizeof(*rule));
748 s = sizeof(*rule);
749 len = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - s;
750
751 if ((proto = proto_find(env, rule->rule_protoid)) == NULL((void*)0)) {
752 free(rule);
753 return (-1);
754 }
755
756#define GETKV(_n, _f){ if (rule->rule_ctl.kvlen[_n]._f >= 0) { if ((len <
rule->rule_ctl.kvlen[_n]._f) || (rule->rule_kv[_n].kv__f
= get_string(p + s, rule->rule_ctl.kvlen[_n]._f)) == ((void
*)0)) { free(rule); return (-1); } s += rule->rule_ctl.kvlen
[_n]._f; len -= rule->rule_ctl.kvlen[_n]._f; do {} while(0
); } }
{ \
757 if (rule->rule_ctl.kvlen[_n]._f >= 0) { \
758 /* Also accept "empty" 0-length strings */ \
759 if ((len < rule->rule_ctl.kvlen[_n]._f) || \
760 (rule->rule_kv[_n].kv_##_f = \
761 get_string(p + s, \
762 rule->rule_ctl.kvlen[_n]._f)) == NULL((void*)0)) { \
763 free(rule); \
764 return (-1); \
765 } \
766 s += rule->rule_ctl.kvlen[_n]._f; \
767 len -= rule->rule_ctl.kvlen[_n]._f; \
768 \
769 DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__, \do {} while(0)
770 #_n, #_f, rule->rule_ctl.kvlen[_n]._f, \do {} while(0)
771 rule->rule_kv[_n].kv_option, \do {} while(0)
772 rule->rule_kv[_n].kv_##_f)do {} while(0); \
773 } \
774}
775
776 memset(&rule->rule_kv[0], 0, sizeof(struct kv));
777 for (i = 1; i < KEY_TYPE_MAX; i++) {
778 TAILQ_INIT(&rule->rule_kv[i].kv_children)do { (&rule->rule_kv[i].kv_children)->tqh_first = (
(void*)0); (&rule->rule_kv[i].kv_children)->tqh_last
= &(&rule->rule_kv[i].kv_children)->tqh_first;
} while (0)
;
779 GETKV(i, key){ if (rule->rule_ctl.kvlen[i].key >= 0) { if ((len <
rule->rule_ctl.kvlen[i].key) || (rule->rule_kv[i].kv_key
= get_string(p + s, rule->rule_ctl.kvlen[i].key)) == ((void
*)0)) { free(rule); return (-1); } s += rule->rule_ctl.kvlen
[i].key; len -= rule->rule_ctl.kvlen[i].key; do {} while(0
); } }
;
780 GETKV(i, value){ if (rule->rule_ctl.kvlen[i].value >= 0) { if ((len <
rule->rule_ctl.kvlen[i].value) || (rule->rule_kv[i].kv_value
= get_string(p + s, rule->rule_ctl.kvlen[i].value)) == ((
void*)0)) { free(rule); return (-1); } s += rule->rule_ctl
.kvlen[i].value; len -= rule->rule_ctl.kvlen[i].value; do {
} while(0); } }
;
781 }
782
783 if (rule->rule_labelname[0])
784 rule->rule_label = label_name2id(rule->rule_labelname);
785
786 if (rule->rule_tagname[0])
787 rule->rule_tag = tag_name2id(rule->rule_tagname);
788
789 if (rule->rule_taggedname[0])
790 rule->rule_tagged = tag_name2id(rule->rule_taggedname);
791
792 rule->rule_id = proto->rulecount++;
793
794 TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry)do { (rule)->rule_entry.tqe_next = ((void*)0); (rule)->
rule_entry.tqe_prev = (&proto->rules)->tqh_last; *(
&proto->rules)->tqh_last = (rule); (&proto->
rules)->tqh_last = &(rule)->rule_entry.tqe_next; } while
(0)
;
795
796 DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,do {} while(0)
797 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
798 rule->rule_id, proto->name)do {} while(0);
799
800 return (0);
801}
802
803static int
804config_setrelayfd(struct privsep *ps, int id, int n,
805 objid_t obj_id, objid_t rlay_id, enum fd_type type, int ofd)
806{
807 struct ctl_relayfd rfd;
808 int fd;
809
810 rfd.id = obj_id;
811 rfd.relayid = rlay_id;
812 rfd.type = type;
813
814 if ((fd = dup(ofd)) == -1)
815 return (-1);
816 if (proc_compose_imsg(ps, id, n, IMSG_CFG_RELAY_FD, -1, fd,
817 &rfd, sizeof(rfd)) != 0)
818 return (-1);
819
820 return (0);
821}
822
823int
824config_setrelay(struct relayd *env, struct relay *rlay)
825{
826 struct privsep *ps = env->sc_ps;
827 struct ctl_relaytable crt;
828 struct relay_table *rlt;
829 struct relay_config rl;
830 struct relay_cert *cert;
831 int id;
832 int fd, n, m;
833 struct iovec iov[6];
834 size_t c;
835 u_int what;
836
837 /* opens listening sockets etc. */
838 if (relay_privinit(rlay) == -1)
839 return (-1);
840
841 for (id = 0; id < PROC_MAX; id++) {
842 what = ps->ps_what[id];
843
844 if ((what & CONFIG_RELAYS0x04) == 0 || id == privsep_process)
845 continue;
846
847 DPRINTF("%s: sending relay %s to %s fd %d", __func__,do {} while(0)
848 rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s)do {} while(0);
849
850 memcpy(&rl, &rlay->rl_conf, sizeof(rl));
851
852 c = 0;
853 iov[c].iov_base = &rl;
854 iov[c++].iov_len = sizeof(rl);
855
856 if ((what & CONFIG_CA_ENGINE0x40) == 0 &&
857 rl.tls_cakey_len) {
858 iov[c].iov_base = rlay->rl_tls_cakey;
859 iov[c++].iov_len = rl.tls_cakey_len;
860 } else
861 rl.tls_cakey_len = 0;
862
863 if (id == PROC_RELAY) {
864 /* XXX imsg code will close the fd after 1st call */
865 n = -1;
866 proc_range(ps, id, &n, &m);
867 for (n = 0; n < m; n++) {
868 if ((fd = dup(rlay->rl_s)) == -1)
869 return (-1);
870 if (proc_composev_imsg(ps, id, n,
871 IMSG_CFG_RELAY, -1, fd, iov, c) != 0) {
872 log_warn("%s: failed to compose "
873 "IMSG_CFG_RELAY imsg for `%s'",
874 __func__, rlay->rl_conf.name);
875 return (-1);
876 }
877 /* Prevent fd exhaustion in the parent. */
878 if (proc_flush_imsg(ps, id, n) == -1) {
879 log_warn("%s: failed to flush "
880 "IMSG_CFG_RELAY imsg for `%s'",
881 __func__, rlay->rl_conf.name);
882 return (-1);
883 }
884 }
885 } else {
886 if (proc_composev(ps, id,
887 IMSG_CFG_RELAY, iov, c) != 0) {
888 log_warn("%s: failed to compose "
889 "IMSG_CFG_RELAY imsg for `%s'",
890 __func__, rlay->rl_conf.name);
891 return (-1);
892 }
893 }
894
895 /* cert keypairs */
896 TAILQ_FOREACH(cert, env->sc_certs, cert_entry)for((cert) = ((env->sc_certs)->tqh_first); (cert) != ((
void*)0); (cert) = ((cert)->cert_entry.tqe_next))
{
897 if (cert->cert_relayid != rlay->rl_conf.id)
898 continue;
899 n = -1;
900 proc_range(ps, id, &n, &m);
901 for (n = 0; (what & CONFIG_CERTS0x80) && n < m; n++) {
902 if (cert->cert_fd != -1 &&
903 config_setrelayfd(ps, id, n,
904 cert->cert_id, cert->cert_relayid,
905 RELAY_FD_CERT, cert->cert_fd) == -1) {
906 log_warn("%s: fd passing failed for "
907 "`%s'", __func__,
908 rlay->rl_conf.name);
909 return (-1);
910 }
911 if (id == PROC_RELAY &&
912 cert->cert_ocsp_fd != -1 &&
913 config_setrelayfd(ps, id, n,
914 cert->cert_id, cert->cert_relayid,
915 RELAY_FD_OCSP, cert->cert_ocsp_fd) == -1) {
916 log_warn("%s: fd passing failed for "
917 "`%s'", __func__,
918 rlay->rl_conf.name);
919 return (-1);
920 }
921 if (id == PROC_CA &&
922 cert->cert_key_fd != -1 &&
923 config_setrelayfd(ps, id, n,
924 cert->cert_id, cert->cert_relayid,
925 RELAY_FD_KEY, cert->cert_key_fd) == -1) {
926 log_warn("%s: fd passing failed for "
927 "`%s'", __func__,
928 rlay->rl_conf.name);
929 return (-1);
930 }
931 }
932 }
933
934 /* CA certs */
935 if (what & CONFIG_CERTS0x80) {
936 n = -1;
937 proc_range(ps, id, &n, &m);
938 for (n = 0; n < m; n++) {
939 if (rlay->rl_tls_ca_fd != -1 &&
940 config_setrelayfd(ps, id, n, 0,
941 rlay->rl_conf.id, RELAY_FD_CACERT,
942 rlay->rl_tls_ca_fd) == -1) {
943 log_warn("%s: fd passing failed for "
944 "`%s'", __func__,
945 rlay->rl_conf.name);
946 return (-1);
947 }
948 if (rlay->rl_tls_cacert_fd != -1 &&
949 config_setrelayfd(ps, id, n, 0,
950 rlay->rl_conf.id, RELAY_FD_CAFILE,
951 rlay->rl_tls_cacert_fd) == -1) {
952 log_warn("%s: fd passing failed for "
953 "`%s'", __func__,
954 rlay->rl_conf.name);
955 return (-1);
956 }
957 /* Prevent fd exhaustion in the parent. */
958 if (proc_flush_imsg(ps, id, n) == -1) {
959 log_warn("%s: failed to flush "
960 "IMSG_CFG_RELAY imsg for `%s'",
961 __func__, rlay->rl_conf.name);
962 return (-1);
963 }
964 }
965 }
966
967 if ((what & CONFIG_TABLES0x01) == 0)
968 continue;
969
970 /* Now send the tables associated to this relay */
971 TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry)for((rlt) = ((&rlay->rl_tables)->tqh_first); (rlt) !=
((void*)0); (rlt) = ((rlt)->rlt_entry.tqe_next))
{
972 crt.id = rlt->rlt_table->conf.id;
973 crt.relayid = rlay->rl_conf.id;
974 crt.mode = rlt->rlt_mode;
975 crt.flags = rlt->rlt_flags;
976
977 c = 0;
978 iov[c].iov_base = &crt;
979 iov[c++].iov_len = sizeof(crt);
980
981 proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
982 }
983 }
984
985 /* Close server socket early to prevent fd exhaustion in the parent. */
986 if (rlay->rl_s != -1) {
987 close(rlay->rl_s);
988 rlay->rl_s = -1;
989 }
990 if (rlay->rl_tls_cacert_fd != -1) {
991 close(rlay->rl_tls_cacert_fd);
992 rlay->rl_tls_cacert_fd = -1;
993 }
994 if (rlay->rl_tls_ca_fd != -1) {
995 close(rlay->rl_tls_ca_fd);
996 rlay->rl_tls_ca_fd = -1;
997 }
998 TAILQ_FOREACH(cert, env->sc_certs, cert_entry)for((cert) = ((env->sc_certs)->tqh_first); (cert) != ((
void*)0); (cert) = ((cert)->cert_entry.tqe_next))
{
999 if (cert->cert_relayid != rlay->rl_conf.id)
1000 continue;
1001
1002 if (cert->cert_fd != -1) {
1003 close(cert->cert_fd);
1004 cert->cert_fd = -1;
1005 }
1006 if (cert->cert_key_fd != -1) {
1007 close(cert->cert_key_fd);
1008 cert->cert_key_fd = -1;
1009 }
1010 if (cert->cert_ocsp_fd != -1) {
1011 close(cert->cert_ocsp_fd);
1012 cert->cert_ocsp_fd = -1;
1013 }
1014 }
1015
1016 return (0);
1017}
1018
1019int
1020config_getrelay(struct relayd *env, struct imsg *imsg)
1021{
1022 struct privsep *ps = env->sc_ps;
1023 struct relay *rlay;
1024 u_int8_t *p = imsg->data;
1025 size_t s;
1026
1027 if ((rlay = calloc(1, sizeof(*rlay))) == NULL((void*)0))
1028 return (-1);
1029
1030 IMSG_SIZE_CHECK(imsg, &rlay->rl_conf)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&rlay->rl_conf)) fatalx("bad length imsg received");
} while (0)
;
1031 memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
1032 s = sizeof(rlay->rl_conf);
1033
1034 rlay->rl_s = imsg->fd;
1035 rlay->rl_tls_ca_fd = -1;
1036 rlay->rl_tls_cacert_fd = -1;
1037
1038 if (ps->ps_what[privsep_process] & CONFIG_PROTOS0x08) {
1039 if (rlay->rl_conf.proto == EMPTY_ID(2147483647 *2U +1U))
1040 rlay->rl_proto = &env->sc_proto_default;
1041 else if ((rlay->rl_proto =
1042 proto_find(env, rlay->rl_conf.proto)) == NULL((void*)0)) {
1043 log_debug("%s: unknown protocol", __func__);
1044 goto fail;
1045 }
1046 }
1047
1048 if ((off_t)(IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - s) <
1049 (rlay->rl_conf.tls_cakey_len)) {
1050 log_debug("%s: invalid message length", __func__);
1051 goto fail;
1052 }
1053
1054 if (rlay->rl_conf.tls_cakey_len) {
1055 if ((rlay->rl_tls_cakey = get_data(p + s,
1056 rlay->rl_conf.tls_cakey_len)) == NULL((void*)0))
1057 goto fail;
1058 s += rlay->rl_conf.tls_cakey_len;
Value stored to 's' is never read
1059 }
1060
1061 TAILQ_INIT(&rlay->rl_tables)do { (&rlay->rl_tables)->tqh_first = ((void*)0); (&
rlay->rl_tables)->tqh_last = &(&rlay->rl_tables
)->tqh_first; } while (0)
;
1062 TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry)do { (rlay)->rl_entry.tqe_next = ((void*)0); (rlay)->rl_entry
.tqe_prev = (env->sc_relays)->tqh_last; *(env->sc_relays
)->tqh_last = (rlay); (env->sc_relays)->tqh_last = &
(rlay)->rl_entry.tqe_next; } while (0)
;
1063
1064 env->sc_relaycount++;
1065
1066 DPRINTF("%s: %s %d received relay %s", __func__,do {} while(0)
1067 ps->ps_title[privsep_process], ps->ps_instance,do {} while(0)
1068 rlay->rl_conf.name)do {} while(0);
1069
1070 return (0);
1071
1072 fail:
1073 free(rlay->rl_tls_cakey);
1074 close(rlay->rl_s);
1075 free(rlay);
1076 return (-1);
1077}
1078
1079int
1080config_getrelaytable(struct relayd *env, struct imsg *imsg)
1081{
1082 struct relay_table *rlt = NULL((void*)0);
1083 struct ctl_relaytable crt;
1084 struct relay *rlay;
1085 struct table *table;
1086 u_int8_t *p = imsg->data;
1087
1088 IMSG_SIZE_CHECK(imsg, &crt)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&crt)) fatalx("bad length imsg received"); } while (0)
;
1089 memcpy(&crt, p, sizeof(crt));
1090
1091 if ((rlay = relay_find(env, crt.relayid)) == NULL((void*)0)) {
1092 log_debug("%s: unknown relay", __func__);
1093 goto fail;
1094 }
1095
1096 if ((table = table_find(env, crt.id)) == NULL((void*)0)) {
1097 log_debug("%s: unknown table", __func__);
1098 goto fail;
1099 }
1100
1101 if ((rlt = calloc(1, sizeof(*rlt))) == NULL((void*)0))
1102 goto fail;
1103
1104 rlt->rlt_table = table;
1105 rlt->rlt_mode = crt.mode;
1106 rlt->rlt_flags = crt.flags;
1107
1108 TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry)do { (rlt)->rlt_entry.tqe_next = ((void*)0); (rlt)->rlt_entry
.tqe_prev = (&rlay->rl_tables)->tqh_last; *(&rlay
->rl_tables)->tqh_last = (rlt); (&rlay->rl_tables
)->tqh_last = &(rlt)->rlt_entry.tqe_next; } while (
0)
;
1109
1110 DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,do {} while(0)
1111 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
1112 table->conf.name, rlay->rl_conf.name)do {} while(0);
1113
1114 return (0);
1115
1116 fail:
1117 free(rlt);
1118 return (-1);
1119}
1120
1121int
1122config_getrelayfd(struct relayd *env, struct imsg *imsg)
1123{
1124 struct ctl_relayfd crfd;
1125 struct relay *rlay = NULL((void*)0);
1126 struct relay_cert *cert;
1127 u_int8_t *p = imsg->data;
1128
1129 IMSG_SIZE_CHECK(imsg, &crfd)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*&crfd)) fatalx("bad length imsg received"); } while (0)
;
1130 memcpy(&crfd, p, sizeof(crfd));
1131
1132 switch (crfd.type) {
1133 case RELAY_FD_CERT:
1134 case RELAY_FD_KEY:
1135 case RELAY_FD_OCSP:
1136 if ((cert = cert_find(env, crfd.id)) == NULL((void*)0)) {
1137 if ((cert = cert_add(env, crfd.id)) == NULL((void*)0))
1138 return (-1);
1139 cert->cert_relayid = crfd.relayid;
1140 }
1141 /* FALLTHROUGH */
1142 default:
1143 if ((rlay = relay_find(env, crfd.relayid)) == NULL((void*)0)) {
1144 log_debug("%s: unknown relay", __func__);
1145 return (-1);
1146 }
1147 break;
1148 }
1149
1150 switch (crfd.type) {
1151 case RELAY_FD_CERT:
1152 cert->cert_fd = imsg->fd;
1153 break;
1154 case RELAY_FD_KEY:
1155 cert->cert_key_fd = imsg->fd;
1156 break;
1157 case RELAY_FD_OCSP:
1158 cert->cert_ocsp_fd = imsg->fd;
1159 break;
1160 case RELAY_FD_CACERT:
1161 rlay->rl_tls_ca_fd = imsg->fd;
1162 break;
1163 case RELAY_FD_CAFILE:
1164 rlay->rl_tls_cacert_fd = imsg->fd;
1165 break;
1166 }
1167
1168 DPRINTF("%s: %s %d received relay fd %d type %d for relay %s", __func__,do {} while(0)
1169 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,do {} while(0)
1170 imsg->fd, crfd.type, rlay->rl_conf.name)do {} while(0);
1171
1172 return (0);
1173}