]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/ldpe.c
pimd: make the json output a bit more machine-friendly
[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;
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(QUAGGA_USER) && defined(QUAGGA_GROUP)
70 .user = QUAGGA_USER,
71 .group = QUAGGA_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 = SIGINT,
92 .handler = &sigint,
93 },
94 {
95 .signal = SIGTERM,
96 .handler = &sigint,
97 },
98 };
99
100 /* label distribution protocol engine */
101 void
102 ldpe(const char *user, const char *group)
103 {
104 struct thread thread;
105
106 leconf = config_new_empty();
107
108 #ifdef HAVE_SETPROCTITLE
109 setproctitle("ldp engine");
110 #endif
111 ldpd_process = PROC_LDP_ENGINE;
112
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)
117 fatal("inet_pton");
118 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
119 fatal("inet_pton");
120 #ifdef __OpenBSD__
121 global.pfkeysock = pfkey_init();
122 #endif
123
124 /* drop privileges */
125 if (user)
126 ldpe_privs.user = user;
127 if (group)
128 ldpe_privs.group = group;
129 zprivs_init(&ldpe_privs);
130
131 if (control_init() == -1)
132 fatalx("control socket setup failed");
133
134 #ifdef HAVE_PLEDGE
135 if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
136 fatal("pledge");
137 #endif
138
139 master = thread_master_create();
140 accept_init();
141
142 /* setup signal handler */
143 signal_init(master, array_size(ldpe_signals), ldpe_signals);
144
145 /* setup pipe and event handler to the parent process */
146 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
147 fatal(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;
154
155 #ifdef __OpenBSD__
156 if (sysdep.no_pfkey == 0)
157 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
158 NULL, global.pfkeysock);
159 #endif
160
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;
168
169 /* listen on ldpd control socket */
170 TAILQ_INIT(&ctl_conns);
171 control_listen();
172
173 if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
174 fatal(__func__);
175
176 /* Fetch next active thread. */
177 while (thread_fetch(master, &thread))
178 thread_call(&thread);
179 }
180
181 static void
182 ldpe_shutdown(void)
183 {
184 struct if_addr *if_addr;
185 struct adj *adj;
186
187 /* close pipes */
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);
194
195 control_cleanup();
196 config_clear(leconf);
197
198 #ifdef __OpenBSD__
199 if (sysdep.no_pfkey == 0) {
200 THREAD_READ_OFF(pfkey_ev);
201 close(global.pfkeysock);
202 }
203 #endif
204 ldpe_close_sockets(AF_INET);
205 ldpe_close_sockets(AF_INET6);
206
207 /* remove addresses from global list */
208 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
209 LIST_REMOVE(if_addr, entry);
210 free(if_addr);
211 }
212 while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
213 adj_del(adj, S_SHUTDOWN);
214
215 /* clean up */
216 free(iev_lde);
217 free(iev_main);
218 free(pkt_ptr);
219
220 log_info("ldp engine exiting");
221 exit(0);
222 }
223
224 /* imesg */
225 int
226 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
227 {
228 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
229 }
230
231 int
232 ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
233 uint16_t datalen)
234 {
235 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
236 data, datalen));
237 }
238
239 /* ARGSUSED */
240 static int
241 ldpe_dispatch_main(struct thread *thread)
242 {
243 static struct ldpd_conf *nconf;
244 struct iface *niface;
245 struct tnbr *ntnbr;
246 struct nbr_params *nnbrp;
247 static struct l2vpn *nl2vpn;
248 struct l2vpn_if *nlif;
249 struct l2vpn_pw *npw;
250 struct imsg imsg;
251 int fd = THREAD_FD(thread);
252 struct imsgev *iev = THREAD_ARG(thread);
253 struct imsgbuf *ibuf = &iev->ibuf;
254 struct iface *iface = NULL;
255 struct kif *kif;
256 int af;
257 enum socket_type *socket_type;
258 static int disc_socket = -1;
259 static int edisc_socket = -1;
260 static int session_socket = -1;
261 struct nbr *nbr;
262 #ifdef __OpenBSD__
263 struct nbr_params *nbrp;
264 #endif
265 int n, shut = 0;
266
267 iev->ev_read = NULL;
268
269 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
270 fatal("imsg_read error");
271 if (n == 0) /* connection closed */
272 shut = 1;
273
274 for (;;) {
275 if ((n = imsg_get(ibuf, &imsg)) == -1)
276 fatal("ldpe_dispatch_main: imsg_get error");
277 if (n == 0)
278 break;
279
280 switch (imsg.hdr.type) {
281 case IMSG_IFSTATUS:
282 if (imsg.hdr.len != IMSG_HEADER_SIZE +
283 sizeof(struct kif))
284 fatalx("IFSTATUS imsg with wrong len");
285 kif = imsg.data;
286
287 iface = if_lookup_name(leconf, kif->ifname);
288 if (!iface)
289 break;
290
291 if_update_info(iface, kif);
292 if_update(iface, AF_UNSPEC);
293 break;
294 case IMSG_NEWADDR:
295 if (imsg.hdr.len != IMSG_HEADER_SIZE +
296 sizeof(struct kaddr))
297 fatalx("NEWADDR imsg with wrong len");
298
299 if_addr_add(imsg.data);
300 break;
301 case IMSG_DELADDR:
302 if (imsg.hdr.len != IMSG_HEADER_SIZE +
303 sizeof(struct kaddr))
304 fatalx("DELADDR imsg with wrong len");
305
306 if_addr_del(imsg.data);
307 break;
308 case IMSG_SOCKET_IPC:
309 if (iev_lde) {
310 log_warnx("%s: received unexpected imsg fd "
311 "to lde", __func__);
312 break;
313 }
314 if ((fd = imsg.fd) == -1) {
315 log_warnx("%s: expected to receive imsg fd to "
316 "lde but didn't receive any", __func__);
317 break;
318 }
319
320 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
321 fatal(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;
328 break;
329 case IMSG_CLOSE_SOCKETS:
330 af = imsg.hdr.peerid;
331
332 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
333 if (nbr->af != af)
334 continue;
335 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
336 #ifdef __OpenBSD__
337 pfkey_remove(nbr);
338 #endif
339 }
340 ldpe_close_sockets(af);
341 if_update_all(af);
342 tnbr_update_all(af);
343
344 disc_socket = -1;
345 edisc_socket = -1;
346 session_socket = -1;
347 if ((ldp_af_conf_get(leconf, af))->flags &
348 F_LDPD_AF_ENABLED)
349 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
350 af, NULL, 0);
351 break;
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;
357
358 switch (*socket_type) {
359 case LDP_SOCKET_DISC:
360 disc_socket = imsg.fd;
361 break;
362 case LDP_SOCKET_EDISC:
363 edisc_socket = imsg.fd;
364 break;
365 case LDP_SOCKET_SESSION:
366 session_socket = imsg.fd;
367 break;
368 }
369 break;
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)
375 close(disc_socket);
376 if (edisc_socket != -1)
377 close(edisc_socket);
378 if (session_socket != -1)
379 close(session_socket);
380 break;
381 }
382
383 ldpe_setup_sockets(af, disc_socket, edisc_socket,
384 session_socket);
385 if_update_all(af);
386 tnbr_update_all(af);
387 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
388 if (nbr->af != af)
389 continue;
390 nbr->laddr = (ldp_af_conf_get(leconf,
391 af))->trans_addr;
392 #ifdef __OpenBSD__
393 nbrp = nbr_params_find(leconf, nbr->id);
394 if (nbrp && pfkey_establish(nbr, nbrp) == -1)
395 fatalx("pfkey setup failed");
396 #endif
397 if (nbr_session_active_role(nbr))
398 nbr_establish_connection(nbr);
399 }
400 break;
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);
407 }
408 if_update_all(AF_UNSPEC);
409 tnbr_update_all(AF_UNSPEC);
410 break;
411 case IMSG_RECONF_CONF:
412 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
413 NULL)
414 fatal(NULL);
415 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
416
417 LIST_INIT(&nconf->iface_list);
418 LIST_INIT(&nconf->tnbr_list);
419 LIST_INIT(&nconf->nbrp_list);
420 LIST_INIT(&nconf->l2vpn_list);
421 break;
422 case IMSG_RECONF_IFACE:
423 if ((niface = malloc(sizeof(struct iface))) == NULL)
424 fatal(NULL);
425 memcpy(niface, imsg.data, sizeof(struct iface));
426
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;
432
433 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
434 break;
435 case IMSG_RECONF_TNBR:
436 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
437 fatal(NULL);
438 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
439
440 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
441 break;
442 case IMSG_RECONF_NBRP:
443 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
444 fatal(NULL);
445 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
446
447 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
448 break;
449 case IMSG_RECONF_L2VPN:
450 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
451 fatal(NULL);
452 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
453
454 LIST_INIT(&nl2vpn->if_list);
455 LIST_INIT(&nl2vpn->pw_list);
456 LIST_INIT(&nl2vpn->pw_inactive_list);
457
458 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
459 break;
460 case IMSG_RECONF_L2VPN_IF:
461 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
462 fatal(NULL);
463 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
464
465 nlif->l2vpn = nl2vpn;
466 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
467 break;
468 case IMSG_RECONF_L2VPN_PW:
469 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
470 fatal(NULL);
471 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
472
473 npw->l2vpn = nl2vpn;
474 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
475 break;
476 case IMSG_RECONF_L2VPN_IPW:
477 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
478 fatal(NULL);
479 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
480
481 npw->l2vpn = nl2vpn;
482 LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry);
483 break;
484 case IMSG_RECONF_END:
485 merge_config(leconf, nconf);
486 nconf = NULL;
487 global.conf_seqnum++;
488 break;
489 case IMSG_CTL_END:
490 control_imsg_relay(&imsg);
491 break;
492 case IMSG_DEBUG_UPDATE:
493 if (imsg.hdr.len != IMSG_HEADER_SIZE +
494 sizeof(ldp_debug)) {
495 log_warnx("%s: wrong imsg len", __func__);
496 break;
497 }
498 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
499 break;
500 default:
501 log_debug("ldpe_dispatch_main: error handling imsg %d",
502 imsg.hdr.type);
503 break;
504 }
505 imsg_free(&imsg);
506 }
507 if (!shut)
508 imsg_event_add(iev);
509 else {
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);
513 ldpe_shutdown();
514 }
515
516 return (0);
517 }
518
519 /* ARGSUSED */
520 static int
521 ldpe_dispatch_lde(struct thread *thread)
522 {
523 struct imsgev *iev = THREAD_ARG(thread);
524 struct imsgbuf *ibuf = &iev->ibuf;
525 struct imsg imsg;
526 struct map map;
527 struct notify_msg nm;
528 int n, shut = 0;
529 struct nbr *nbr = NULL;
530
531 iev->ev_read = NULL;
532
533 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
534 fatal("imsg_read error");
535 if (n == 0) /* connection closed */
536 shut = 1;
537
538 for (;;) {
539 if ((n = imsg_get(ibuf, &imsg)) == -1)
540 fatal("ldpe_dispatch_lde: imsg_get error");
541 if (n == 0)
542 break;
543
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));
552
553 nbr = nbr_find_peerid(imsg.hdr.peerid);
554 if (nbr == NULL) {
555 log_debug("ldpe_dispatch_lde: cannot find "
556 "neighbor");
557 break;
558 }
559 if (nbr->state != NBR_STA_OPER)
560 break;
561
562 switch (imsg.hdr.type) {
563 case IMSG_MAPPING_ADD:
564 mapping_list_add(&nbr->mapping_list, &map);
565 break;
566 case IMSG_RELEASE_ADD:
567 mapping_list_add(&nbr->release_list, &map);
568 break;
569 case IMSG_REQUEST_ADD:
570 mapping_list_add(&nbr->request_list, &map);
571 break;
572 case IMSG_WITHDRAW_ADD:
573 mapping_list_add(&nbr->withdraw_list, &map);
574 break;
575 }
576 break;
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);
582 if (nbr == NULL) {
583 log_debug("ldpe_dispatch_lde: cannot find "
584 "neighbor");
585 break;
586 }
587 if (nbr->state != NBR_STA_OPER)
588 break;
589
590 switch (imsg.hdr.type) {
591 case IMSG_MAPPING_ADD_END:
592 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
593 &nbr->mapping_list);
594 break;
595 case IMSG_RELEASE_ADD_END:
596 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
597 &nbr->release_list);
598 break;
599 case IMSG_REQUEST_ADD_END:
600 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
601 &nbr->request_list);
602 break;
603 case IMSG_WITHDRAW_ADD_END:
604 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
605 &nbr->withdraw_list);
606 break;
607 }
608 break;
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));
613
614 nbr = nbr_find_peerid(imsg.hdr.peerid);
615 if (nbr == NULL) {
616 log_debug("ldpe_dispatch_lde: cannot find "
617 "neighbor");
618 break;
619 }
620 if (nbr->state != NBR_STA_OPER)
621 break;
622
623 send_notification_full(nbr->tcp, &nm);
624 break;
625 case IMSG_CTL_END:
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);
630 break;
631 default:
632 log_debug("ldpe_dispatch_lde: error handling imsg %d",
633 imsg.hdr.type);
634 break;
635 }
636 imsg_free(&imsg);
637 }
638 if (!shut)
639 imsg_event_add(iev);
640 else {
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);
644 ldpe_shutdown();
645 }
646
647 return (0);
648 }
649
650 #ifdef __OpenBSD__
651 /* ARGSUSED */
652 static int
653 ldpe_dispatch_pfkey(struct thread *thread)
654 {
655 int fd = THREAD_FD(thread);
656
657 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
658 NULL, global.pfkeysock);
659
660 if (pfkey_read(fd, NULL) == -1)
661 fatal("pfkey_read failed, exiting...");
662
663 return (0);
664 }
665 #endif /* __OpenBSD__ */
666
667 static void
668 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
669 int session_socket)
670 {
671 struct ldpd_af_global *af_global;
672
673 af_global = ldp_af_global_get(&global, af);
674
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);
679
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);
684
685 /* session socket */
686 af_global->ldp_session_socket = session_socket;
687 accept_add(af_global->ldp_session_socket, session_accept, NULL);
688 }
689
690 static void
691 ldpe_close_sockets(int af)
692 {
693 struct ldpd_af_global *af_global;
694
695 af_global = ldp_af_global_get(&global, af);
696
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;
702 }
703
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;
709 }
710
711 /* session socket */
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;
716 }
717 }
718
719 void
720 ldpe_reset_nbrs(int af)
721 {
722 struct nbr *nbr;
723
724 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
725 if (nbr->af == af)
726 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
727 }
728 }
729
730 void
731 ldpe_reset_ds_nbrs(void)
732 {
733 struct nbr *nbr;
734
735 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
736 if (nbr->ds_tlv)
737 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
738 }
739 }
740
741 void
742 ldpe_remove_dynamic_tnbrs(int af)
743 {
744 struct tnbr *tnbr, *safe;
745
746 LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
747 if (tnbr->af != af)
748 continue;
749
750 tnbr->flags &= ~F_TNBR_DYNAMIC;
751 tnbr_check(tnbr);
752 }
753 }
754
755 void
756 ldpe_stop_init_backoff(int af)
757 {
758 struct nbr *nbr;
759
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);
764 }
765 }
766 }
767
768 static void
769 ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
770 {
771 struct iface *iface;
772 struct iface_af *ia;
773 struct ctl_iface *ictl;
774
775 LIST_FOREACH(iface, &leconf->iface_list, entry) {
776 if (idx == 0 || idx == iface->ifindex) {
777 ia = iface_af_get(iface, af);
778 if (!ia->enabled)
779 continue;
780
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));
785 }
786 }
787 }
788
789 void
790 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
791 {
792 ldpe_iface_af_ctl(c, AF_INET, idx);
793 ldpe_iface_af_ctl(c, AF_INET6, idx);
794 }
795
796 void
797 ldpe_adj_ctl(struct ctl_conn *c)
798 {
799 struct iface *iface;
800 struct tnbr *tnbr;
801 struct adj *adj;
802 struct ctl_adj *actl;
803 struct ctl_disc_if ictl;
804 struct ctl_disc_tnbr tctl;
805
806 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
807
808 LIST_FOREACH(iface, &leconf->iface_list, entry) {
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);
812
813 if (!ictl.active_v4 && !ictl.active_v6)
814 continue;
815
816 strlcpy(ictl.name, iface->name, sizeof(ictl.name));
817 if (LIST_EMPTY(&iface->ipv4.adj_list) &&
818 LIST_EMPTY(&iface->ipv6.adj_list))
819 ictl.no_adj = 1;
820 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
821 -1, &ictl, sizeof(ictl));
822
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));
827 }
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));
832 }
833 }
834
835 LIST_FOREACH(tnbr, &leconf->tnbr_list, entry) {
836 memset(&tctl, 0, sizeof(tctl));
837 tctl.af = tnbr->af;
838 tctl.addr = tnbr->addr;
839 if (tnbr->adj == NULL)
840 tctl.no_adj = 1;
841
842 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0,
843 -1, &tctl, sizeof(tctl));
844
845 if (tnbr->adj == NULL)
846 continue;
847
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));
851 }
852
853 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
854 }
855
856 void
857 ldpe_nbr_ctl(struct ctl_conn *c)
858 {
859 struct adj *adj;
860 struct ctl_adj *actl;
861 struct nbr *nbr;
862 struct ctl_nbr *nctl;
863
864 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
865 if (nbr->state == NBR_STA_PRESENT)
866 continue;
867
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));
871
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));
876 }
877
878 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1,
879 NULL, 0);
880 }
881 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
882 }
883
884 void
885 mapping_list_add(struct mapping_head *mh, struct map *map)
886 {
887 struct mapping_entry *me;
888
889 me = calloc(1, sizeof(*me));
890 if (me == NULL)
891 fatal(__func__);
892 me->map = *map;
893
894 TAILQ_INSERT_TAIL(mh, me, entry);
895 }
896
897 void
898 mapping_list_clr(struct mapping_head *mh)
899 {
900 struct mapping_entry *me;
901
902 while ((me = TAILQ_FIRST(mh)) != NULL) {
903 TAILQ_REMOVE(mh, me, entry);
904 free(me);
905 }
906 }