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