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