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