1 /* $OpenBSD: ldpe.c,v 1.88 2024/11/21 13:38:14 claudio Exp $ */
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 <sys/types.h>
23 #include <stdlib.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <pwd.h>
27 #include <unistd.h>
28 #include <arpa/inet.h>
29 #include <errno.h>
30
31 #include "ldpd.h"
32 #include "ldpe.h"
33 #include "lde.h"
34 #include "control.h"
35 #include "log.h"
36
37 static void ldpe_sig_handler(int, short, void *);
38 static __dead void ldpe_shutdown(void);
39 static void ldpe_dispatch_main(int, short, void *);
40 static void ldpe_dispatch_lde(int, short, void *);
41 static void ldpe_dispatch_pfkey(int, short, void *);
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 struct ldpd_sysdep sysdep;
48
49 static struct imsgev *iev_main;
50 static struct imsgev *iev_lde;
51 static struct event pfkey_ev;
52
53 static void
ldpe_sig_handler(int sig,short event,void * bula)54 ldpe_sig_handler(int sig, short event, void *bula)
55 {
56 switch (sig) {
57 case SIGINT:
58 case SIGTERM:
59 ldpe_shutdown();
60 /* NOTREACHED */
61 default:
62 fatalx("unexpected signal");
63 }
64 }
65
66 /* label distribution protocol engine */
67 void
ldpe(int debug,int verbose,char * sockname)68 ldpe(int debug, int verbose, char *sockname)
69 {
70 struct passwd *pw;
71 struct event ev_sigint, ev_sigterm;
72
73 leconf = config_new_empty();
74
75 log_init(debug);
76 log_verbose(verbose);
77
78 setproctitle("ldp engine");
79 ldpd_process = PROC_LDP_ENGINE;
80 log_procname = "ldpe";
81
82 /* create ldpd control socket outside chroot */
83 global.csock = sockname;
84 if (control_init(global.csock) == -1)
85 fatalx("control socket setup failed");
86
87 LIST_INIT(&global.addr_list);
88 LIST_INIT(&global.adj_list);
89 TAILQ_INIT(&global.pending_conns);
90 if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
91 fatal("inet_pton");
92 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
93 fatal("inet_pton");
94 global.pfkeysock = pfkey_init();
95
96 if ((pw = getpwnam(LDPD_USER)) == NULL)
97 fatal("getpwnam");
98
99 if (chroot(pw->pw_dir) == -1)
100 fatal("chroot");
101 if (chdir("/") == -1)
102 fatal("chdir(\"/\")");
103
104 if (setgroups(1, &pw->pw_gid) ||
105 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
106 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
107 fatal("can't drop privileges");
108
109 if (pledge("stdio inet mcast recvfd", NULL) == -1)
110 fatal("pledge");
111
112 event_init();
113 accept_init();
114
115 /* setup signal handler */
116 signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
117 signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
118 signal_add(&ev_sigint, NULL);
119 signal_add(&ev_sigterm, NULL);
120 signal(SIGPIPE, SIG_IGN);
121 signal(SIGHUP, SIG_IGN);
122
123 /* setup pipe and event handler to the parent process */
124 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
125 fatal(NULL);
126 if (imsgbuf_init(&iev_main->ibuf, 3) == -1)
127 fatal(NULL);
128 imsgbuf_allow_fdpass(&iev_main->ibuf);
129 iev_main->handler = ldpe_dispatch_main;
130 iev_main->events = EV_READ;
131 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
132 iev_main->handler, iev_main);
133 event_add(&iev_main->ev, NULL);
134
135 if (sysdep.no_pfkey == 0) {
136 event_set(&pfkey_ev, global.pfkeysock, EV_READ | EV_PERSIST,
137 ldpe_dispatch_pfkey, NULL);
138 event_add(&pfkey_ev, NULL);
139 }
140
141 /* mark sockets as closed */
142 global.ipv4.ldp_disc_socket = -1;
143 global.ipv4.ldp_edisc_socket = -1;
144 global.ipv4.ldp_session_socket = -1;
145 global.ipv6.ldp_disc_socket = -1;
146 global.ipv6.ldp_edisc_socket = -1;
147 global.ipv6.ldp_session_socket = -1;
148
149 /* listen on ldpd control socket */
150 control_listen();
151
152 event_dispatch();
153
154 ldpe_shutdown();
155 }
156
157 static __dead void
ldpe_shutdown(void)158 ldpe_shutdown(void)
159 {
160 struct if_addr *if_addr;
161 struct adj *adj;
162
163 /* close pipes */
164 imsgbuf_write(&iev_lde->ibuf);
165 imsgbuf_clear(&iev_lde->ibuf);
166 close(iev_lde->ibuf.fd);
167 imsgbuf_write(&iev_main->ibuf);
168 imsgbuf_clear(&iev_main->ibuf);
169 close(iev_main->ibuf.fd);
170
171 control_cleanup();
172 config_clear(leconf);
173
174 if (sysdep.no_pfkey == 0) {
175 event_del(&pfkey_ev);
176 close(global.pfkeysock);
177 }
178 ldpe_close_sockets(AF_INET);
179 ldpe_close_sockets(AF_INET6);
180
181 /* remove addresses from global list */
182 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
183 LIST_REMOVE(if_addr, entry);
184 free(if_addr);
185 }
186 while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
187 adj_del(adj, S_SHUTDOWN);
188
189 /* clean up */
190 free(iev_lde);
191 free(iev_main);
192
193 log_info("ldp engine exiting");
194 exit(0);
195 }
196
197 /* imesg */
198 int
ldpe_imsg_compose_parent(int type,pid_t pid,void * data,uint16_t datalen)199 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
200 {
201 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
202 }
203
204 int
ldpe_imsg_compose_lde(int type,uint32_t peerid,pid_t pid,void * data,uint16_t datalen)205 ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
206 uint16_t datalen)
207 {
208 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
209 data, datalen));
210 }
211
212 static void
ldpe_dispatch_main(int fd,short event,void * bula)213 ldpe_dispatch_main(int fd, short event, void *bula)
214 {
215 static struct ldpd_conf *nconf;
216 struct iface *niface;
217 struct tnbr *ntnbr;
218 struct nbr_params *nnbrp;
219 static struct l2vpn *l2vpn, *nl2vpn;
220 struct l2vpn_if *lif = NULL, *nlif;
221 struct l2vpn_pw *npw;
222 struct imsg imsg;
223 struct imsgev *iev = bula;
224 struct imsgbuf *ibuf = &iev->ibuf;
225 struct iface *iface = NULL;
226 struct kif *kif;
227 int af;
228 enum socket_type *socket_type;
229 static int disc_socket = -1;
230 static int edisc_socket = -1;
231 static int session_socket = -1;
232 struct nbr *nbr;
233 int n, shut = 0;
234
235 if (event & EV_READ) {
236 if ((n = imsgbuf_read(ibuf)) == -1)
237 fatal("imsgbuf_read error");
238 if (n == 0) /* connection closed */
239 shut = 1;
240 }
241 if (event & EV_WRITE) {
242 if (imsgbuf_write(ibuf) == -1) {
243 if (errno == EPIPE) /* connection closed */
244 shut = 1;
245 else
246 fatal("imsgbuf_write");
247 }
248 }
249
250 for (;;) {
251 if ((n = imsg_get(ibuf, &imsg)) == -1)
252 fatal("ldpe_dispatch_main: imsg_get error");
253 if (n == 0)
254 break;
255
256 switch (imsg.hdr.type) {
257 case IMSG_IFSTATUS:
258 if (imsg.hdr.len != IMSG_HEADER_SIZE +
259 sizeof(struct kif))
260 fatalx("IFSTATUS imsg with wrong len");
261 kif = imsg.data;
262
263 iface = if_lookup(leconf, kif->ifindex);
264 if (iface) {
265 iface->flags = kif->flags;
266 iface->linkstate = kif->link_state;
267 if_update(iface, AF_UNSPEC);
268 break;
269 }
270
271 LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry) {
272 lif = l2vpn_if_find(l2vpn, kif->ifindex);
273 if (lif) {
274 lif->flags = kif->flags;
275 lif->linkstate = kif->link_state;
276 memcpy(lif->mac, kif->mac,
277 sizeof(lif->mac));
278 l2vpn_if_update(lif);
279 break;
280 }
281 }
282 break;
283 case IMSG_NEWADDR:
284 if (imsg.hdr.len != IMSG_HEADER_SIZE +
285 sizeof(struct kaddr))
286 fatalx("NEWADDR imsg with wrong len");
287
288 if_addr_add(imsg.data);
289 break;
290 case IMSG_DELADDR:
291 if (imsg.hdr.len != IMSG_HEADER_SIZE +
292 sizeof(struct kaddr))
293 fatalx("DELADDR imsg with wrong len");
294
295 if_addr_del(imsg.data);
296 break;
297 case IMSG_SOCKET_IPC:
298 if (iev_lde) {
299 log_warnx("%s: received unexpected imsg fd "
300 "to lde", __func__);
301 break;
302 }
303 if ((fd = imsg_get_fd(&imsg)) == -1) {
304 log_warnx("%s: expected to receive imsg fd to "
305 "lde but didn't receive any", __func__);
306 break;
307 }
308
309 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
310 fatal(NULL);
311 if (imsgbuf_init(&iev_lde->ibuf, fd) == -1)
312 fatal(NULL);
313 iev_lde->handler = ldpe_dispatch_lde;
314 iev_lde->events = EV_READ;
315 event_set(&iev_lde->ev, iev_lde->ibuf.fd,
316 iev_lde->events, iev_lde->handler, iev_lde);
317 event_add(&iev_lde->ev, NULL);
318 break;
319 case IMSG_CLOSE_SOCKETS:
320 af = imsg.hdr.peerid;
321
322 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
323 if (nbr->af != af)
324 continue;
325 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
326 pfkey_remove(nbr);
327 }
328 ldpe_close_sockets(af);
329 if_update_all(af);
330 tnbr_update_all(af);
331
332 disc_socket = -1;
333 edisc_socket = -1;
334 session_socket = -1;
335 if ((ldp_af_conf_get(leconf, af))->flags &
336 F_LDPD_AF_ENABLED)
337 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
338 af, NULL, 0);
339 break;
340 case IMSG_SOCKET_NET:
341 if (imsg.hdr.len != IMSG_HEADER_SIZE +
342 sizeof(enum socket_type))
343 fatalx("SOCKET_NET imsg with wrong len");
344 socket_type = imsg.data;
345
346 switch (*socket_type) {
347 case LDP_SOCKET_DISC:
348 disc_socket = imsg_get_fd(&imsg);
349 break;
350 case LDP_SOCKET_EDISC:
351 edisc_socket = imsg_get_fd(&imsg);
352 break;
353 case LDP_SOCKET_SESSION:
354 session_socket = imsg_get_fd(&imsg);
355 break;
356 }
357 break;
358 case IMSG_SETUP_SOCKETS:
359 af = imsg.hdr.peerid;
360 if (disc_socket == -1 || edisc_socket == -1 ||
361 session_socket == -1) {
362 if (disc_socket != -1)
363 close(disc_socket);
364 if (edisc_socket != -1)
365 close(edisc_socket);
366 if (session_socket != -1)
367 close(session_socket);
368 break;
369 }
370
371 ldpe_setup_sockets(af, disc_socket, edisc_socket,
372 session_socket);
373 if_update_all(af);
374 tnbr_update_all(af);
375 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
376 if (nbr->af != af)
377 continue;
378 nbr->laddr = (ldp_af_conf_get(leconf,
379 af))->trans_addr;
380 if (pfkey_establish(nconf, nbr) == -1)
381 fatalx("pfkey setup failed");
382 if (nbr_session_active_role(nbr))
383 nbr_establish_connection(nbr);
384 }
385 break;
386 case IMSG_RECONF_CONF:
387 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
388 NULL)
389 fatal(NULL);
390 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
391
392 LIST_INIT(&nconf->iface_list);
393 LIST_INIT(&nconf->tnbr_list);
394 LIST_INIT(&nconf->nbrp_list);
395 LIST_INIT(&nconf->l2vpn_list);
396 LIST_INIT(&nconf->auth_list);
397 break;
398 case IMSG_RECONF_IFACE:
399 if ((niface = malloc(sizeof(struct iface))) == NULL)
400 fatal(NULL);
401 memcpy(niface, imsg.data, sizeof(struct iface));
402
403 LIST_INIT(&niface->addr_list);
404 LIST_INIT(&niface->ipv4.adj_list);
405 LIST_INIT(&niface->ipv6.adj_list);
406 niface->ipv4.iface = niface;
407 niface->ipv6.iface = niface;
408
409 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
410 break;
411 case IMSG_RECONF_TNBR:
412 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
413 fatal(NULL);
414 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
415
416 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
417 break;
418 case IMSG_RECONF_NBRP:
419 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
420 fatal(NULL);
421 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
422
423 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry);
424 break;
425 case IMSG_RECONF_L2VPN:
426 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
427 fatal(NULL);
428 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
429
430 LIST_INIT(&nl2vpn->if_list);
431 LIST_INIT(&nl2vpn->pw_list);
432
433 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
434 break;
435 case IMSG_RECONF_L2VPN_IF:
436 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
437 fatal(NULL);
438 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
439
440 nlif->l2vpn = nl2vpn;
441 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
442 break;
443 case IMSG_RECONF_L2VPN_PW:
444 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
445 fatal(NULL);
446 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
447
448 npw->l2vpn = nl2vpn;
449 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
450 break;
451 case IMSG_RECONF_CONF_AUTH: {
452 struct ldp_auth *auth;
453
454 auth = malloc(sizeof(*auth));
455 if (auth == NULL)
456 fatal(NULL);
457
458 memcpy(auth, imsg.data, sizeof(*auth));
459
460 LIST_INSERT_HEAD(&nconf->auth_list, auth, entry);
461 break;
462 }
463
464 case IMSG_RECONF_END:
465 merge_config(leconf, nconf);
466 nconf = NULL;
467 global.conf_seqnum++;
468 break;
469 case IMSG_CTL_KROUTE:
470 case IMSG_CTL_KROUTE_ADDR:
471 case IMSG_CTL_IFINFO:
472 case IMSG_CTL_END:
473 control_imsg_relay(&imsg);
474 break;
475 default:
476 log_debug("ldpe_dispatch_main: error handling imsg %d",
477 imsg.hdr.type);
478 break;
479 }
480 imsg_free(&imsg);
481 }
482 if (!shut)
483 imsg_event_add(iev);
484 else {
485 /* this pipe is dead, so remove the event handler */
486 event_del(&iev->ev);
487 event_loopexit(NULL);
488 }
489 }
490
491 static void
ldpe_dispatch_lde(int fd,short event,void * bula)492 ldpe_dispatch_lde(int fd, short event, void *bula)
493 {
494 struct imsgev *iev = bula;
495 struct imsgbuf *ibuf = &iev->ibuf;
496 struct imsg imsg;
497 struct map map;
498 struct notify_msg nm;
499 int n, shut = 0;
500 struct nbr *nbr = NULL;
501
502 if (event & EV_READ) {
503 if ((n = imsgbuf_read(ibuf)) == -1)
504 fatal("imsgbuf_read error");
505 if (n == 0) /* connection closed */
506 shut = 1;
507 }
508 if (event & EV_WRITE) {
509 if (imsgbuf_write(ibuf) == -1) {
510 if (errno == EPIPE) /* connection closed */
511 shut = 1;
512 else
513 fatal("imsgbuf_write");
514 }
515 }
516
517 for (;;) {
518 if ((n = imsg_get(ibuf, &imsg)) == -1)
519 fatal("ldpe_dispatch_lde: imsg_get error");
520 if (n == 0)
521 break;
522
523 switch (imsg.hdr.type) {
524 case IMSG_MAPPING_ADD:
525 case IMSG_RELEASE_ADD:
526 case IMSG_REQUEST_ADD:
527 case IMSG_WITHDRAW_ADD:
528 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
529 fatalx("invalid size of map request");
530 memcpy(&map, imsg.data, sizeof(map));
531
532 nbr = nbr_find_peerid(imsg.hdr.peerid);
533 if (nbr == NULL) {
534 log_debug("ldpe_dispatch_lde: cannot find "
535 "neighbor");
536 break;
537 }
538 if (nbr->state != NBR_STA_OPER)
539 break;
540
541 switch (imsg.hdr.type) {
542 case IMSG_MAPPING_ADD:
543 mapping_list_add(&nbr->mapping_list, &map);
544 break;
545 case IMSG_RELEASE_ADD:
546 mapping_list_add(&nbr->release_list, &map);
547 break;
548 case IMSG_REQUEST_ADD:
549 mapping_list_add(&nbr->request_list, &map);
550 break;
551 case IMSG_WITHDRAW_ADD:
552 mapping_list_add(&nbr->withdraw_list, &map);
553 break;
554 }
555 break;
556 case IMSG_MAPPING_ADD_END:
557 case IMSG_RELEASE_ADD_END:
558 case IMSG_REQUEST_ADD_END:
559 case IMSG_WITHDRAW_ADD_END:
560 nbr = nbr_find_peerid(imsg.hdr.peerid);
561 if (nbr == NULL) {
562 log_debug("ldpe_dispatch_lde: cannot find "
563 "neighbor");
564 break;
565 }
566 if (nbr->state != NBR_STA_OPER)
567 break;
568
569 switch (imsg.hdr.type) {
570 case IMSG_MAPPING_ADD_END:
571 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
572 &nbr->mapping_list);
573 break;
574 case IMSG_RELEASE_ADD_END:
575 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
576 &nbr->release_list);
577 break;
578 case IMSG_REQUEST_ADD_END:
579 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
580 &nbr->request_list);
581 break;
582 case IMSG_WITHDRAW_ADD_END:
583 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
584 &nbr->withdraw_list);
585 break;
586 }
587 break;
588 case IMSG_NOTIFICATION_SEND:
589 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
590 fatalx("invalid size of OE request");
591 memcpy(&nm, imsg.data, sizeof(nm));
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 send_notification_full(nbr->tcp, &nm);
603 break;
604 case IMSG_CTL_END:
605 case IMSG_CTL_SHOW_LIB:
606 case IMSG_CTL_SHOW_L2VPN_PW:
607 case IMSG_CTL_SHOW_L2VPN_BINDING:
608 control_imsg_relay(&imsg);
609 break;
610 default:
611 log_debug("ldpe_dispatch_lde: error handling imsg %d",
612 imsg.hdr.type);
613 break;
614 }
615 imsg_free(&imsg);
616 }
617 if (!shut)
618 imsg_event_add(iev);
619 else {
620 /* this pipe is dead, so remove the event handler */
621 event_del(&iev->ev);
622 event_loopexit(NULL);
623 }
624 }
625
626 static void
ldpe_dispatch_pfkey(int fd,short event,void * bula)627 ldpe_dispatch_pfkey(int fd, short event, void *bula)
628 {
629 if (event & EV_READ) {
630 if (pfkey_read(fd, NULL) == -1) {
631 fatal("pfkey_read failed, exiting...");
632 }
633 }
634 }
635
636 static void
ldpe_setup_sockets(int af,int disc_socket,int edisc_socket,int session_socket)637 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
638 int session_socket)
639 {
640 struct ldpd_af_global *af_global;
641
642 af_global = ldp_af_global_get(&global, af);
643
644 /* discovery socket */
645 af_global->ldp_disc_socket = disc_socket;
646 event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
647 EV_READ|EV_PERSIST, disc_recv_packet, NULL);
648 event_add(&af_global->disc_ev, NULL);
649
650 /* extended discovery socket */
651 af_global->ldp_edisc_socket = edisc_socket;
652 event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
653 EV_READ|EV_PERSIST, disc_recv_packet, NULL);
654 event_add(&af_global->edisc_ev, NULL);
655
656 /* session socket */
657 af_global->ldp_session_socket = session_socket;
658 accept_add(af_global->ldp_session_socket, session_accept, NULL);
659 }
660
661 static void
ldpe_close_sockets(int af)662 ldpe_close_sockets(int af)
663 {
664 struct ldpd_af_global *af_global;
665
666 af_global = ldp_af_global_get(&global, af);
667
668 /* discovery socket */
669 if (event_initialized(&af_global->disc_ev))
670 event_del(&af_global->disc_ev);
671 if (af_global->ldp_disc_socket != -1) {
672 close(af_global->ldp_disc_socket);
673 af_global->ldp_disc_socket = -1;
674 }
675
676 /* extended discovery socket */
677 if (event_initialized(&af_global->edisc_ev))
678 event_del(&af_global->edisc_ev);
679 if (af_global->ldp_edisc_socket != -1) {
680 close(af_global->ldp_edisc_socket);
681 af_global->ldp_edisc_socket = -1;
682 }
683
684 /* session socket */
685 if (af_global->ldp_session_socket != -1) {
686 accept_del(af_global->ldp_session_socket);
687 close(af_global->ldp_session_socket);
688 af_global->ldp_session_socket = -1;
689 }
690 }
691
692 void
ldpe_reset_nbrs(int af)693 ldpe_reset_nbrs(int af)
694 {
695 struct nbr *nbr;
696
697 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
698 if (nbr->af == af)
699 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
700 }
701 }
702
703 void
ldpe_reset_ds_nbrs(void)704 ldpe_reset_ds_nbrs(void)
705 {
706 struct nbr *nbr;
707
708 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
709 if (nbr->ds_tlv)
710 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
711 }
712 }
713
714 void
ldpe_remove_dynamic_tnbrs(int af)715 ldpe_remove_dynamic_tnbrs(int af)
716 {
717 struct tnbr *tnbr, *safe;
718
719 LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) {
720 if (tnbr->af != af)
721 continue;
722
723 tnbr->flags &= ~F_TNBR_DYNAMIC;
724 tnbr_check(tnbr);
725 }
726 }
727
728 void
ldpe_stop_init_backoff(int af)729 ldpe_stop_init_backoff(int af)
730 {
731 struct nbr *nbr;
732
733 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
734 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
735 nbr_stop_idtimer(nbr);
736 nbr_establish_connection(nbr);
737 }
738 }
739 }
740
741 static void
ldpe_iface_af_ctl(struct ctl_conn * c,int af,unsigned int idx)742 ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
743 {
744 struct iface *iface;
745 struct iface_af *ia;
746 struct ctl_iface *ictl;
747
748 LIST_FOREACH(iface, &leconf->iface_list, entry) {
749 if (idx == 0 || idx == iface->ifindex) {
750 ia = iface_af_get(iface, af);
751 if (!ia->enabled)
752 continue;
753
754 ictl = if_to_ctl(ia);
755 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
756 0, 0, -1, ictl, sizeof(struct ctl_iface));
757 }
758 }
759 }
760
761 void
ldpe_iface_ctl(struct ctl_conn * c,unsigned int idx)762 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
763 {
764 ldpe_iface_af_ctl(c, AF_INET, idx);
765 ldpe_iface_af_ctl(c, AF_INET6, idx);
766 }
767
768 void
ldpe_adj_ctl(struct ctl_conn * c)769 ldpe_adj_ctl(struct ctl_conn *c)
770 {
771 struct nbr *nbr;
772 struct adj *adj;
773 struct ctl_adj *actl;
774
775 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
776 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) {
777 actl = adj_to_ctl(adj);
778 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
779 0, 0, -1, actl, sizeof(struct ctl_adj));
780 }
781 }
782 /* show adjacencies not associated with any neighbor */
783 LIST_FOREACH(adj, &global.adj_list, global_entry) {
784 if (adj->nbr != NULL)
785 continue;
786
787 actl = adj_to_ctl(adj);
788 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
789 -1, actl, sizeof(struct ctl_adj));
790 }
791
792 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
793 }
794
795 void
ldpe_nbr_ctl(struct ctl_conn * c)796 ldpe_nbr_ctl(struct ctl_conn *c)
797 {
798 struct nbr *nbr;
799 struct ctl_nbr *nctl;
800
801 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
802 nctl = nbr_to_ctl(nbr);
803 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
804 sizeof(struct ctl_nbr));
805 }
806 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
807 }
808
809 void
mapping_list_add(struct mapping_head * mh,struct map * map)810 mapping_list_add(struct mapping_head *mh, struct map *map)
811 {
812 struct mapping_entry *me;
813
814 me = calloc(1, sizeof(*me));
815 if (me == NULL)
816 fatal(__func__);
817 me->map = *map;
818
819 TAILQ_INSERT_TAIL(mh, me, entry);
820 }
821
822 void
mapping_list_clr(struct mapping_head * mh)823 mapping_list_clr(struct mapping_head *mh)
824 {
825 struct mapping_entry *me;
826
827 while ((me = TAILQ_FIRST(mh)) != NULL) {
828 TAILQ_REMOVE(mh, me, entry);
829 free(me);
830 }
831 }
832