File: | src/usr.sbin/relayd/config.c |
Warning: | line 1058, column 3 Value stored to 's' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
33 | int |
34 | config_init(struct relayd *env) |
35 | { |
36 | struct privsep *ps = env->sc_ps; |
37 | u_int what; |
38 | |
39 | /* Global configuration */ |
40 | if (privsep_process == PROC_PARENT) { |
41 | env->sc_conf.timeout.tv_sec = CHECK_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 | |
137 | void |
138 | config_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 | |
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(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 | |
253 | int |
254 | config_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 | |
266 | int |
267 | config_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 | |
307 | int |
308 | config_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 | |
346 | int |
347 | config_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 | |
388 | int |
389 | config_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 | |
429 | int |
430 | config_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 | |
457 | int |
458 | config_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 | |
490 | int |
491 | config_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 | |
517 | int |
518 | config_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 | |
544 | int |
545 | config_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 | |
573 | int |
574 | config_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 | |
612 | int |
613 | config_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 | |
643 | int |
644 | config_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 | |
695 | int |
696 | config_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 | |
734 | int |
735 | config_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 | |
803 | static int |
804 | config_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 | |
823 | int |
824 | config_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 | |
1019 | int |
1020 | config_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 | |
1079 | int |
1080 | config_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 | |
1121 | int |
1122 | config_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 | } |