]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldpe.c
ldpd: simplify initialization of the child processes
[mirror_frr.git] / ldpd / ldpe.c
CommitLineData
8429abe0
RW
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
eac6e3f0 22#include <zebra.h>
8429abe0
RW
23
24#include "ldpd.h"
25#include "ldpe.h"
26#include "lde.h"
27#include "control.h"
28#include "log.h"
eac6e3f0
RW
29#include "ldp_debug.h"
30
31#include <lib/log.h>
32#include "memory.h"
33#include "privs.h"
34#include "sigevent.h"
35
36static void ldpe_shutdown(void);
37static int ldpe_dispatch_main(struct thread *);
38static int ldpe_dispatch_lde(struct thread *);
39#ifdef __OpenBSD__
40static int ldpe_dispatch_pfkey(struct thread *);
41#endif
8429abe0
RW
42static void ldpe_setup_sockets(int, int, int, int);
43static void ldpe_close_sockets(int);
44static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45
46struct ldpd_conf *leconf;
eac6e3f0 47#ifdef __OpenBSD__
8429abe0 48struct ldpd_sysdep sysdep;
eac6e3f0 49#endif
8429abe0 50
28e8294c 51static struct imsgev *iev_main, *iev_main_sync;
8429abe0 52static struct imsgev *iev_lde;
eac6e3f0
RW
53#ifdef __OpenBSD__
54static struct thread *pfkey_ev;
55#endif
8429abe0 56
eac6e3f0
RW
57/* Master of threads. */
58struct thread_master *master;
59
60/* ldpe privileges */
61static zebra_capabilities_t _caps_p [] =
62{
63 ZCAP_BIND,
64 ZCAP_NET_ADMIN
65};
66
67struct zebra_privs_t ldpe_privs =
68{
b2f36157
DL
69#if defined(FRR_USER) && defined(FRR_GROUP)
70 .user = FRR_USER,
71 .group = FRR_GROUP,
eac6e3f0
RW
72#endif
73#if defined(VTY_GROUP)
74 .vty_group = VTY_GROUP,
75#endif
76 .caps_p = _caps_p,
77 .cap_num_p = array_size(_caps_p),
78 .cap_num_i = 0
79};
80
81/* SIGINT / SIGTERM handler. */
8429abe0 82static void
eac6e3f0 83sigint(void)
8429abe0 84{
eac6e3f0 85 ldpe_shutdown();
8429abe0
RW
86}
87
eac6e3f0
RW
88static struct quagga_signal_t ldpe_signals[] =
89{
1e7e440f
RW
90 {
91 .signal = SIGHUP,
92 /* ignore */
93 },
eac6e3f0
RW
94 {
95 .signal = SIGINT,
96 .handler = &sigint,
97 },
98 {
99 .signal = SIGTERM,
100 .handler = &sigint,
101 },
102};
103
8429abe0
RW
104/* label distribution protocol engine */
105void
274f5abf 106ldpe(void)
8429abe0 107{
eac6e3f0 108 struct thread thread;
8429abe0 109
eac6e3f0 110#ifdef HAVE_SETPROCTITLE
8429abe0 111 setproctitle("ldp engine");
eac6e3f0 112#endif
8429abe0 113 ldpd_process = PROC_LDP_ENGINE;
fa68f9da 114 log_procname = log_procnames[ldpd_process];
8429abe0 115
eac6e3f0 116 master = thread_master_create();
8429abe0
RW
117
118 /* setup signal handler */
eac6e3f0 119 signal_init(master, array_size(ldpe_signals), ldpe_signals);
8429abe0 120
28e8294c
RW
121 /* setup pipes and event handlers to the parent process */
122 if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
8429abe0 123 fatal(NULL);
28e8294c 124 imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
eac6e3f0
RW
125 iev_main->handler_read = ldpe_dispatch_main;
126 iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
127 iev_main, iev_main->ibuf.fd);
128 iev_main->handler_write = ldp_write_handler;
28e8294c
RW
129
130 if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
131 fatal(NULL);
132 imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
eac6e3f0 133
274f5abf
RW
134 /* create base configuration */
135 leconf = config_new_empty();
136
137 /* Fetch next active thread. */
138 while (thread_fetch(master, &thread))
139 thread_call(&thread);
140}
141
142void
143ldpe_init(struct ldpd_init *init)
144{
145 /* drop privileges */
146 if (init->user)
147 ldpe_privs.user = init->user;
148 if (init->group)
149 ldpe_privs.group = init->group;
150 zprivs_init(&ldpe_privs);
151
152 /* listen on ldpd control socket */
153 strlcpy(ctl_sock_path, init->ctl_sock_path, sizeof(ctl_sock_path));
154 if (control_init(ctl_sock_path) == -1)
155 fatalx("control socket setup failed");
156 TAILQ_INIT(&ctl_conns);
157 control_listen();
158
159#ifdef HAVE_PLEDGE
160 if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
161 fatal("pledge");
162#endif
163
164 LIST_INIT(&global.addr_list);
165 RB_INIT(&global.adj_tree);
166 TAILQ_INIT(&global.pending_conns);
167 if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
168 fatal("inet_pton");
169 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
170 fatal("inet_pton");
eac6e3f0 171#ifdef __OpenBSD__
274f5abf 172 global.pfkeysock = pfkey_init();
eac6e3f0
RW
173 if (sysdep.no_pfkey == 0)
174 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
175 NULL, global.pfkeysock);
176#endif
8429abe0
RW
177
178 /* mark sockets as closed */
179 global.ipv4.ldp_disc_socket = -1;
180 global.ipv4.ldp_edisc_socket = -1;
181 global.ipv4.ldp_session_socket = -1;
182 global.ipv6.ldp_disc_socket = -1;
183 global.ipv6.ldp_edisc_socket = -1;
184 global.ipv6.ldp_session_socket = -1;
185
8429abe0
RW
186 if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
187 fatal(__func__);
188
274f5abf 189 accept_init();
8429abe0
RW
190}
191
eac6e3f0 192static void
8429abe0
RW
193ldpe_shutdown(void)
194{
195 struct if_addr *if_addr;
196 struct adj *adj;
197
198 /* close pipes */
199 msgbuf_write(&iev_lde->ibuf.w);
200 msgbuf_clear(&iev_lde->ibuf.w);
201 close(iev_lde->ibuf.fd);
202 msgbuf_write(&iev_main->ibuf.w);
203 msgbuf_clear(&iev_main->ibuf.w);
204 close(iev_main->ibuf.fd);
28e8294c
RW
205 msgbuf_clear(&iev_main_sync->ibuf.w);
206 close(iev_main_sync->ibuf.fd);
8429abe0 207
274f5abf 208 control_cleanup(ctl_sock_path);
8429abe0
RW
209 config_clear(leconf);
210
eac6e3f0 211#ifdef __OpenBSD__
8429abe0 212 if (sysdep.no_pfkey == 0) {
eac6e3f0 213 THREAD_READ_OFF(pfkey_ev);
8429abe0
RW
214 close(global.pfkeysock);
215 }
eac6e3f0 216#endif
8429abe0
RW
217 ldpe_close_sockets(AF_INET);
218 ldpe_close_sockets(AF_INET6);
219
220 /* remove addresses from global list */
221 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
222 LIST_REMOVE(if_addr, entry);
223 free(if_addr);
224 }
057d48bd 225 while ((adj = RB_ROOT(&global.adj_tree)) != NULL)
8429abe0
RW
226 adj_del(adj, S_SHUTDOWN);
227
228 /* clean up */
229 free(iev_lde);
230 free(iev_main);
28e8294c 231 free(iev_main_sync);
8429abe0
RW
232 free(pkt_ptr);
233
234 log_info("ldp engine exiting");
235 exit(0);
236}
237
238/* imesg */
239int
240ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
241{
242 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
243}
244
245int
246ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
247 uint16_t datalen)
248{
249 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
250 data, datalen));
251}
252
253/* ARGSUSED */
eac6e3f0
RW
254static int
255ldpe_dispatch_main(struct thread *thread)
8429abe0
RW
256{
257 static struct ldpd_conf *nconf;
258 struct iface *niface;
259 struct tnbr *ntnbr;
260 struct nbr_params *nnbrp;
26519d8c 261 static struct l2vpn *l2vpn, *nl2vpn;
52b530fc
RW
262 struct l2vpn_if *lif, *nlif;
263 struct l2vpn_pw *pw, *npw;
8429abe0 264 struct imsg imsg;
eac6e3f0
RW
265 int fd = THREAD_FD(thread);
266 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
267 struct imsgbuf *ibuf = &iev->ibuf;
268 struct iface *iface = NULL;
269 struct kif *kif;
270 int af;
271 enum socket_type *socket_type;
272 static int disc_socket = -1;
273 static int edisc_socket = -1;
274 static int session_socket = -1;
275 struct nbr *nbr;
eac6e3f0 276#ifdef __OpenBSD__
8429abe0 277 struct nbr_params *nbrp;
eac6e3f0 278#endif
8429abe0
RW
279 int n, shut = 0;
280
eac6e3f0
RW
281 iev->ev_read = NULL;
282
283 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
284 fatal("imsg_read error");
285 if (n == 0) /* connection closed */
286 shut = 1;
8429abe0
RW
287
288 for (;;) {
289 if ((n = imsg_get(ibuf, &imsg)) == -1)
290 fatal("ldpe_dispatch_main: imsg_get error");
291 if (n == 0)
292 break;
293
294 switch (imsg.hdr.type) {
295 case IMSG_IFSTATUS:
296 if (imsg.hdr.len != IMSG_HEADER_SIZE +
297 sizeof(struct kif))
298 fatalx("IFSTATUS imsg with wrong len");
299 kif = imsg.data;
300
eac6e3f0 301 iface = if_lookup_name(leconf, kif->ifname);
26519d8c
RW
302 if (iface) {
303 if_update_info(iface, kif);
61cd1100 304 ldp_if_update(iface, AF_UNSPEC);
8429abe0 305 break;
26519d8c 306 }
8429abe0 307
26519d8c 308 RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) {
52bd4c23 309 lif = l2vpn_if_find(l2vpn, kif->ifname);
26519d8c 310 if (lif) {
52b530fc 311 l2vpn_if_update_info(lif, kif);
26519d8c
RW
312 l2vpn_if_update(lif);
313 break;
314 }
52b530fc
RW
315 pw = l2vpn_pw_find(l2vpn, kif->ifname);
316 if (pw) {
317 l2vpn_pw_update_info(pw, kif);
318 break;
319 }
26519d8c 320 }
8429abe0
RW
321 break;
322 case IMSG_NEWADDR:
323 if (imsg.hdr.len != IMSG_HEADER_SIZE +
324 sizeof(struct kaddr))
325 fatalx("NEWADDR imsg with wrong len");
326
327 if_addr_add(imsg.data);
328 break;
329 case IMSG_DELADDR:
330 if (imsg.hdr.len != IMSG_HEADER_SIZE +
331 sizeof(struct kaddr))
332 fatalx("DELADDR imsg with wrong len");
333
334 if_addr_del(imsg.data);
335 break;
336 case IMSG_SOCKET_IPC:
337 if (iev_lde) {
338 log_warnx("%s: received unexpected imsg fd "
339 "to lde", __func__);
340 break;
341 }
342 if ((fd = imsg.fd) == -1) {
343 log_warnx("%s: expected to receive imsg fd to "
344 "lde but didn't receive any", __func__);
345 break;
346 }
347
348 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
349 fatal(NULL);
350 imsg_init(&iev_lde->ibuf, fd);
eac6e3f0
RW
351 iev_lde->handler_read = ldpe_dispatch_lde;
352 iev_lde->ev_read = thread_add_read(master,
353 iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd);
354 iev_lde->handler_write = ldp_write_handler;
355 iev_lde->ev_write = NULL;
8429abe0 356 break;
274f5abf
RW
357 case IMSG_INIT:
358 if (imsg.hdr.len != IMSG_HEADER_SIZE +
359 sizeof(struct ldpd_init))
360 fatalx("INIT imsg with wrong len");
361
362 memcpy(&init, imsg.data, sizeof(init));
363 ldpe_init(&init);
364 break;
8429abe0
RW
365 case IMSG_CLOSE_SOCKETS:
366 af = imsg.hdr.peerid;
367
368 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
369 if (nbr->af != af)
370 continue;
371 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
eac6e3f0 372#ifdef __OpenBSD__
8429abe0 373 pfkey_remove(nbr);
eac6e3f0 374#endif
0f7b5df9 375 nbr->auth.method = AUTH_NONE;
8429abe0
RW
376 }
377 ldpe_close_sockets(af);
378 if_update_all(af);
379 tnbr_update_all(af);
380
381 disc_socket = -1;
382 edisc_socket = -1;
383 session_socket = -1;
384 if ((ldp_af_conf_get(leconf, af))->flags &
385 F_LDPD_AF_ENABLED)
386 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
387 af, NULL, 0);
388 break;
389 case IMSG_SOCKET_NET:
390 if (imsg.hdr.len != IMSG_HEADER_SIZE +
391 sizeof(enum socket_type))
392 fatalx("SOCKET_NET imsg with wrong len");
393 socket_type = imsg.data;
394
395 switch (*socket_type) {
396 case LDP_SOCKET_DISC:
397 disc_socket = imsg.fd;
398 break;
399 case LDP_SOCKET_EDISC:
400 edisc_socket = imsg.fd;
401 break;
402 case LDP_SOCKET_SESSION:
403 session_socket = imsg.fd;
404 break;
405 }
406 break;
407 case IMSG_SETUP_SOCKETS:
408 af = imsg.hdr.peerid;
409 if (disc_socket == -1 || edisc_socket == -1 ||
410 session_socket == -1) {
411 if (disc_socket != -1)
412 close(disc_socket);
413 if (edisc_socket != -1)
414 close(edisc_socket);
415 if (session_socket != -1)
416 close(session_socket);
417 break;
418 }
419
420 ldpe_setup_sockets(af, disc_socket, edisc_socket,
421 session_socket);
422 if_update_all(af);
423 tnbr_update_all(af);
424 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
425 if (nbr->af != af)
426 continue;
427 nbr->laddr = (ldp_af_conf_get(leconf,
428 af))->trans_addr;
eac6e3f0 429#ifdef __OpenBSD__
8429abe0 430 nbrp = nbr_params_find(leconf, nbr->id);
0f7b5df9
RW
431 if (nbrp) {
432 nbr->auth.method = nbrp->auth.method;
433 if (pfkey_establish(nbr, nbrp) == -1)
434 fatalx("pfkey setup failed");
435 }
eac6e3f0 436#endif
8429abe0
RW
437 if (nbr_session_active_role(nbr))
438 nbr_establish_connection(nbr);
439 }
440 break;
eac6e3f0
RW
441 case IMSG_RTRID_UPDATE:
442 memcpy(&global.rtr_id, imsg.data,
443 sizeof(global.rtr_id));
444 if (leconf->rtr_id.s_addr == INADDR_ANY) {
45a8eba9 445 ldpe_reset_nbrs(AF_UNSPEC);
eac6e3f0
RW
446 }
447 if_update_all(AF_UNSPEC);
448 tnbr_update_all(AF_UNSPEC);
449 break;
8429abe0
RW
450 case IMSG_RECONF_CONF:
451 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
452 NULL)
453 fatal(NULL);
454 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
455
7d3d7491 456 RB_INIT(&nconf->iface_tree);
7989cdba 457 RB_INIT(&nconf->tnbr_tree);
76c4abd1 458 RB_INIT(&nconf->nbrp_tree);
90d7e7bd 459 RB_INIT(&nconf->l2vpn_tree);
8429abe0
RW
460 break;
461 case IMSG_RECONF_IFACE:
462 if ((niface = malloc(sizeof(struct iface))) == NULL)
463 fatal(NULL);
464 memcpy(niface, imsg.data, sizeof(struct iface));
465
7d3d7491 466 RB_INSERT(iface_head, &nconf->iface_tree, niface);
8429abe0
RW
467 break;
468 case IMSG_RECONF_TNBR:
469 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
470 fatal(NULL);
471 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
472
7989cdba 473 RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
8429abe0
RW
474 break;
475 case IMSG_RECONF_NBRP:
476 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
477 fatal(NULL);
478 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
479
76c4abd1 480 RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
8429abe0
RW
481 break;
482 case IMSG_RECONF_L2VPN:
483 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
484 fatal(NULL);
485 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
486
029c1958 487 RB_INIT(&nl2vpn->if_tree);
20bacaeb
RW
488 RB_INIT(&nl2vpn->pw_tree);
489 RB_INIT(&nl2vpn->pw_inactive_tree);
8429abe0 490
90d7e7bd 491 RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
8429abe0
RW
492 break;
493 case IMSG_RECONF_L2VPN_IF:
494 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
495 fatal(NULL);
496 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
497
029c1958 498 RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
8429abe0
RW
499 break;
500 case IMSG_RECONF_L2VPN_PW:
501 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
502 fatal(NULL);
503 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
504
20bacaeb 505 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
8429abe0 506 break;
eac6e3f0
RW
507 case IMSG_RECONF_L2VPN_IPW:
508 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
509 fatal(NULL);
510 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
511
20bacaeb 512 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
eac6e3f0 513 break;
8429abe0
RW
514 case IMSG_RECONF_END:
515 merge_config(leconf, nconf);
1d75a89d 516 ldp_clear_config(nconf);
8429abe0
RW
517 nconf = NULL;
518 global.conf_seqnum++;
519 break;
8429abe0
RW
520 case IMSG_CTL_END:
521 control_imsg_relay(&imsg);
522 break;
eac6e3f0
RW
523 case IMSG_DEBUG_UPDATE:
524 if (imsg.hdr.len != IMSG_HEADER_SIZE +
525 sizeof(ldp_debug)) {
526 log_warnx("%s: wrong imsg len", __func__);
527 break;
528 }
529 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
530 break;
8429abe0
RW
531 default:
532 log_debug("ldpe_dispatch_main: error handling imsg %d",
533 imsg.hdr.type);
534 break;
535 }
536 imsg_free(&imsg);
537 }
538 if (!shut)
539 imsg_event_add(iev);
540 else {
eac6e3f0
RW
541 /* this pipe is dead, so remove the event handlers and exit */
542 THREAD_READ_OFF(iev->ev_read);
543 THREAD_WRITE_OFF(iev->ev_write);
544 ldpe_shutdown();
8429abe0 545 }
eac6e3f0
RW
546
547 return (0);
8429abe0
RW
548}
549
550/* ARGSUSED */
eac6e3f0
RW
551static int
552ldpe_dispatch_lde(struct thread *thread)
8429abe0 553{
eac6e3f0 554 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
555 struct imsgbuf *ibuf = &iev->ibuf;
556 struct imsg imsg;
236c6935
RW
557 struct map *map;
558 struct notify_msg *nm;
559 struct nbr *nbr;
8429abe0 560 int n, shut = 0;
8429abe0 561
eac6e3f0
RW
562 iev->ev_read = NULL;
563
564 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
565 fatal("imsg_read error");
566 if (n == 0) /* connection closed */
567 shut = 1;
8429abe0
RW
568
569 for (;;) {
570 if ((n = imsg_get(ibuf, &imsg)) == -1)
571 fatal("ldpe_dispatch_lde: imsg_get error");
572 if (n == 0)
573 break;
574
575 switch (imsg.hdr.type) {
576 case IMSG_MAPPING_ADD:
577 case IMSG_RELEASE_ADD:
578 case IMSG_REQUEST_ADD:
579 case IMSG_WITHDRAW_ADD:
236c6935
RW
580 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
581 sizeof(struct map))
8429abe0 582 fatalx("invalid size of map request");
236c6935 583 map = imsg.data;
8429abe0
RW
584
585 nbr = nbr_find_peerid(imsg.hdr.peerid);
586 if (nbr == NULL) {
587 log_debug("ldpe_dispatch_lde: cannot find "
588 "neighbor");
589 break;
590 }
591 if (nbr->state != NBR_STA_OPER)
592 break;
593
594 switch (imsg.hdr.type) {
595 case IMSG_MAPPING_ADD:
236c6935 596 mapping_list_add(&nbr->mapping_list, map);
8429abe0
RW
597 break;
598 case IMSG_RELEASE_ADD:
236c6935 599 mapping_list_add(&nbr->release_list, map);
8429abe0
RW
600 break;
601 case IMSG_REQUEST_ADD:
236c6935 602 mapping_list_add(&nbr->request_list, map);
8429abe0
RW
603 break;
604 case IMSG_WITHDRAW_ADD:
236c6935 605 mapping_list_add(&nbr->withdraw_list, map);
8429abe0
RW
606 break;
607 }
608 break;
609 case IMSG_MAPPING_ADD_END:
610 case IMSG_RELEASE_ADD_END:
611 case IMSG_REQUEST_ADD_END:
612 case IMSG_WITHDRAW_ADD_END:
613 nbr = nbr_find_peerid(imsg.hdr.peerid);
614 if (nbr == NULL) {
615 log_debug("ldpe_dispatch_lde: cannot find "
616 "neighbor");
617 break;
618 }
619 if (nbr->state != NBR_STA_OPER)
620 break;
621
622 switch (imsg.hdr.type) {
623 case IMSG_MAPPING_ADD_END:
624 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
625 &nbr->mapping_list);
626 break;
627 case IMSG_RELEASE_ADD_END:
628 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
629 &nbr->release_list);
630 break;
631 case IMSG_REQUEST_ADD_END:
632 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
633 &nbr->request_list);
634 break;
635 case IMSG_WITHDRAW_ADD_END:
636 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
637 &nbr->withdraw_list);
638 break;
639 }
640 break;
641 case IMSG_NOTIFICATION_SEND:
236c6935
RW
642 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
643 sizeof(struct notify_msg))
8429abe0 644 fatalx("invalid size of OE request");
236c6935 645 nm = imsg.data;
8429abe0
RW
646
647 nbr = nbr_find_peerid(imsg.hdr.peerid);
648 if (nbr == NULL) {
649 log_debug("ldpe_dispatch_lde: cannot find "
650 "neighbor");
651 break;
652 }
653 if (nbr->state != NBR_STA_OPER)
654 break;
655
236c6935 656 send_notification_full(nbr->tcp, nm);
8429abe0
RW
657 break;
658 case IMSG_CTL_END:
0f7b5df9
RW
659 case IMSG_CTL_SHOW_LIB_BEGIN:
660 case IMSG_CTL_SHOW_LIB_RCVD:
661 case IMSG_CTL_SHOW_LIB_SENT:
662 case IMSG_CTL_SHOW_LIB_END:
8429abe0
RW
663 case IMSG_CTL_SHOW_L2VPN_PW:
664 case IMSG_CTL_SHOW_L2VPN_BINDING:
665 control_imsg_relay(&imsg);
666 break;
667 default:
668 log_debug("ldpe_dispatch_lde: error handling imsg %d",
669 imsg.hdr.type);
670 break;
671 }
672 imsg_free(&imsg);
673 }
674 if (!shut)
675 imsg_event_add(iev);
676 else {
eac6e3f0
RW
677 /* this pipe is dead, so remove the event handlers and exit */
678 THREAD_READ_OFF(iev->ev_read);
679 THREAD_WRITE_OFF(iev->ev_write);
680 ldpe_shutdown();
8429abe0 681 }
eac6e3f0
RW
682
683 return (0);
8429abe0
RW
684}
685
eac6e3f0 686#ifdef __OpenBSD__
8429abe0 687/* ARGSUSED */
eac6e3f0
RW
688static int
689ldpe_dispatch_pfkey(struct thread *thread)
8429abe0 690{
eac6e3f0
RW
691 int fd = THREAD_FD(thread);
692
693 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
694 NULL, global.pfkeysock);
695
696 if (pfkey_read(fd, NULL) == -1)
697 fatal("pfkey_read failed, exiting...");
698
699 return (0);
8429abe0 700}
eac6e3f0 701#endif /* __OpenBSD__ */
8429abe0
RW
702
703static void
704ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
705 int session_socket)
706{
707 struct ldpd_af_global *af_global;
708
709 af_global = ldp_af_global_get(&global, af);
710
711 /* discovery socket */
712 af_global->ldp_disc_socket = disc_socket;
eac6e3f0
RW
713 af_global->disc_ev = thread_add_read(master, disc_recv_packet,
714 &af_global->disc_ev, af_global->ldp_disc_socket);
8429abe0
RW
715
716 /* extended discovery socket */
717 af_global->ldp_edisc_socket = edisc_socket;
eac6e3f0
RW
718 af_global->edisc_ev = thread_add_read(master, disc_recv_packet,
719 &af_global->edisc_ev, af_global->ldp_edisc_socket);
8429abe0
RW
720
721 /* session socket */
722 af_global->ldp_session_socket = session_socket;
723 accept_add(af_global->ldp_session_socket, session_accept, NULL);
724}
725
726static void
727ldpe_close_sockets(int af)
728{
729 struct ldpd_af_global *af_global;
730
731 af_global = ldp_af_global_get(&global, af);
732
733 /* discovery socket */
eac6e3f0 734 THREAD_READ_OFF(af_global->disc_ev);
8429abe0
RW
735 if (af_global->ldp_disc_socket != -1) {
736 close(af_global->ldp_disc_socket);
737 af_global->ldp_disc_socket = -1;
738 }
739
740 /* extended discovery socket */
eac6e3f0 741 THREAD_READ_OFF(af_global->edisc_ev);
8429abe0
RW
742 if (af_global->ldp_edisc_socket != -1) {
743 close(af_global->ldp_edisc_socket);
744 af_global->ldp_edisc_socket = -1;
745 }
746
747 /* session socket */
748 if (af_global->ldp_session_socket != -1) {
749 accept_del(af_global->ldp_session_socket);
750 close(af_global->ldp_session_socket);
751 af_global->ldp_session_socket = -1;
752 }
753}
754
45a8eba9
RW
755int
756ldpe_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen)
757{
758 return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen);
759}
760
8429abe0
RW
761void
762ldpe_reset_nbrs(int af)
763{
764 struct nbr *nbr;
765
766 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
45a8eba9 767 if (af == AF_UNSPEC || nbr->af == af)
8429abe0
RW
768 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
769 }
770}
771
772void
773ldpe_reset_ds_nbrs(void)
774{
775 struct nbr *nbr;
776
777 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
778 if (nbr->ds_tlv)
779 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
780 }
781}
782
783void
784ldpe_remove_dynamic_tnbrs(int af)
785{
786 struct tnbr *tnbr, *safe;
787
7989cdba 788 RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) {
8429abe0
RW
789 if (tnbr->af != af)
790 continue;
791
792 tnbr->flags &= ~F_TNBR_DYNAMIC;
7989cdba 793 tnbr_check(leconf, tnbr);
8429abe0
RW
794 }
795}
796
797void
798ldpe_stop_init_backoff(int af)
799{
800 struct nbr *nbr;
801
802 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
803 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
804 nbr_stop_idtimer(nbr);
805 nbr_establish_connection(nbr);
806 }
807 }
808}
809
810static void
811ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
812{
813 struct iface *iface;
814 struct iface_af *ia;
815 struct ctl_iface *ictl;
816
7d3d7491 817 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
8429abe0
RW
818 if (idx == 0 || idx == iface->ifindex) {
819 ia = iface_af_get(iface, af);
820 if (!ia->enabled)
821 continue;
822
823 ictl = if_to_ctl(ia);
05aac414 824 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
8429abe0
RW
825 0, 0, -1, ictl, sizeof(struct ctl_iface));
826 }
827 }
828}
829
830void
831ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
832{
833 ldpe_iface_af_ctl(c, AF_INET, idx);
834 ldpe_iface_af_ctl(c, AF_INET6, idx);
835}
836
837void
838ldpe_adj_ctl(struct ctl_conn *c)
bc0eb287
RW
839{
840 struct adj *adj;
841 struct ctl_adj *actl;
842
843 RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
844 actl = adj_to_ctl(adj);
845 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
846 -1, actl, sizeof(struct ctl_adj));
847 }
848
849 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
850}
851
852void
853ldpe_adj_detail_ctl(struct ctl_conn *c)
8429abe0 854{
eac6e3f0
RW
855 struct iface *iface;
856 struct tnbr *tnbr;
857 struct adj *adj;
858 struct ctl_adj *actl;
859 struct ctl_disc_if ictl;
860 struct ctl_disc_tnbr tctl;
8429abe0 861
eac6e3f0
RW
862 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
863
7d3d7491 864 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
eac6e3f0
RW
865 memset(&ictl, 0, sizeof(ictl));
866 ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
867 ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);
868
869 if (!ictl.active_v4 && !ictl.active_v6)
870 continue;
871
872 strlcpy(ictl.name, iface->name, sizeof(ictl.name));
057d48bd
RW
873 if (RB_EMPTY(&iface->ipv4.adj_tree) &&
874 RB_EMPTY(&iface->ipv6.adj_tree))
eac6e3f0
RW
875 ictl.no_adj = 1;
876 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
877 -1, &ictl, sizeof(ictl));
878
057d48bd 879 RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
8429abe0 880 actl = adj_to_ctl(adj);
eac6e3f0
RW
881 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
882 0, 0, -1, actl, sizeof(struct ctl_adj));
883 }
057d48bd 884 RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
eac6e3f0
RW
885 actl = adj_to_ctl(adj);
886 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
8429abe0
RW
887 0, 0, -1, actl, sizeof(struct ctl_adj));
888 }
889 }
eac6e3f0 890
7989cdba 891 RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) {
eac6e3f0
RW
892 memset(&tctl, 0, sizeof(tctl));
893 tctl.af = tnbr->af;
894 tctl.addr = tnbr->addr;
895 if (tnbr->adj == NULL)
896 tctl.no_adj = 1;
897
898 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0,
899 -1, &tctl, sizeof(tctl));
900
901 if (tnbr->adj == NULL)
8429abe0
RW
902 continue;
903
eac6e3f0
RW
904 actl = adj_to_ctl(tnbr->adj);
905 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0,
8429abe0
RW
906 -1, actl, sizeof(struct ctl_adj));
907 }
908
909 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
910}
911
912void
913ldpe_nbr_ctl(struct ctl_conn *c)
914{
eac6e3f0
RW
915 struct adj *adj;
916 struct ctl_adj *actl;
8429abe0
RW
917 struct nbr *nbr;
918 struct ctl_nbr *nctl;
919
920 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
eac6e3f0
RW
921 if (nbr->state == NBR_STA_PRESENT)
922 continue;
923
8429abe0
RW
924 nctl = nbr_to_ctl(nbr);
925 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
926 sizeof(struct ctl_nbr));
eac6e3f0 927
057d48bd 928 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
eac6e3f0
RW
929 actl = adj_to_ctl(adj);
930 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
931 0, 0, -1, actl, sizeof(struct ctl_adj));
932 }
933
934 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1,
935 NULL, 0);
8429abe0
RW
936 }
937 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
938}
939
940void
941mapping_list_add(struct mapping_head *mh, struct map *map)
942{
943 struct mapping_entry *me;
944
945 me = calloc(1, sizeof(*me));
946 if (me == NULL)
947 fatal(__func__);
948 me->map = *map;
949
950 TAILQ_INSERT_TAIL(mh, me, entry);
951}
952
953void
954mapping_list_clr(struct mapping_head *mh)
955{
956 struct mapping_entry *me;
957
958 while ((me = TAILQ_FIRST(mh)) != NULL) {
959 TAILQ_REMOVE(mh, me, entry);
960 free(me);
961 }
962}