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