]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldpe.c
ldpd: copy original sources from OpenBSD (14/09/2016)
[mirror_frr.git] / ldpd / ldpe.c
CommitLineData
8429abe0
RW
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22#include <sys/types.h>
23#include <stdlib.h>
24#include <signal.h>
25#include <string.h>
26#include <pwd.h>
27#include <unistd.h>
28#include <arpa/inet.h>
29#include <errno.h>
30
31#include "ldpd.h"
32#include "ldpe.h"
33#include "lde.h"
34#include "control.h"
35#include "log.h"
36
37static void ldpe_sig_handler(int, short, void *);
38static __dead void ldpe_shutdown(void);
39static void ldpe_dispatch_main(int, short, void *);
40static void ldpe_dispatch_lde(int, short, void *);
41static void ldpe_dispatch_pfkey(int, short, void *);
42static void ldpe_setup_sockets(int, int, int, int);
43static void ldpe_close_sockets(int);
44static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45
46struct ldpd_conf *leconf;
47struct ldpd_sysdep sysdep;
48
49static struct imsgev *iev_main;
50static struct imsgev *iev_lde;
51static struct event pfkey_ev;
52
53/* ARGSUSED */
54static void
55ldpe_sig_handler(int sig, short event, void *bula)
56{
57 switch (sig) {
58 case SIGINT:
59 case SIGTERM:
60 ldpe_shutdown();
61 /* NOTREACHED */
62 default:
63 fatalx("unexpected signal");
64 }
65}
66
67/* label distribution protocol engine */
68void
69ldpe(int debug, int verbose)
70{
71 struct passwd *pw;
72 struct event ev_sigint, ev_sigterm;
73
74 leconf = config_new_empty();
75
76 log_init(debug);
77 log_verbose(verbose);
78
79 setproctitle("ldp engine");
80 ldpd_process = PROC_LDP_ENGINE;
81
82 /* create ldpd control socket outside chroot */
83 if (control_init() == -1)
84 fatalx("control socket setup failed");
85
86 LIST_INIT(&global.addr_list);
87 LIST_INIT(&global.adj_list);
88 TAILQ_INIT(&global.pending_conns);
89 if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
90 fatal("inet_pton");
91 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
92 fatal("inet_pton");
93 global.pfkeysock = pfkey_init();
94
95 if ((pw = getpwnam(LDPD_USER)) == NULL)
96 fatal("getpwnam");
97
98 if (chroot(pw->pw_dir) == -1)
99 fatal("chroot");
100 if (chdir("/") == -1)
101 fatal("chdir(\"/\")");
102
103 if (setgroups(1, &pw->pw_gid) ||
104 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
105 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
106 fatal("can't drop privileges");
107
108 if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
109 fatal("pledge");
110
111 event_init();
112 accept_init();
113
114 /* setup signal handler */
115 signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
116 signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
117 signal_add(&ev_sigint, NULL);
118 signal_add(&ev_sigterm, NULL);
119 signal(SIGPIPE, SIG_IGN);
120 signal(SIGHUP, SIG_IGN);
121
122 /* setup pipe and event handler to the parent process */
123 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
124 fatal(NULL);
125 imsg_init(&iev_main->ibuf, 3);
126 iev_main->handler = ldpe_dispatch_main;
127 iev_main->events = EV_READ;
128 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
129 iev_main->handler, iev_main);
130 event_add(&iev_main->ev, NULL);
131
132 if (sysdep.no_pfkey == 0) {
133 event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST,
134 ldpe_dispatch_pfkey, NULL);
135 event_add(&pfkey_ev, NULL);
136 }
137
138 /* mark sockets as closed */
139 global.ipv4.ldp_disc_socket = -1;
140 global.ipv4.ldp_edisc_socket = -1;
141 global.ipv4.ldp_session_socket = -1;
142 global.ipv6.ldp_disc_socket = -1;
143 global.ipv6.ldp_edisc_socket = -1;
144 global.ipv6.ldp_session_socket = -1;
145
146 /* listen on ldpd control socket */
147 TAILQ_INIT(&ctl_conns);
148 control_listen();
149
150 if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
151 fatal(__func__);
152
153 event_dispatch();
154
155 ldpe_shutdown();
156}
157
158static __dead void
159ldpe_shutdown(void)
160{
161 struct if_addr *if_addr;
162 struct adj *adj;
163
164 /* close pipes */
165 msgbuf_write(&iev_lde->ibuf.w);
166 msgbuf_clear(&iev_lde->ibuf.w);
167 close(iev_lde->ibuf.fd);
168 msgbuf_write(&iev_main->ibuf.w);
169 msgbuf_clear(&iev_main->ibuf.w);
170 close(iev_main->ibuf.fd);
171
172 control_cleanup();
173 config_clear(leconf);
174
175 if (sysdep.no_pfkey == 0) {
176 event_del(&pfkey_ev);
177 close(global.pfkeysock);
178 }
179 ldpe_close_sockets(AF_INET);
180 ldpe_close_sockets(AF_INET6);
181
182 /* remove addresses from global list */
183 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
184 LIST_REMOVE(if_addr, entry);
185 free(if_addr);
186 }
187 while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
188 adj_del(adj, S_SHUTDOWN);
189
190 /* clean up */
191 free(iev_lde);
192 free(iev_main);
193 free(pkt_ptr);
194
195 log_info("ldp engine exiting");
196 exit(0);
197}
198
199/* imesg */
200int
201ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
202{
203 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
204}
205
206int
207ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
208 uint16_t datalen)
209{
210 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
211 data, datalen));
212}
213
214/* ARGSUSED */
215static void
216ldpe_dispatch_main(int fd, short event, void *bula)
217{
218 static struct ldpd_conf *nconf;
219 struct iface *niface;
220 struct tnbr *ntnbr;
221 struct nbr_params *nnbrp;
222 static struct l2vpn *nl2vpn;
223 struct l2vpn_if *nlif;
224 struct l2vpn_pw *npw;
225 struct imsg imsg;
226 struct imsgev *iev = bula;
227 struct imsgbuf *ibuf = &iev->ibuf;
228 struct iface *iface = NULL;
229 struct kif *kif;
230 int af;
231 enum socket_type *socket_type;
232 static int disc_socket = -1;
233 static int edisc_socket = -1;
234 static int session_socket = -1;
235 struct nbr *nbr;
236 struct nbr_params *nbrp;
237 int n, shut = 0;
238
239 if (event & EV_READ) {
240 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
241 fatal("imsg_read error");
242 if (n == 0) /* connection closed */
243 shut = 1;
244 }
245 if (event & EV_WRITE) {
246 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
247 fatal("ldpe_dispatch_main: msgbuf_write");
248 if (n == 0)
249 shut = 1;
250 }
251
252 for (;;) {
253 if ((n = imsg_get(ibuf, &imsg)) == -1)
254 fatal("ldpe_dispatch_main: imsg_get error");
255 if (n == 0)
256 break;
257
258 switch (imsg.hdr.type) {
259 case IMSG_IFSTATUS:
260 if (imsg.hdr.len != IMSG_HEADER_SIZE +
261 sizeof(struct kif))
262 fatalx("IFSTATUS imsg with wrong len");
263 kif = imsg.data;
264
265 iface = if_lookup(leconf, kif->ifindex);
266 if (!iface)
267 break;
268
269 iface->flags = kif->flags;
270 iface->linkstate = kif->link_state;
271 if_update(iface, AF_UNSPEC);
272 break;
273 case IMSG_NEWADDR:
274 if (imsg.hdr.len != IMSG_HEADER_SIZE +
275 sizeof(struct kaddr))
276 fatalx("NEWADDR imsg with wrong len");
277
278 if_addr_add(imsg.data);
279 break;
280 case IMSG_DELADDR:
281 if (imsg.hdr.len != IMSG_HEADER_SIZE +
282 sizeof(struct kaddr))
283 fatalx("DELADDR imsg with wrong len");
284
285 if_addr_del(imsg.data);
286 break;
287 case IMSG_SOCKET_IPC:
288 if (iev_lde) {
289 log_warnx("%s: received unexpected imsg fd "
290 "to lde", __func__);
291 break;
292 }
293 if ((fd = imsg.fd) == -1) {
294 log_warnx("%s: expected to receive imsg fd to "
295 "lde but didn't receive any", __func__);
296 break;
297 }
298
299 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
300 fatal(NULL);
301 imsg_init(&iev_lde->ibuf, fd);
302 iev_lde->handler = ldpe_dispatch_lde;
303 iev_lde->events = EV_READ;
304 event_set(&iev_lde->ev, iev_lde->ibuf.fd,
305 iev_lde->events, iev_lde->handler, iev_lde);
306 event_add(&iev_lde->ev, NULL);
307 break;
308 case IMSG_CLOSE_SOCKETS:
309 af = imsg.hdr.peerid;
310
311 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
312 if (nbr->af != af)
313 continue;
314 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
315 pfkey_remove(nbr);
316 }
317 ldpe_close_sockets(af);
318 if_update_all(af);
319 tnbr_update_all(af);
320
321 disc_socket = -1;
322 edisc_socket = -1;
323 session_socket = -1;
324 if ((ldp_af_conf_get(leconf, af))->flags &
325 F_LDPD_AF_ENABLED)
326 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
327 af, NULL, 0);
328 break;
329 case IMSG_SOCKET_NET:
330 if (imsg.hdr.len != IMSG_HEADER_SIZE +
331 sizeof(enum socket_type))
332 fatalx("SOCKET_NET imsg with wrong len");
333 socket_type = imsg.data;
334
335 switch (*socket_type) {
336 case LDP_SOCKET_DISC:
337 disc_socket = imsg.fd;
338 break;
339 case LDP_SOCKET_EDISC:
340 edisc_socket = imsg.fd;
341 break;
342 case LDP_SOCKET_SESSION:
343 session_socket = imsg.fd;
344 break;
345 }
346 break;
347 case IMSG_SETUP_SOCKETS:
348 af = imsg.hdr.peerid;
349 if (disc_socket == -1 || edisc_socket == -1 ||
350 session_socket == -1) {
351 if (disc_socket != -1)
352 close(disc_socket);
353 if (edisc_socket != -1)
354 close(edisc_socket);
355 if (session_socket != -1)
356 close(session_socket);
357 break;
358 }
359
360 ldpe_setup_sockets(af, disc_socket, edisc_socket,
361 session_socket);
362 if_update_all(af);
363 tnbr_update_all(af);
364 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
365 if (nbr->af != af)
366 continue;
367 nbr->laddr = (ldp_af_conf_get(leconf,
368 af))->trans_addr;
369 nbrp = nbr_params_find(leconf, nbr->id);
370 if (nbrp && pfkey_establish(nbr, nbrp) == -1)
371 fatalx("pfkey setup failed");
372 if (nbr_session_active_role(nbr))
373 nbr_establish_connection(nbr);
374 }
375 break;
376 case IMSG_RECONF_CONF:
377 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
378 NULL)
379 fatal(NULL);
380 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
381
382 LIST_INIT(&nconf->iface_list);
383 LIST_INIT(&nconf->tnbr_list);
384 LIST_INIT(&nconf->nbrp_list);
385 LIST_INIT(&nconf->l2vpn_list);
386 break;
387 case IMSG_RECONF_IFACE:
388 if ((niface = malloc(sizeof(struct iface))) == NULL)
389 fatal(NULL);
390 memcpy(niface, imsg.data, sizeof(struct iface));
391
392 LIST_INIT(&niface->addr_list);
393 LIST_INIT(&niface->ipv4.adj_list);
394 LIST_INIT(&niface->ipv6.adj_list);
395 niface->ipv4.iface = niface;
396 niface->ipv6.iface = niface;
397
398 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
399 break;
400 case IMSG_RECONF_TNBR:
401 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
402 fatal(NULL);
403 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
404
405 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
406 break;
407 case IMSG_RECONF_NBRP:
408 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
409 fatal(NULL);
410 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
411
412 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
413 break;
414 case IMSG_RECONF_L2VPN:
415 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
416 fatal(NULL);
417 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
418
419 LIST_INIT(&nl2vpn->if_list);
420 LIST_INIT(&nl2vpn->pw_list);
421
422 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
423 break;
424 case IMSG_RECONF_L2VPN_IF:
425 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
426 fatal(NULL);
427 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
428
429 nlif->l2vpn = nl2vpn;
430 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
431 break;
432 case IMSG_RECONF_L2VPN_PW:
433 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
434 fatal(NULL);
435 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
436
437 npw->l2vpn = nl2vpn;
438 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
439 break;
440 case IMSG_RECONF_END:
441 merge_config(leconf, nconf);
442 nconf = NULL;
443 global.conf_seqnum++;
444 break;
445 case IMSG_CTL_KROUTE:
446 case IMSG_CTL_KROUTE_ADDR:
447 case IMSG_CTL_IFINFO:
448 case IMSG_CTL_END:
449 control_imsg_relay(&imsg);
450 break;
451 default:
452 log_debug("ldpe_dispatch_main: error handling imsg %d",
453 imsg.hdr.type);
454 break;
455 }
456 imsg_free(&imsg);
457 }
458 if (!shut)
459 imsg_event_add(iev);
460 else {
461 /* this pipe is dead, so remove the event handler */
462 event_del(&iev->ev);
463 event_loopexit(NULL);
464 }
465}
466
467/* ARGSUSED */
468static void
469ldpe_dispatch_lde(int fd, short event, void *bula)
470{
471 struct imsgev *iev = bula;
472 struct imsgbuf *ibuf = &iev->ibuf;
473 struct imsg imsg;
474 struct map map;
475 struct notify_msg nm;
476 int n, shut = 0;
477 struct nbr *nbr = NULL;
478
479 if (event & EV_READ) {
480 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
481 fatal("imsg_read error");
482 if (n == 0) /* connection closed */
483 shut = 1;
484 }
485 if (event & EV_WRITE) {
486 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
487 fatal("ldpe_dispatch_lde: msgbuf_write");
488 if (n == 0)
489 shut = 1;
490 }
491
492 for (;;) {
493 if ((n = imsg_get(ibuf, &imsg)) == -1)
494 fatal("ldpe_dispatch_lde: imsg_get error");
495 if (n == 0)
496 break;
497
498 switch (imsg.hdr.type) {
499 case IMSG_MAPPING_ADD:
500 case IMSG_RELEASE_ADD:
501 case IMSG_REQUEST_ADD:
502 case IMSG_WITHDRAW_ADD:
503 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
504 fatalx("invalid size of map request");
505 memcpy(&map, imsg.data, sizeof(map));
506
507 nbr = nbr_find_peerid(imsg.hdr.peerid);
508 if (nbr == NULL) {
509 log_debug("ldpe_dispatch_lde: cannot find "
510 "neighbor");
511 break;
512 }
513 if (nbr->state != NBR_STA_OPER)
514 break;
515
516 switch (imsg.hdr.type) {
517 case IMSG_MAPPING_ADD:
518 mapping_list_add(&nbr->mapping_list, &map);
519 break;
520 case IMSG_RELEASE_ADD:
521 mapping_list_add(&nbr->release_list, &map);
522 break;
523 case IMSG_REQUEST_ADD:
524 mapping_list_add(&nbr->request_list, &map);
525 break;
526 case IMSG_WITHDRAW_ADD:
527 mapping_list_add(&nbr->withdraw_list, &map);
528 break;
529 }
530 break;
531 case IMSG_MAPPING_ADD_END:
532 case IMSG_RELEASE_ADD_END:
533 case IMSG_REQUEST_ADD_END:
534 case IMSG_WITHDRAW_ADD_END:
535 nbr = nbr_find_peerid(imsg.hdr.peerid);
536 if (nbr == NULL) {
537 log_debug("ldpe_dispatch_lde: cannot find "
538 "neighbor");
539 break;
540 }
541 if (nbr->state != NBR_STA_OPER)
542 break;
543
544 switch (imsg.hdr.type) {
545 case IMSG_MAPPING_ADD_END:
546 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
547 &nbr->mapping_list);
548 break;
549 case IMSG_RELEASE_ADD_END:
550 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
551 &nbr->release_list);
552 break;
553 case IMSG_REQUEST_ADD_END:
554 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
555 &nbr->request_list);
556 break;
557 case IMSG_WITHDRAW_ADD_END:
558 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
559 &nbr->withdraw_list);
560 break;
561 }
562 break;
563 case IMSG_NOTIFICATION_SEND:
564 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
565 fatalx("invalid size of OE request");
566 memcpy(&nm, imsg.data, sizeof(nm));
567
568 nbr = nbr_find_peerid(imsg.hdr.peerid);
569 if (nbr == NULL) {
570 log_debug("ldpe_dispatch_lde: cannot find "
571 "neighbor");
572 break;
573 }
574 if (nbr->state != NBR_STA_OPER)
575 break;
576
577 send_notification_full(nbr->tcp, &nm);
578 break;
579 case IMSG_CTL_END:
580 case IMSG_CTL_SHOW_LIB:
581 case IMSG_CTL_SHOW_L2VPN_PW:
582 case IMSG_CTL_SHOW_L2VPN_BINDING:
583 control_imsg_relay(&imsg);
584 break;
585 default:
586 log_debug("ldpe_dispatch_lde: error handling imsg %d",
587 imsg.hdr.type);
588 break;
589 }
590 imsg_free(&imsg);
591 }
592 if (!shut)
593 imsg_event_add(iev);
594 else {
595 /* this pipe is dead, so remove the event handler */
596 event_del(&iev->ev);
597 event_loopexit(NULL);
598 }
599}
600
601/* ARGSUSED */
602static void
603ldpe_dispatch_pfkey(int fd, short event, void *bula)
604{
605 if (event & EV_READ) {
606 if (pfkey_read(fd, NULL) == -1) {
607 fatal("pfkey_read failed, exiting...");
608 }
609 }
610}
611
612static void
613ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
614 int session_socket)
615{
616 struct ldpd_af_global *af_global;
617
618 af_global = ldp_af_global_get(&global, af);
619
620 /* discovery socket */
621 af_global->ldp_disc_socket = disc_socket;
622 event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
623 EV_READ|EV_PERSIST, disc_recv_packet, NULL);
624 event_add(&af_global->disc_ev, NULL);
625
626 /* extended discovery socket */
627 af_global->ldp_edisc_socket = edisc_socket;
628 event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
629 EV_READ|EV_PERSIST, disc_recv_packet, NULL);
630 event_add(&af_global->edisc_ev, NULL);
631
632 /* session socket */
633 af_global->ldp_session_socket = session_socket;
634 accept_add(af_global->ldp_session_socket, session_accept, NULL);
635}
636
637static void
638ldpe_close_sockets(int af)
639{
640 struct ldpd_af_global *af_global;
641
642 af_global = ldp_af_global_get(&global, af);
643
644 /* discovery socket */
645 if (event_initialized(&af_global->disc_ev))
646 event_del(&af_global->disc_ev);
647 if (af_global->ldp_disc_socket != -1) {
648 close(af_global->ldp_disc_socket);
649 af_global->ldp_disc_socket = -1;
650 }
651
652 /* extended discovery socket */
653 if (event_initialized(&af_global->edisc_ev))
654 event_del(&af_global->edisc_ev);
655 if (af_global->ldp_edisc_socket != -1) {
656 close(af_global->ldp_edisc_socket);
657 af_global->ldp_edisc_socket = -1;
658 }
659
660 /* session socket */
661 if (af_global->ldp_session_socket != -1) {
662 accept_del(af_global->ldp_session_socket);
663 close(af_global->ldp_session_socket);
664 af_global->ldp_session_socket = -1;
665 }
666}
667
668void
669ldpe_reset_nbrs(int af)
670{
671 struct nbr *nbr;
672
673 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
674 if (nbr->af == af)
675 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
676 }
677}
678
679void
680ldpe_reset_ds_nbrs(void)
681{
682 struct nbr *nbr;
683
684 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
685 if (nbr->ds_tlv)
686 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
687 }
688}
689
690void
691ldpe_remove_dynamic_tnbrs(int af)
692{
693 struct tnbr *tnbr, *safe;
694
695 LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
696 if (tnbr->af != af)
697 continue;
698
699 tnbr->flags &= ~F_TNBR_DYNAMIC;
700 tnbr_check(tnbr);
701 }
702}
703
704void
705ldpe_stop_init_backoff(int af)
706{
707 struct nbr *nbr;
708
709 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
710 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
711 nbr_stop_idtimer(nbr);
712 nbr_establish_connection(nbr);
713 }
714 }
715}
716
717static void
718ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
719{
720 struct iface *iface;
721 struct iface_af *ia;
722 struct ctl_iface *ictl;
723
724 LIST_FOREACH(iface, &leconf->iface_list, entry) {
725 if (idx == 0 || idx == iface->ifindex) {
726 ia = iface_af_get(iface, af);
727 if (!ia->enabled)
728 continue;
729
730 ictl = if_to_ctl(ia);
731 imsg_compose_event(&c->iev,
732 IMSG_CTL_SHOW_INTERFACE,
733 0, 0, -1, ictl, sizeof(struct ctl_iface));
734 }
735 }
736}
737
738void
739ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
740{
741 ldpe_iface_af_ctl(c, AF_INET, idx);
742 ldpe_iface_af_ctl(c, AF_INET6, idx);
743}
744
745void
746ldpe_adj_ctl(struct ctl_conn *c)
747{
748 struct nbr *nbr;
749 struct adj *adj;
750 struct ctl_adj *actl;
751
752 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
753 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) {
754 actl = adj_to_ctl(adj);
755 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
756 0, 0, -1, actl, sizeof(struct ctl_adj));
757 }
758 }
759 /* show adjacencies not associated with any neighbor */
760 LIST_FOREACH(adj, &global.adj_list, global_entry) {
761 if (adj->nbr != NULL)
762 continue;
763
764 actl = adj_to_ctl(adj);
765 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
766 -1, actl, sizeof(struct ctl_adj));
767 }
768
769 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
770}
771
772void
773ldpe_nbr_ctl(struct ctl_conn *c)
774{
775 struct nbr *nbr;
776 struct ctl_nbr *nctl;
777
778 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
779 nctl = nbr_to_ctl(nbr);
780 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
781 sizeof(struct ctl_nbr));
782 }
783 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
784}
785
786void
787mapping_list_add(struct mapping_head *mh, struct map *map)
788{
789 struct mapping_entry *me;
790
791 me = calloc(1, sizeof(*me));
792 if (me == NULL)
793 fatal(__func__);
794 me->map = *map;
795
796 TAILQ_INSERT_TAIL(mh, me, entry);
797}
798
799void
800mapping_list_clr(struct mapping_head *mh)
801{
802 struct mapping_entry *me;
803
804 while ((me = TAILQ_FIRST(mh)) != NULL) {
805 TAILQ_REMOVE(mh, me, entry);
806 free(me);
807 }
808}