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