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