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