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