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