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