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>
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.
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.
29 #include "ldp_debug.h"
36 static void ldpe_shutdown(void);
37 static int ldpe_dispatch_main(struct thread
*);
38 static int ldpe_dispatch_lde(struct thread
*);
40 static int ldpe_dispatch_pfkey(struct thread
*);
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);
46 struct ldpd_conf
*leconf
;
48 struct ldpd_sysdep sysdep
;
51 static struct imsgev
*iev_main
;
52 static struct imsgev
*iev_lde
;
54 static struct thread
*pfkey_ev
;
57 /* Master of threads. */
58 struct thread_master
*master
;
61 static zebra_capabilities_t _caps_p
[] =
67 struct zebra_privs_t ldpe_privs
=
69 #if defined(QUAGGA_USER) && defined(QUAGGA_GROUP)
71 .group
= QUAGGA_GROUP
,
73 #if defined(VTY_GROUP)
74 .vty_group
= VTY_GROUP
,
77 .cap_num_p
= array_size(_caps_p
),
81 /* SIGINT / SIGTERM handler. */
88 static struct quagga_signal_t ldpe_signals
[] =
100 /* label distribution protocol engine */
102 ldpe(const char *user
, const char *group
)
104 struct thread thread
;
106 leconf
= config_new_empty();
108 #ifdef HAVE_SETPROCTITLE
109 setproctitle("ldp engine");
111 ldpd_process
= PROC_LDP_ENGINE
;
113 LIST_INIT(&global
.addr_list
);
114 LIST_INIT(&global
.adj_list
);
115 TAILQ_INIT(&global
.pending_conns
);
116 if (inet_pton(AF_INET
, AllRouters_v4
, &global
.mcast_addr_v4
) != 1)
118 if (inet_pton(AF_INET6
, AllRouters_v6
, &global
.mcast_addr_v6
) != 1)
121 global
.pfkeysock
= pfkey_init();
124 /* drop privileges */
126 ldpe_privs
.user
= user
;
128 ldpe_privs
.group
= group
;
129 zprivs_init(&ldpe_privs
);
131 if (control_init() == -1)
132 fatalx("control socket setup failed");
135 if (pledge("stdio cpath inet mcast recvfd", NULL
) == -1)
139 master
= thread_master_create();
142 /* setup signal handler */
143 signal_init(master
, array_size(ldpe_signals
), ldpe_signals
);
145 /* setup pipe and event handler to the parent process */
146 if ((iev_main
= malloc(sizeof(struct imsgev
))) == NULL
)
148 imsg_init(&iev_main
->ibuf
, 3);
149 iev_main
->handler_read
= ldpe_dispatch_main
;
150 iev_main
->ev_read
= thread_add_read(master
, iev_main
->handler_read
,
151 iev_main
, iev_main
->ibuf
.fd
);
152 iev_main
->handler_write
= ldp_write_handler
;
153 iev_main
->ev_write
= NULL
;
156 if (sysdep
.no_pfkey
== 0)
157 pfkey_ev
= thread_add_read(master
, ldpe_dispatch_pfkey
,
158 NULL
, global
.pfkeysock
);
161 /* mark sockets as closed */
162 global
.ipv4
.ldp_disc_socket
= -1;
163 global
.ipv4
.ldp_edisc_socket
= -1;
164 global
.ipv4
.ldp_session_socket
= -1;
165 global
.ipv6
.ldp_disc_socket
= -1;
166 global
.ipv6
.ldp_edisc_socket
= -1;
167 global
.ipv6
.ldp_session_socket
= -1;
169 /* listen on ldpd control socket */
170 TAILQ_INIT(&ctl_conns
);
173 if ((pkt_ptr
= calloc(1, IBUF_READ_SIZE
)) == NULL
)
176 /* Fetch next active thread. */
177 while (thread_fetch(master
, &thread
))
178 thread_call(&thread
);
184 struct if_addr
*if_addr
;
188 msgbuf_write(&iev_lde
->ibuf
.w
);
189 msgbuf_clear(&iev_lde
->ibuf
.w
);
190 close(iev_lde
->ibuf
.fd
);
191 msgbuf_write(&iev_main
->ibuf
.w
);
192 msgbuf_clear(&iev_main
->ibuf
.w
);
193 close(iev_main
->ibuf
.fd
);
196 config_clear(leconf
);
199 if (sysdep
.no_pfkey
== 0) {
200 THREAD_READ_OFF(pfkey_ev
);
201 close(global
.pfkeysock
);
204 ldpe_close_sockets(AF_INET
);
205 ldpe_close_sockets(AF_INET6
);
207 /* remove addresses from global list */
208 while ((if_addr
= LIST_FIRST(&global
.addr_list
)) != NULL
) {
209 LIST_REMOVE(if_addr
, entry
);
212 while ((adj
= LIST_FIRST(&global
.adj_list
)) != NULL
)
213 adj_del(adj
, S_SHUTDOWN
);
220 log_info("ldp engine exiting");
226 ldpe_imsg_compose_parent(int type
, pid_t pid
, void *data
, uint16_t datalen
)
228 return (imsg_compose_event(iev_main
, type
, 0, pid
, -1, data
, datalen
));
232 ldpe_imsg_compose_lde(int type
, uint32_t peerid
, pid_t pid
, void *data
,
235 return (imsg_compose_event(iev_lde
, type
, peerid
, pid
, -1,
241 ldpe_dispatch_main(struct thread
*thread
)
243 static struct ldpd_conf
*nconf
;
244 struct iface
*niface
;
246 struct nbr_params
*nnbrp
;
247 static struct l2vpn
*nl2vpn
;
248 struct l2vpn_if
*nlif
;
249 struct l2vpn_pw
*npw
;
251 int fd
= THREAD_FD(thread
);
252 struct imsgev
*iev
= THREAD_ARG(thread
);
253 struct imsgbuf
*ibuf
= &iev
->ibuf
;
254 struct iface
*iface
= NULL
;
257 enum socket_type
*socket_type
;
258 static int disc_socket
= -1;
259 static int edisc_socket
= -1;
260 static int session_socket
= -1;
263 struct nbr_params
*nbrp
;
269 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
270 fatal("imsg_read error");
271 if (n
== 0) /* connection closed */
275 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
276 fatal("ldpe_dispatch_main: imsg_get error");
280 switch (imsg
.hdr
.type
) {
282 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
284 fatalx("IFSTATUS imsg with wrong len");
287 iface
= if_lookup_name(leconf
, kif
->ifname
);
291 if_update_info(iface
, kif
);
292 if_update(iface
, AF_UNSPEC
);
295 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
296 sizeof(struct kaddr
))
297 fatalx("NEWADDR imsg with wrong len");
299 if_addr_add(imsg
.data
);
302 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
303 sizeof(struct kaddr
))
304 fatalx("DELADDR imsg with wrong len");
306 if_addr_del(imsg
.data
);
308 case IMSG_SOCKET_IPC
:
310 log_warnx("%s: received unexpected imsg fd "
314 if ((fd
= imsg
.fd
) == -1) {
315 log_warnx("%s: expected to receive imsg fd to "
316 "lde but didn't receive any", __func__
);
320 if ((iev_lde
= malloc(sizeof(struct imsgev
))) == NULL
)
322 imsg_init(&iev_lde
->ibuf
, fd
);
323 iev_lde
->handler_read
= ldpe_dispatch_lde
;
324 iev_lde
->ev_read
= thread_add_read(master
,
325 iev_lde
->handler_read
, iev_lde
, iev_lde
->ibuf
.fd
);
326 iev_lde
->handler_write
= ldp_write_handler
;
327 iev_lde
->ev_write
= NULL
;
329 case IMSG_CLOSE_SOCKETS
:
330 af
= imsg
.hdr
.peerid
;
332 RB_FOREACH(nbr
, nbr_id_head
, &nbrs_by_id
) {
335 session_shutdown(nbr
, S_SHUTDOWN
, 0, 0);
340 ldpe_close_sockets(af
);
347 if ((ldp_af_conf_get(leconf
, af
))->flags
&
349 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS
,
352 case IMSG_SOCKET_NET
:
353 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
354 sizeof(enum socket_type
))
355 fatalx("SOCKET_NET imsg with wrong len");
356 socket_type
= imsg
.data
;
358 switch (*socket_type
) {
359 case LDP_SOCKET_DISC
:
360 disc_socket
= imsg
.fd
;
362 case LDP_SOCKET_EDISC
:
363 edisc_socket
= imsg
.fd
;
365 case LDP_SOCKET_SESSION
:
366 session_socket
= imsg
.fd
;
370 case IMSG_SETUP_SOCKETS
:
371 af
= imsg
.hdr
.peerid
;
372 if (disc_socket
== -1 || edisc_socket
== -1 ||
373 session_socket
== -1) {
374 if (disc_socket
!= -1)
376 if (edisc_socket
!= -1)
378 if (session_socket
!= -1)
379 close(session_socket
);
383 ldpe_setup_sockets(af
, disc_socket
, edisc_socket
,
387 RB_FOREACH(nbr
, nbr_id_head
, &nbrs_by_id
) {
390 nbr
->laddr
= (ldp_af_conf_get(leconf
,
393 nbrp
= nbr_params_find(leconf
, nbr
->id
);
394 if (nbrp
&& pfkey_establish(nbr
, nbrp
) == -1)
395 fatalx("pfkey setup failed");
397 if (nbr_session_active_role(nbr
))
398 nbr_establish_connection(nbr
);
401 case IMSG_RTRID_UPDATE
:
402 memcpy(&global
.rtr_id
, imsg
.data
,
403 sizeof(global
.rtr_id
));
404 if (leconf
->rtr_id
.s_addr
== INADDR_ANY
) {
405 ldpe_reset_nbrs(AF_INET
);
406 ldpe_reset_nbrs(AF_INET6
);
408 if_update_all(AF_UNSPEC
);
409 tnbr_update_all(AF_UNSPEC
);
411 case IMSG_RECONF_CONF
:
412 if ((nconf
= malloc(sizeof(struct ldpd_conf
))) ==
415 memcpy(nconf
, imsg
.data
, sizeof(struct ldpd_conf
));
417 RB_INIT(&nconf
->iface_tree
);
418 RB_INIT(&nconf
->tnbr_tree
);
419 RB_INIT(&nconf
->nbrp_tree
);
420 RB_INIT(&nconf
->l2vpn_tree
);
422 case IMSG_RECONF_IFACE
:
423 if ((niface
= malloc(sizeof(struct iface
))) == NULL
)
425 memcpy(niface
, imsg
.data
, sizeof(struct iface
));
427 LIST_INIT(&niface
->addr_list
);
428 LIST_INIT(&niface
->ipv4
.adj_list
);
429 LIST_INIT(&niface
->ipv6
.adj_list
);
430 niface
->ipv4
.iface
= niface
;
431 niface
->ipv6
.iface
= niface
;
433 RB_INSERT(iface_head
, &nconf
->iface_tree
, niface
);
435 case IMSG_RECONF_TNBR
:
436 if ((ntnbr
= malloc(sizeof(struct tnbr
))) == NULL
)
438 memcpy(ntnbr
, imsg
.data
, sizeof(struct tnbr
));
440 RB_INSERT(tnbr_head
, &nconf
->tnbr_tree
, ntnbr
);
442 case IMSG_RECONF_NBRP
:
443 if ((nnbrp
= malloc(sizeof(struct nbr_params
))) == NULL
)
445 memcpy(nnbrp
, imsg
.data
, sizeof(struct nbr_params
));
447 RB_INSERT(nbrp_head
, &nconf
->nbrp_tree
, nnbrp
);
449 case IMSG_RECONF_L2VPN
:
450 if ((nl2vpn
= malloc(sizeof(struct l2vpn
))) == NULL
)
452 memcpy(nl2vpn
, imsg
.data
, sizeof(struct l2vpn
));
454 RB_INIT(&nl2vpn
->if_tree
);
455 RB_INIT(&nl2vpn
->pw_tree
);
456 RB_INIT(&nl2vpn
->pw_inactive_tree
);
458 RB_INSERT(l2vpn_head
, &nconf
->l2vpn_tree
, nl2vpn
);
460 case IMSG_RECONF_L2VPN_IF
:
461 if ((nlif
= malloc(sizeof(struct l2vpn_if
))) == NULL
)
463 memcpy(nlif
, imsg
.data
, sizeof(struct l2vpn_if
));
465 nlif
->l2vpn
= nl2vpn
;
466 RB_INSERT(l2vpn_if_head
, &nl2vpn
->if_tree
, nlif
);
468 case IMSG_RECONF_L2VPN_PW
:
469 if ((npw
= malloc(sizeof(struct l2vpn_pw
))) == NULL
)
471 memcpy(npw
, imsg
.data
, sizeof(struct l2vpn_pw
));
474 RB_INSERT(l2vpn_pw_head
, &nl2vpn
->pw_tree
, npw
);
476 case IMSG_RECONF_L2VPN_IPW
:
477 if ((npw
= malloc(sizeof(struct l2vpn_pw
))) == NULL
)
479 memcpy(npw
, imsg
.data
, sizeof(struct l2vpn_pw
));
482 RB_INSERT(l2vpn_pw_head
, &nl2vpn
->pw_inactive_tree
, npw
);
484 case IMSG_RECONF_END
:
485 merge_config(leconf
, nconf
);
487 global
.conf_seqnum
++;
490 control_imsg_relay(&imsg
);
492 case IMSG_DEBUG_UPDATE
:
493 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
495 log_warnx("%s: wrong imsg len", __func__
);
498 memcpy(&ldp_debug
, imsg
.data
, sizeof(ldp_debug
));
501 log_debug("ldpe_dispatch_main: error handling imsg %d",
510 /* this pipe is dead, so remove the event handlers and exit */
511 THREAD_READ_OFF(iev
->ev_read
);
512 THREAD_WRITE_OFF(iev
->ev_write
);
521 ldpe_dispatch_lde(struct thread
*thread
)
523 struct imsgev
*iev
= THREAD_ARG(thread
);
524 struct imsgbuf
*ibuf
= &iev
->ibuf
;
527 struct notify_msg nm
;
529 struct nbr
*nbr
= NULL
;
533 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
534 fatal("imsg_read error");
535 if (n
== 0) /* connection closed */
539 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
540 fatal("ldpe_dispatch_lde: imsg_get error");
544 switch (imsg
.hdr
.type
) {
545 case IMSG_MAPPING_ADD
:
546 case IMSG_RELEASE_ADD
:
547 case IMSG_REQUEST_ADD
:
548 case IMSG_WITHDRAW_ADD
:
549 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= sizeof(map
))
550 fatalx("invalid size of map request");
551 memcpy(&map
, imsg
.data
, sizeof(map
));
553 nbr
= nbr_find_peerid(imsg
.hdr
.peerid
);
555 log_debug("ldpe_dispatch_lde: cannot find "
559 if (nbr
->state
!= NBR_STA_OPER
)
562 switch (imsg
.hdr
.type
) {
563 case IMSG_MAPPING_ADD
:
564 mapping_list_add(&nbr
->mapping_list
, &map
);
566 case IMSG_RELEASE_ADD
:
567 mapping_list_add(&nbr
->release_list
, &map
);
569 case IMSG_REQUEST_ADD
:
570 mapping_list_add(&nbr
->request_list
, &map
);
572 case IMSG_WITHDRAW_ADD
:
573 mapping_list_add(&nbr
->withdraw_list
, &map
);
577 case IMSG_MAPPING_ADD_END
:
578 case IMSG_RELEASE_ADD_END
:
579 case IMSG_REQUEST_ADD_END
:
580 case IMSG_WITHDRAW_ADD_END
:
581 nbr
= nbr_find_peerid(imsg
.hdr
.peerid
);
583 log_debug("ldpe_dispatch_lde: cannot find "
587 if (nbr
->state
!= NBR_STA_OPER
)
590 switch (imsg
.hdr
.type
) {
591 case IMSG_MAPPING_ADD_END
:
592 send_labelmessage(nbr
, MSG_TYPE_LABELMAPPING
,
595 case IMSG_RELEASE_ADD_END
:
596 send_labelmessage(nbr
, MSG_TYPE_LABELRELEASE
,
599 case IMSG_REQUEST_ADD_END
:
600 send_labelmessage(nbr
, MSG_TYPE_LABELREQUEST
,
603 case IMSG_WITHDRAW_ADD_END
:
604 send_labelmessage(nbr
, MSG_TYPE_LABELWITHDRAW
,
605 &nbr
->withdraw_list
);
609 case IMSG_NOTIFICATION_SEND
:
610 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= sizeof(nm
))
611 fatalx("invalid size of OE request");
612 memcpy(&nm
, imsg
.data
, sizeof(nm
));
614 nbr
= nbr_find_peerid(imsg
.hdr
.peerid
);
616 log_debug("ldpe_dispatch_lde: cannot find "
620 if (nbr
->state
!= NBR_STA_OPER
)
623 send_notification_full(nbr
->tcp
, &nm
);
626 case IMSG_CTL_SHOW_LIB
:
627 case IMSG_CTL_SHOW_L2VPN_PW
:
628 case IMSG_CTL_SHOW_L2VPN_BINDING
:
629 control_imsg_relay(&imsg
);
632 log_debug("ldpe_dispatch_lde: error handling imsg %d",
641 /* this pipe is dead, so remove the event handlers and exit */
642 THREAD_READ_OFF(iev
->ev_read
);
643 THREAD_WRITE_OFF(iev
->ev_write
);
653 ldpe_dispatch_pfkey(struct thread
*thread
)
655 int fd
= THREAD_FD(thread
);
657 pfkey_ev
= thread_add_read(master
, ldpe_dispatch_pfkey
,
658 NULL
, global
.pfkeysock
);
660 if (pfkey_read(fd
, NULL
) == -1)
661 fatal("pfkey_read failed, exiting...");
665 #endif /* __OpenBSD__ */
668 ldpe_setup_sockets(int af
, int disc_socket
, int edisc_socket
,
671 struct ldpd_af_global
*af_global
;
673 af_global
= ldp_af_global_get(&global
, af
);
675 /* discovery socket */
676 af_global
->ldp_disc_socket
= disc_socket
;
677 af_global
->disc_ev
= thread_add_read(master
, disc_recv_packet
,
678 &af_global
->disc_ev
, af_global
->ldp_disc_socket
);
680 /* extended discovery socket */
681 af_global
->ldp_edisc_socket
= edisc_socket
;
682 af_global
->edisc_ev
= thread_add_read(master
, disc_recv_packet
,
683 &af_global
->edisc_ev
, af_global
->ldp_edisc_socket
);
686 af_global
->ldp_session_socket
= session_socket
;
687 accept_add(af_global
->ldp_session_socket
, session_accept
, NULL
);
691 ldpe_close_sockets(int af
)
693 struct ldpd_af_global
*af_global
;
695 af_global
= ldp_af_global_get(&global
, af
);
697 /* discovery socket */
698 THREAD_READ_OFF(af_global
->disc_ev
);
699 if (af_global
->ldp_disc_socket
!= -1) {
700 close(af_global
->ldp_disc_socket
);
701 af_global
->ldp_disc_socket
= -1;
704 /* extended discovery socket */
705 THREAD_READ_OFF(af_global
->edisc_ev
);
706 if (af_global
->ldp_edisc_socket
!= -1) {
707 close(af_global
->ldp_edisc_socket
);
708 af_global
->ldp_edisc_socket
= -1;
712 if (af_global
->ldp_session_socket
!= -1) {
713 accept_del(af_global
->ldp_session_socket
);
714 close(af_global
->ldp_session_socket
);
715 af_global
->ldp_session_socket
= -1;
720 ldpe_reset_nbrs(int af
)
724 RB_FOREACH(nbr
, nbr_id_head
, &nbrs_by_id
) {
726 session_shutdown(nbr
, S_SHUTDOWN
, 0, 0);
731 ldpe_reset_ds_nbrs(void)
735 RB_FOREACH(nbr
, nbr_id_head
, &nbrs_by_id
) {
737 session_shutdown(nbr
, S_SHUTDOWN
, 0, 0);
742 ldpe_remove_dynamic_tnbrs(int af
)
744 struct tnbr
*tnbr
, *safe
;
746 RB_FOREACH_SAFE(tnbr
, tnbr_head
, &leconf
->tnbr_tree
, safe
) {
750 tnbr
->flags
&= ~F_TNBR_DYNAMIC
;
751 tnbr_check(leconf
, tnbr
);
756 ldpe_stop_init_backoff(int af
)
760 RB_FOREACH(nbr
, nbr_id_head
, &nbrs_by_id
) {
761 if (nbr
->af
== af
&& nbr_pending_idtimer(nbr
)) {
762 nbr_stop_idtimer(nbr
);
763 nbr_establish_connection(nbr
);
769 ldpe_iface_af_ctl(struct ctl_conn
*c
, int af
, unsigned int idx
)
773 struct ctl_iface
*ictl
;
775 RB_FOREACH(iface
, iface_head
, &leconf
->iface_tree
) {
776 if (idx
== 0 || idx
== iface
->ifindex
) {
777 ia
= iface_af_get(iface
, af
);
781 ictl
= if_to_ctl(ia
);
782 imsg_compose_event(&c
->iev
,
783 IMSG_CTL_SHOW_INTERFACE
,
784 0, 0, -1, ictl
, sizeof(struct ctl_iface
));
790 ldpe_iface_ctl(struct ctl_conn
*c
, unsigned int idx
)
792 ldpe_iface_af_ctl(c
, AF_INET
, idx
);
793 ldpe_iface_af_ctl(c
, AF_INET6
, idx
);
797 ldpe_adj_ctl(struct ctl_conn
*c
)
802 struct ctl_adj
*actl
;
803 struct ctl_disc_if ictl
;
804 struct ctl_disc_tnbr tctl
;
806 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISCOVERY
, 0, 0, -1, NULL
, 0);
808 RB_FOREACH(iface
, iface_head
, &leconf
->iface_tree
) {
809 memset(&ictl
, 0, sizeof(ictl
));
810 ictl
.active_v4
= (iface
->ipv4
.state
== IF_STA_ACTIVE
);
811 ictl
.active_v6
= (iface
->ipv6
.state
== IF_STA_ACTIVE
);
813 if (!ictl
.active_v4
&& !ictl
.active_v6
)
816 strlcpy(ictl
.name
, iface
->name
, sizeof(ictl
.name
));
817 if (LIST_EMPTY(&iface
->ipv4
.adj_list
) &&
818 LIST_EMPTY(&iface
->ipv6
.adj_list
))
820 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISC_IFACE
, 0, 0,
821 -1, &ictl
, sizeof(ictl
));
823 LIST_FOREACH(adj
, &iface
->ipv4
.adj_list
, ia_entry
) {
824 actl
= adj_to_ctl(adj
);
825 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISC_ADJ
,
826 0, 0, -1, actl
, sizeof(struct ctl_adj
));
828 LIST_FOREACH(adj
, &iface
->ipv6
.adj_list
, ia_entry
) {
829 actl
= adj_to_ctl(adj
);
830 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISC_ADJ
,
831 0, 0, -1, actl
, sizeof(struct ctl_adj
));
835 RB_FOREACH(tnbr
, tnbr_head
, &leconf
->tnbr_tree
) {
836 memset(&tctl
, 0, sizeof(tctl
));
838 tctl
.addr
= tnbr
->addr
;
839 if (tnbr
->adj
== NULL
)
842 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISC_TNBR
, 0, 0,
843 -1, &tctl
, sizeof(tctl
));
845 if (tnbr
->adj
== NULL
)
848 actl
= adj_to_ctl(tnbr
->adj
);
849 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_DISC_ADJ
, 0, 0,
850 -1, actl
, sizeof(struct ctl_adj
));
853 imsg_compose_event(&c
->iev
, IMSG_CTL_END
, 0, 0, -1, NULL
, 0);
857 ldpe_nbr_ctl(struct ctl_conn
*c
)
860 struct ctl_adj
*actl
;
862 struct ctl_nbr
*nctl
;
864 RB_FOREACH(nbr
, nbr_addr_head
, &nbrs_by_addr
) {
865 if (nbr
->state
== NBR_STA_PRESENT
)
868 nctl
= nbr_to_ctl(nbr
);
869 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_NBR
, 0, 0, -1, nctl
,
870 sizeof(struct ctl_nbr
));
872 LIST_FOREACH(adj
, &nbr
->adj_list
, nbr_entry
) {
873 actl
= adj_to_ctl(adj
);
874 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_NBR_DISC
,
875 0, 0, -1, actl
, sizeof(struct ctl_adj
));
878 imsg_compose_event(&c
->iev
, IMSG_CTL_SHOW_NBR_END
, 0, 0, -1,
881 imsg_compose_event(&c
->iev
, IMSG_CTL_END
, 0, 0, -1, NULL
, 0);
885 mapping_list_add(struct mapping_head
*mh
, struct map
*map
)
887 struct mapping_entry
*me
;
889 me
= calloc(1, sizeof(*me
));
894 TAILQ_INSERT_TAIL(mh
, me
, entry
);
898 mapping_list_clr(struct mapping_head
*mh
)
900 struct mapping_entry
*me
;
902 while ((me
= TAILQ_FIRST(mh
)) != NULL
) {
903 TAILQ_REMOVE(mh
, me
, entry
);