]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/ldpe.c
bgpd: Show the real table version for a decent peer subgroup
[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 event *thread);
29 static void ldpe_dispatch_lde(struct event *thread);
30 #ifdef __OpenBSD__
31 static void ldpe_dispatch_pfkey(struct event *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 event *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 event_add_read(master, iev_main->handler_read, iev_main,
115 iev_main->ibuf.fd, &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 event thread;
126 while (event_fetch(master, &thread))
127 event_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 event_add_read(master, ldpe_dispatch_pfkey, NULL,
141 global.pfkeysock, &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 EVENT_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, data, datalen));
261 }
262
263 /* ARGSUSED */
264 static void ldpe_dispatch_main(struct event *thread)
265 {
266 static struct ldpd_conf *nconf;
267 struct iface *niface;
268 struct tnbr *ntnbr;
269 struct nbr_params *nnbrp;
270 static struct l2vpn *l2vpn, *nl2vpn;
271 struct l2vpn_if *lif, *nlif;
272 struct l2vpn_pw *pw, *npw;
273 struct imsg imsg;
274 int fd;
275 struct imsgev *iev = EVENT_ARG(thread);
276 struct imsgbuf *ibuf = &iev->ibuf;
277 struct iface *iface = NULL;
278 struct kif *kif;
279 int af;
280 enum socket_type *socket_type;
281 static int disc_socket = -1;
282 static int edisc_socket = -1;
283 static int session_socket = -1;
284 struct nbr *nbr;
285 #ifdef __OpenBSD__
286 struct nbr_params *nbrp;
287 #endif
288 int n, shut = 0;
289 struct ldp_access *laccess;
290 struct ldp_igp_sync_if_state_req *ldp_sync_if_state_req;
291 struct ldp_rlfa_node *rnode, *rntmp;
292 struct ldp_rlfa_client *rclient;
293 struct zapi_rlfa_request *rlfa_req;
294 struct zapi_rlfa_igp *rlfa_igp;
295
296 iev->ev_read = NULL;
297
298 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
299 fatal("imsg_read error");
300 if (n == 0) /* connection closed */
301 shut = 1;
302
303 for (;;) {
304 if ((n = imsg_get(ibuf, &imsg)) == -1)
305 fatal("ldpe_dispatch_main: imsg_get error");
306 if (n == 0)
307 break;
308
309 switch (imsg.hdr.type) {
310 case IMSG_IFSTATUS:
311 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kif))
312 fatalx("IFSTATUS imsg with wrong len");
313 kif = imsg.data;
314
315 iface = if_lookup_name(leconf, kif->ifname);
316 if (iface) {
317 if_update_info(iface, kif);
318 ldp_if_update(iface, AF_UNSPEC);
319 break;
320 }
321
322 RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) {
323 lif = l2vpn_if_find(l2vpn, kif->ifname);
324 if (lif) {
325 l2vpn_if_update_info(lif, kif);
326 l2vpn_if_update(lif);
327 break;
328 }
329 pw = l2vpn_pw_find(l2vpn, kif->ifname);
330 if (pw) {
331 l2vpn_pw_update_info(pw, kif);
332 break;
333 }
334 }
335 break;
336 case IMSG_NEWADDR:
337 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr))
338 fatalx("NEWADDR imsg with wrong len");
339
340 if_addr_add(imsg.data);
341 break;
342 case IMSG_DELADDR:
343 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr))
344 fatalx("DELADDR imsg with wrong len");
345
346 if_addr_del(imsg.data);
347 break;
348 case IMSG_SOCKET_IPC:
349 if (iev_lde) {
350 log_warnx("%s: received unexpected imsg fd to lde", __func__);
351 break;
352 }
353 if ((fd = imsg.fd) == -1) {
354 log_warnx("%s: expected to receive imsg fd to lde but didn't receive any", __func__);
355 break;
356 }
357
358 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
359 fatal(NULL);
360 imsg_init(&iev_lde->ibuf, fd);
361 iev_lde->handler_read = ldpe_dispatch_lde;
362 event_add_read(master, iev_lde->handler_read, iev_lde,
363 iev_lde->ibuf.fd, &iev_lde->ev_read);
364 iev_lde->handler_write = ldp_write_handler;
365 iev_lde->ev_write = NULL;
366 break;
367 case IMSG_INIT:
368 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldpd_init))
369 fatalx("INIT imsg with wrong len");
370
371 memcpy(&init, imsg.data, sizeof(init));
372 ldpe_init(&init);
373 break;
374 case IMSG_AGENTX_ENABLED:
375 ldp_agentx_enabled();
376 break;
377 case IMSG_CLOSE_SOCKETS:
378 af = imsg.hdr.peerid;
379
380 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
381 if (nbr->af != af)
382 continue;
383 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
384 #ifdef __OpenBSD__
385 pfkey_remove(nbr);
386 #endif
387 nbr->auth.method = AUTH_NONE;
388 }
389 ldpe_close_sockets(af);
390 if_update_all(af);
391 tnbr_update_all(af);
392
393 disc_socket = -1;
394 edisc_socket = -1;
395 session_socket = -1;
396 if (CHECK_FLAG((ldp_af_conf_get(leconf, af))->flags, F_LDPD_AF_ENABLED))
397 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, af, NULL, 0);
398 break;
399 case IMSG_SOCKET_NET:
400 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(enum socket_type))
401 fatalx("SOCKET_NET imsg with wrong len");
402 socket_type = imsg.data;
403
404 switch (*socket_type) {
405 case LDP_SOCKET_DISC:
406 disc_socket = imsg.fd;
407 break;
408 case LDP_SOCKET_EDISC:
409 edisc_socket = imsg.fd;
410 break;
411 case LDP_SOCKET_SESSION:
412 session_socket = imsg.fd;
413 break;
414 }
415 break;
416 case IMSG_SETUP_SOCKETS:
417 af = imsg.hdr.peerid;
418 if (disc_socket == -1 || edisc_socket == -1 ||
419 session_socket == -1) {
420 if (disc_socket != -1)
421 close(disc_socket);
422 if (edisc_socket != -1)
423 close(edisc_socket);
424 if (session_socket != -1)
425 close(session_socket);
426 break;
427 }
428
429 ldpe_setup_sockets(af, disc_socket, edisc_socket, session_socket);
430 if_update_all(af);
431 tnbr_update_all(af);
432 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
433 if (nbr->af != af)
434 continue;
435 nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr;
436 #ifdef __OpenBSD__
437 nbrp = nbr_params_find(leconf, nbr->id);
438 if (nbrp) {
439 nbr->auth.method = nbrp->auth.method;
440 if (pfkey_establish(nbr, nbrp) == -1)
441 fatalx("pfkey setup failed");
442 }
443 #endif
444 if (nbr_session_active_role(nbr))
445 nbr_establish_connection(nbr);
446 }
447 break;
448 case IMSG_RTRID_UPDATE:
449 memcpy(&global.rtr_id, imsg.data, sizeof(global.rtr_id));
450 if (leconf->rtr_id.s_addr == INADDR_ANY) {
451 ldpe_reset_nbrs(AF_UNSPEC);
452 }
453 if_update_all(AF_UNSPEC);
454 tnbr_update_all(AF_UNSPEC);
455 break;
456 case IMSG_RECONF_CONF:
457 if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL)
458 fatal(NULL);
459 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
460
461 RB_INIT(iface_head, &nconf->iface_tree);
462 RB_INIT(tnbr_head, &nconf->tnbr_tree);
463 RB_INIT(nbrp_head, &nconf->nbrp_tree);
464 RB_INIT(l2vpn_head, &nconf->l2vpn_tree);
465 break;
466 case IMSG_RECONF_IFACE:
467 if ((niface = malloc(sizeof(struct iface))) == NULL)
468 fatal(NULL);
469 memcpy(niface, imsg.data, sizeof(struct iface));
470
471 RB_INSERT(iface_head, &nconf->iface_tree, niface);
472 break;
473 case IMSG_RECONF_TNBR:
474 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
475 fatal(NULL);
476 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
477
478 RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
479 break;
480 case IMSG_RECONF_NBRP:
481 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
482 fatal(NULL);
483 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
484
485 RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
486 break;
487 case IMSG_RECONF_L2VPN:
488 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
489 fatal(NULL);
490 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
491
492 RB_INIT(l2vpn_if_head, &nl2vpn->if_tree);
493 RB_INIT(l2vpn_pw_head, &nl2vpn->pw_tree);
494 RB_INIT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree);
495
496 RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
497 break;
498 case IMSG_RECONF_L2VPN_IF:
499 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
500 fatal(NULL);
501 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
502
503 RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
504 break;
505 case IMSG_RECONF_L2VPN_PW:
506 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
507 fatal(NULL);
508 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
509
510 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
511 break;
512 case IMSG_RECONF_L2VPN_IPW:
513 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
514 fatal(NULL);
515 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
516
517 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
518 break;
519 case IMSG_RECONF_END:
520 merge_config(leconf, nconf);
521 ldp_clear_config(nconf);
522 nconf = NULL;
523 global.conf_seqnum++;
524 break;
525 case IMSG_CTL_END:
526 control_imsg_relay(&imsg);
527 break;
528 case IMSG_DEBUG_UPDATE:
529 if (imsg.hdr.len != IMSG_HEADER_SIZE +
530 sizeof(ldp_debug)) {
531 log_warnx("%s: wrong imsg len", __func__);
532 break;
533 }
534 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
535 break;
536 case IMSG_FILTER_UPDATE:
537 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldp_access)) {
538 log_warnx("%s: wrong imsg len", __func__);
539 break;
540 }
541 laccess = imsg.data;
542 ldpe_check_filter_af(AF_INET, &leconf->ipv4, laccess->name);
543 ldpe_check_filter_af(AF_INET6, &leconf->ipv6, laccess->name);
544 break;
545 case IMSG_LDP_SYNC_IF_STATE_REQUEST:
546 if (imsg.hdr.len != IMSG_HEADER_SIZE +
547 sizeof(struct ldp_igp_sync_if_state_req)) {
548 log_warnx("%s: wrong imsg len", __func__);
549 break;
550 }
551 ldp_sync_if_state_req = imsg.data;
552 ldp_sync_fsm_state_req(ldp_sync_if_state_req);
553 break;
554 case IMSG_RLFA_REG:
555 if (imsg.hdr.len != IMSG_HEADER_SIZE +
556 sizeof(struct zapi_rlfa_request)) {
557 log_warnx("%s: wrong imsg len", __func__);
558 break;
559 }
560 rlfa_req = imsg.data;
561
562 rnode = rlfa_node_find(&rlfa_req->destination,
563 rlfa_req->pq_address);
564 if (!rnode)
565 rnode = rlfa_node_new(&rlfa_req->destination,
566 rlfa_req->pq_address);
567 rclient = rlfa_client_find(rnode, &rlfa_req->igp);
568 if (rclient)
569 /* RLFA already registered - do nothing */
570 break;
571 rclient = rlfa_client_new(rnode, &rlfa_req->igp);
572 ldpe_rlfa_init(rclient);
573 break;
574 case IMSG_RLFA_UNREG_ALL:
575 if (imsg.hdr.len != IMSG_HEADER_SIZE +
576 sizeof(struct zapi_rlfa_igp)) {
577 log_warnx("%s: wrong imsg len", __func__);
578 break;
579 }
580 rlfa_igp = imsg.data;
581
582 RB_FOREACH_SAFE (rnode, ldp_rlfa_node_head,
583 &rlfa_node_tree, rntmp) {
584 rclient = rlfa_client_find(rnode, rlfa_igp);
585 if (!rclient)
586 continue;
587
588 ldpe_rlfa_exit(rclient);
589 rlfa_client_del(rclient);
590 }
591 break;
592 default:
593 log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type);
594 break;
595 }
596 imsg_free(&imsg);
597 }
598 if (!shut)
599 imsg_event_add(iev);
600 else {
601 /* this pipe is dead, so remove the event handlers and exit */
602 EVENT_OFF(iev->ev_read);
603 EVENT_OFF(iev->ev_write);
604 ldpe_shutdown();
605 }
606 }
607
608 /* ARGSUSED */
609 static void ldpe_dispatch_lde(struct event *thread)
610 {
611 struct imsgev *iev = EVENT_ARG(thread);
612 struct imsgbuf *ibuf = &iev->ibuf;
613 struct imsg imsg;
614 struct map *map;
615 struct notify_msg *nm;
616 struct nbr *nbr;
617 int n, shut = 0;
618
619 iev->ev_read = NULL;
620
621 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
622 fatal("imsg_read error");
623 if (n == 0) /* connection closed */
624 shut = 1;
625
626 for (;;) {
627 if ((n = imsg_get(ibuf, &imsg)) == -1)
628 fatal("ldpe_dispatch_lde: imsg_get error");
629 if (n == 0)
630 break;
631
632 switch (imsg.hdr.type) {
633 case IMSG_MAPPING_ADD:
634 case IMSG_RELEASE_ADD:
635 case IMSG_REQUEST_ADD:
636 case IMSG_WITHDRAW_ADD:
637 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct map))
638 fatalx("invalid size of map request");
639 map = imsg.data;
640
641 nbr = nbr_find_peerid(imsg.hdr.peerid);
642 if (nbr == NULL)
643 break;
644 if (nbr->state != NBR_STA_OPER)
645 break;
646
647 switch (imsg.hdr.type) {
648 case IMSG_MAPPING_ADD:
649 mapping_list_add(&nbr->mapping_list, map);
650 break;
651 case IMSG_RELEASE_ADD:
652 mapping_list_add(&nbr->release_list, map);
653 break;
654 case IMSG_REQUEST_ADD:
655 mapping_list_add(&nbr->request_list, map);
656 break;
657 case IMSG_WITHDRAW_ADD:
658 mapping_list_add(&nbr->withdraw_list, map);
659 break;
660 }
661 break;
662 case IMSG_MAPPING_ADD_END:
663 case IMSG_RELEASE_ADD_END:
664 case IMSG_REQUEST_ADD_END:
665 case IMSG_WITHDRAW_ADD_END:
666 nbr = nbr_find_peerid(imsg.hdr.peerid);
667 if (nbr == NULL)
668 break;
669 if (nbr->state != NBR_STA_OPER)
670 break;
671
672 switch (imsg.hdr.type) {
673 case IMSG_MAPPING_ADD_END:
674 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
675 &nbr->mapping_list);
676 break;
677 case IMSG_RELEASE_ADD_END:
678 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
679 &nbr->release_list);
680 break;
681 case IMSG_REQUEST_ADD_END:
682 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
683 &nbr->request_list);
684 break;
685 case IMSG_WITHDRAW_ADD_END:
686 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
687 &nbr->withdraw_list);
688 break;
689 }
690 break;
691 case IMSG_NOTIFICATION_SEND:
692 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct notify_msg))
693 fatalx("invalid size of OE request");
694 nm = imsg.data;
695
696 nbr = nbr_find_peerid(imsg.hdr.peerid);
697 if (nbr == NULL) {
698 log_debug("%s: cannot find neighbor", __func__);
699 break;
700 }
701 if (nbr->state != NBR_STA_OPER)
702 break;
703
704 send_notification_full(nbr->tcp, nm);
705 break;
706 case IMSG_CTL_END:
707 case IMSG_CTL_SHOW_LIB_BEGIN:
708 case IMSG_CTL_SHOW_LIB_RCVD:
709 case IMSG_CTL_SHOW_LIB_SENT:
710 case IMSG_CTL_SHOW_LIB_END:
711 case IMSG_CTL_SHOW_L2VPN_PW:
712 case IMSG_CTL_SHOW_L2VPN_BINDING:
713 control_imsg_relay(&imsg);
714 break;
715 case IMSG_NBR_SHUTDOWN:
716 nbr = nbr_find_peerid(imsg.hdr.peerid);
717 if (nbr == NULL) {
718 log_debug("%s: cannot find neighbor", __func__);
719 break;
720 }
721 if (nbr->state != NBR_STA_OPER)
722 break;
723 session_shutdown(nbr,S_SHUTDOWN,0,0);
724 break;
725 default:
726 log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type);
727 break;
728 }
729 imsg_free(&imsg);
730 }
731 if (!shut)
732 imsg_event_add(iev);
733 else {
734 /* this pipe is dead, so remove the event handlers and exit */
735 EVENT_OFF(iev->ev_read);
736 EVENT_OFF(iev->ev_write);
737 ldpe_shutdown();
738 }
739 }
740
741 #ifdef __OpenBSD__
742 /* ARGSUSED */
743 static void ldpe_dispatch_pfkey(struct event *thread)
744 {
745 int fd = EVENT_FD(thread);
746
747 event_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock,
748 &pfkey_ev);
749
750 if (pfkey_read(fd, NULL) == -1)
751 fatal("pfkey_read failed, exiting...");
752 }
753 #endif /* __OpenBSD__ */
754
755 static void
756 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
757 int session_socket)
758 {
759 struct ldpd_af_global *af_global;
760
761 af_global = ldp_af_global_get(&global, af);
762
763 /* discovery socket */
764 af_global->ldp_disc_socket = disc_socket;
765 event_add_read(master, disc_recv_packet, &af_global->disc_ev,
766 af_global->ldp_disc_socket, &af_global->disc_ev);
767
768 /* extended discovery socket */
769 af_global->ldp_edisc_socket = edisc_socket;
770 event_add_read(master, disc_recv_packet, &af_global->edisc_ev,
771 af_global->ldp_edisc_socket, &af_global->edisc_ev);
772
773 /* session socket */
774 af_global->ldp_session_socket = session_socket;
775 accept_add(af_global->ldp_session_socket, session_accept, NULL);
776 }
777
778 static void
779 ldpe_close_sockets(int af)
780 {
781 struct ldpd_af_global *af_global;
782
783 af_global = ldp_af_global_get(&global, af);
784
785 /* discovery socket */
786 EVENT_OFF(af_global->disc_ev);
787 if (af_global->ldp_disc_socket != -1) {
788 close(af_global->ldp_disc_socket);
789 af_global->ldp_disc_socket = -1;
790 }
791
792 /* extended discovery socket */
793 EVENT_OFF(af_global->edisc_ev);
794 if (af_global->ldp_edisc_socket != -1) {
795 close(af_global->ldp_edisc_socket);
796 af_global->ldp_edisc_socket = -1;
797 }
798
799 /* session socket */
800 if (af_global->ldp_session_socket != -1) {
801 accept_del(af_global->ldp_session_socket);
802 close(af_global->ldp_session_socket);
803 af_global->ldp_session_socket = -1;
804 }
805 }
806
807 int
808 ldpe_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen)
809 {
810 return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen);
811 }
812
813 void
814 ldpe_reset_nbrs(int af)
815 {
816 struct nbr *nbr;
817
818 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
819 if (af == AF_UNSPEC || nbr->af == af)
820 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
821 }
822 }
823
824 void
825 ldpe_reset_ds_nbrs(void)
826 {
827 struct nbr *nbr;
828
829 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
830 if (nbr->ds_tlv)
831 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
832 }
833 }
834
835 void
836 ldpe_remove_dynamic_tnbrs(int af)
837 {
838 struct tnbr *tnbr, *safe;
839
840 RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) {
841 if (tnbr->af != af)
842 continue;
843
844 UNSET_FLAG(tnbr->flags, F_TNBR_DYNAMIC);
845 tnbr_check(leconf, tnbr);
846 }
847 }
848
849 void
850 ldpe_stop_init_backoff(int af)
851 {
852 struct nbr *nbr;
853
854 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
855 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
856 nbr_stop_idtimer(nbr);
857 nbr_establish_connection(nbr);
858 }
859 }
860 }
861
862 static void
863 ldpe_iface_af_ctl(struct ctl_conn *c, int af, ifindex_t idx)
864 {
865 struct iface *iface;
866 struct iface_af *ia;
867 struct ctl_iface *ictl;
868
869 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
870 if (idx == 0 || idx == iface->ifindex) {
871 ia = iface_af_get(iface, af);
872 if (!ia->enabled)
873 continue;
874
875 ictl = if_to_ctl(ia);
876 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
877 0, 0, -1, ictl, sizeof(struct ctl_iface));
878 }
879 }
880 }
881
882 void
883 ldpe_iface_ctl(struct ctl_conn *c, ifindex_t idx)
884 {
885 ldpe_iface_af_ctl(c, AF_INET, idx);
886 ldpe_iface_af_ctl(c, AF_INET6, idx);
887 }
888
889 void
890 ldpe_adj_ctl(struct ctl_conn *c)
891 {
892 struct adj *adj;
893 struct ctl_adj *actl;
894
895 RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
896 actl = adj_to_ctl(adj);
897 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
898 -1, actl, sizeof(struct ctl_adj));
899 }
900
901 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
902 }
903
904 void
905 ldpe_adj_detail_ctl(struct ctl_conn *c)
906 {
907 struct iface *iface;
908 struct tnbr *tnbr;
909 struct adj *adj;
910 struct ctl_adj *actl;
911 struct ctl_disc_if ictl;
912 struct ctl_disc_tnbr tctl;
913
914 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
915
916 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
917 memset(&ictl, 0, sizeof(ictl));
918 ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
919 ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);
920
921 if (!ictl.active_v4 && !ictl.active_v6)
922 continue;
923
924 strlcpy(ictl.name, iface->name, sizeof(ictl.name));
925 if (RB_EMPTY(ia_adj_head, &iface->ipv4.adj_tree) &&
926 RB_EMPTY(ia_adj_head, &iface->ipv6.adj_tree))
927 ictl.no_adj = 1;
928 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
929 -1, &ictl, sizeof(ictl));
930
931 RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
932 actl = adj_to_ctl(adj);
933 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
934 0, 0, -1, actl, sizeof(struct ctl_adj));
935 }
936 RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
937 actl = adj_to_ctl(adj);
938 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
939 0, 0, -1, actl, sizeof(struct ctl_adj));
940 }
941 }
942
943 RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) {
944 memset(&tctl, 0, sizeof(tctl));
945 tctl.af = tnbr->af;
946 tctl.addr = tnbr->addr;
947 if (tnbr->adj == NULL)
948 tctl.no_adj = 1;
949
950 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0,
951 -1, &tctl, sizeof(tctl));
952
953 if (tnbr->adj == NULL)
954 continue;
955
956 actl = adj_to_ctl(tnbr->adj);
957 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0,
958 -1, actl, sizeof(struct ctl_adj));
959 }
960
961 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
962 }
963
964 void
965 ldpe_nbr_ctl(struct ctl_conn *c)
966 {
967 struct adj *adj;
968 struct ctl_adj *actl;
969 struct nbr *nbr;
970 struct ctl_nbr *nctl;
971
972 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
973 if (nbr->state == NBR_STA_PRESENT)
974 continue;
975
976 nctl = nbr_to_ctl(nbr);
977 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
978 sizeof(struct ctl_nbr));
979
980 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
981 actl = adj_to_ctl(adj);
982 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
983 0, 0, -1, actl, sizeof(struct ctl_adj));
984 }
985
986 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1,
987 NULL, 0);
988 }
989 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
990 }
991
992 void
993 ldpe_ldp_sync_ctl(struct ctl_conn *c)
994 {
995 struct iface *iface;
996 struct ctl_ldp_sync *ictl;
997
998 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
999 ictl = ldp_sync_to_ctl(iface);
1000 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_LDP_SYNC,
1001 0, 0, -1, ictl, sizeof(struct ctl_ldp_sync));
1002 }
1003 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1004 }
1005
1006 void
1007 mapping_list_add(struct mapping_head *mh, struct map *map)
1008 {
1009 struct mapping_entry *me;
1010
1011 me = calloc(1, sizeof(*me));
1012 if (me == NULL)
1013 fatal(__func__);
1014 me->map = *map;
1015
1016 TAILQ_INSERT_TAIL(mh, me, entry);
1017 }
1018
1019 void
1020 mapping_list_clr(struct mapping_head *mh)
1021 {
1022 struct mapping_entry *me;
1023
1024 while ((me = TAILQ_FIRST(mh)) != NULL) {
1025 TAILQ_REMOVE(mh, me, entry);
1026 assert(me != TAILQ_FIRST(mh));
1027 free(me);
1028 }
1029 }
1030
1031 void
1032 ldpe_check_filter_af(int af, struct ldpd_af_conf *af_conf,
1033 const char *filter_name)
1034 {
1035 if (strcmp(af_conf->acl_thello_accept_from, filter_name) == 0)
1036 ldpe_remove_dynamic_tnbrs(af);
1037 }
1038
1039 void
1040 ldpe_set_config_change_time(void)
1041 {
1042 /* SNMP update time when ever there is a config change */
1043 leconf->config_change_time = time(NULL);
1044 }