]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/ldpe.c
*: Add camelCase JSON keys in addition to PascalCase
[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 frr_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 /* no frr_config_fork() here, allow frr_pthread to create threads */
115 frr_is_after_fork = true;
116
117 /* setup signal handler */
118 signal_init(master, array_size(ldpe_signals), ldpe_signals);
119
120 /* setup pipes and event handlers to the parent process */
121 if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
122 fatal(NULL);
123 imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
124 iev_main->handler_read = ldpe_dispatch_main;
125 thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd,
126 &iev_main->ev_read);
127 iev_main->handler_write = ldp_write_handler;
128
129 memset(&iev_main_data, 0, sizeof(iev_main_data));
130 iev_main_sync = &iev_main_data;
131 imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
132
133 /* create base configuration */
134 leconf = config_new_empty();
135
136 struct thread thread;
137 while (thread_fetch(master, &thread))
138 thread_call(&thread);
139
140 /* NOTREACHED */
141 return;
142 }
143
144 void
145 ldpe_init(struct ldpd_init *init)
146 {
147 #ifdef __OpenBSD__
148 /* This socket must be open before dropping privileges. */
149 global.pfkeysock = pfkey_init();
150 if (sysdep.no_pfkey == 0) {
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 thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd,
379 &iev_lde->ev_read);
380 iev_lde->handler_write = ldp_write_handler;
381 iev_lde->ev_write = NULL;
382 break;
383 case IMSG_INIT:
384 if (imsg.hdr.len != IMSG_HEADER_SIZE +
385 sizeof(struct ldpd_init))
386 fatalx("INIT imsg with wrong len");
387
388 memcpy(&init, imsg.data, sizeof(init));
389 ldpe_init(&init);
390 break;
391 case IMSG_AGENTX_ENABLED:
392 ldp_agentx_enabled();
393 break;
394 case IMSG_CLOSE_SOCKETS:
395 af = imsg.hdr.peerid;
396
397 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
398 if (nbr->af != af)
399 continue;
400 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
401 #ifdef __OpenBSD__
402 pfkey_remove(nbr);
403 #endif
404 nbr->auth.method = AUTH_NONE;
405 }
406 ldpe_close_sockets(af);
407 if_update_all(af);
408 tnbr_update_all(af);
409
410 disc_socket = -1;
411 edisc_socket = -1;
412 session_socket = -1;
413 if ((ldp_af_conf_get(leconf, af))->flags &
414 F_LDPD_AF_ENABLED)
415 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
416 af, NULL, 0);
417 break;
418 case IMSG_SOCKET_NET:
419 if (imsg.hdr.len != IMSG_HEADER_SIZE +
420 sizeof(enum socket_type))
421 fatalx("SOCKET_NET imsg with wrong len");
422 socket_type = imsg.data;
423
424 switch (*socket_type) {
425 case LDP_SOCKET_DISC:
426 disc_socket = imsg.fd;
427 break;
428 case LDP_SOCKET_EDISC:
429 edisc_socket = imsg.fd;
430 break;
431 case LDP_SOCKET_SESSION:
432 session_socket = imsg.fd;
433 break;
434 }
435 break;
436 case IMSG_SETUP_SOCKETS:
437 af = imsg.hdr.peerid;
438 if (disc_socket == -1 || edisc_socket == -1 ||
439 session_socket == -1) {
440 if (disc_socket != -1)
441 close(disc_socket);
442 if (edisc_socket != -1)
443 close(edisc_socket);
444 if (session_socket != -1)
445 close(session_socket);
446 break;
447 }
448
449 ldpe_setup_sockets(af, disc_socket, edisc_socket,
450 session_socket);
451 if_update_all(af);
452 tnbr_update_all(af);
453 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
454 if (nbr->af != af)
455 continue;
456 nbr->laddr = (ldp_af_conf_get(leconf,
457 af))->trans_addr;
458 #ifdef __OpenBSD__
459 nbrp = nbr_params_find(leconf, nbr->id);
460 if (nbrp) {
461 nbr->auth.method = nbrp->auth.method;
462 if (pfkey_establish(nbr, nbrp) == -1)
463 fatalx("pfkey setup failed");
464 }
465 #endif
466 if (nbr_session_active_role(nbr))
467 nbr_establish_connection(nbr);
468 }
469 break;
470 case IMSG_RTRID_UPDATE:
471 memcpy(&global.rtr_id, imsg.data,
472 sizeof(global.rtr_id));
473 if (leconf->rtr_id.s_addr == INADDR_ANY) {
474 ldpe_reset_nbrs(AF_UNSPEC);
475 }
476 if_update_all(AF_UNSPEC);
477 tnbr_update_all(AF_UNSPEC);
478 break;
479 case IMSG_RECONF_CONF:
480 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
481 NULL)
482 fatal(NULL);
483 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
484
485 RB_INIT(iface_head, &nconf->iface_tree);
486 RB_INIT(tnbr_head, &nconf->tnbr_tree);
487 RB_INIT(nbrp_head, &nconf->nbrp_tree);
488 RB_INIT(l2vpn_head, &nconf->l2vpn_tree);
489 break;
490 case IMSG_RECONF_IFACE:
491 if ((niface = malloc(sizeof(struct iface))) == NULL)
492 fatal(NULL);
493 memcpy(niface, imsg.data, sizeof(struct iface));
494
495 RB_INSERT(iface_head, &nconf->iface_tree, niface);
496 break;
497 case IMSG_RECONF_TNBR:
498 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
499 fatal(NULL);
500 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
501
502 RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
503 break;
504 case IMSG_RECONF_NBRP:
505 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
506 fatal(NULL);
507 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
508
509 RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
510 break;
511 case IMSG_RECONF_L2VPN:
512 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
513 fatal(NULL);
514 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
515
516 RB_INIT(l2vpn_if_head, &nl2vpn->if_tree);
517 RB_INIT(l2vpn_pw_head, &nl2vpn->pw_tree);
518 RB_INIT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree);
519
520 RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
521 break;
522 case IMSG_RECONF_L2VPN_IF:
523 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
524 fatal(NULL);
525 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
526
527 RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
528 break;
529 case IMSG_RECONF_L2VPN_PW:
530 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
531 fatal(NULL);
532 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
533
534 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
535 break;
536 case IMSG_RECONF_L2VPN_IPW:
537 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
538 fatal(NULL);
539 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
540
541 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
542 break;
543 case IMSG_RECONF_END:
544 merge_config(leconf, nconf);
545 ldp_clear_config(nconf);
546 nconf = NULL;
547 global.conf_seqnum++;
548 break;
549 case IMSG_CTL_END:
550 control_imsg_relay(&imsg);
551 break;
552 case IMSG_DEBUG_UPDATE:
553 if (imsg.hdr.len != IMSG_HEADER_SIZE +
554 sizeof(ldp_debug)) {
555 log_warnx("%s: wrong imsg len", __func__);
556 break;
557 }
558 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
559 break;
560 case IMSG_FILTER_UPDATE:
561 if (imsg.hdr.len != IMSG_HEADER_SIZE +
562 sizeof(struct ldp_access)) {
563 log_warnx("%s: wrong imsg len", __func__);
564 break;
565 }
566 laccess = imsg.data;
567 ldpe_check_filter_af(AF_INET, &leconf->ipv4,
568 laccess->name);
569 ldpe_check_filter_af(AF_INET6, &leconf->ipv6,
570 laccess->name);
571 break;
572 case IMSG_LDP_SYNC_IF_STATE_REQUEST:
573 if (imsg.hdr.len != IMSG_HEADER_SIZE +
574 sizeof(struct ldp_igp_sync_if_state_req)) {
575 log_warnx("%s: wrong imsg len", __func__);
576 break;
577 }
578 ldp_sync_if_state_req = imsg.data;
579 ldp_sync_fsm_state_req(ldp_sync_if_state_req);
580 break;
581 case IMSG_RLFA_REG:
582 if (imsg.hdr.len != IMSG_HEADER_SIZE +
583 sizeof(struct zapi_rlfa_request)) {
584 log_warnx("%s: wrong imsg len", __func__);
585 break;
586 }
587 rlfa_req = imsg.data;
588
589 rnode = rlfa_node_find(&rlfa_req->destination,
590 rlfa_req->pq_address);
591 if (!rnode)
592 rnode = rlfa_node_new(&rlfa_req->destination,
593 rlfa_req->pq_address);
594 rclient = rlfa_client_find(rnode, &rlfa_req->igp);
595 if (rclient)
596 /* RLFA already registered - do nothing */
597 break;
598 rclient = rlfa_client_new(rnode, &rlfa_req->igp);
599 ldpe_rlfa_init(rclient);
600 break;
601 case IMSG_RLFA_UNREG_ALL:
602 if (imsg.hdr.len != IMSG_HEADER_SIZE +
603 sizeof(struct zapi_rlfa_igp)) {
604 log_warnx("%s: wrong imsg len", __func__);
605 break;
606 }
607 rlfa_igp = imsg.data;
608
609 RB_FOREACH_SAFE (rnode, ldp_rlfa_node_head,
610 &rlfa_node_tree, rntmp) {
611 rclient = rlfa_client_find(rnode, rlfa_igp);
612 if (!rclient)
613 continue;
614
615 ldpe_rlfa_exit(rclient);
616 rlfa_client_del(rclient);
617 }
618 break;
619 default:
620 log_debug("ldpe_dispatch_main: error handling imsg %d",
621 imsg.hdr.type);
622 break;
623 }
624 imsg_free(&imsg);
625 }
626 if (!shut)
627 imsg_event_add(iev);
628 else {
629 /* this pipe is dead, so remove the event handlers and exit */
630 thread_cancel(&iev->ev_read);
631 thread_cancel(&iev->ev_write);
632 ldpe_shutdown();
633 }
634
635 return (0);
636 }
637
638 /* ARGSUSED */
639 static int
640 ldpe_dispatch_lde(struct thread *thread)
641 {
642 struct imsgev *iev = THREAD_ARG(thread);
643 struct imsgbuf *ibuf = &iev->ibuf;
644 struct imsg imsg;
645 struct map *map;
646 struct notify_msg *nm;
647 struct nbr *nbr;
648 int n, shut = 0;
649
650 iev->ev_read = NULL;
651
652 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
653 fatal("imsg_read error");
654 if (n == 0) /* connection closed */
655 shut = 1;
656
657 for (;;) {
658 if ((n = imsg_get(ibuf, &imsg)) == -1)
659 fatal("ldpe_dispatch_lde: imsg_get error");
660 if (n == 0)
661 break;
662
663 switch (imsg.hdr.type) {
664 case IMSG_MAPPING_ADD:
665 case IMSG_RELEASE_ADD:
666 case IMSG_REQUEST_ADD:
667 case IMSG_WITHDRAW_ADD:
668 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
669 sizeof(struct map))
670 fatalx("invalid size of map request");
671 map = imsg.data;
672
673 nbr = nbr_find_peerid(imsg.hdr.peerid);
674 if (nbr == NULL)
675 break;
676 if (nbr->state != NBR_STA_OPER)
677 break;
678
679 switch (imsg.hdr.type) {
680 case IMSG_MAPPING_ADD:
681 mapping_list_add(&nbr->mapping_list, map);
682 break;
683 case IMSG_RELEASE_ADD:
684 mapping_list_add(&nbr->release_list, map);
685 break;
686 case IMSG_REQUEST_ADD:
687 mapping_list_add(&nbr->request_list, map);
688 break;
689 case IMSG_WITHDRAW_ADD:
690 mapping_list_add(&nbr->withdraw_list, map);
691 break;
692 }
693 break;
694 case IMSG_MAPPING_ADD_END:
695 case IMSG_RELEASE_ADD_END:
696 case IMSG_REQUEST_ADD_END:
697 case IMSG_WITHDRAW_ADD_END:
698 nbr = nbr_find_peerid(imsg.hdr.peerid);
699 if (nbr == NULL)
700 break;
701 if (nbr->state != NBR_STA_OPER)
702 break;
703
704 switch (imsg.hdr.type) {
705 case IMSG_MAPPING_ADD_END:
706 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
707 &nbr->mapping_list);
708 break;
709 case IMSG_RELEASE_ADD_END:
710 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
711 &nbr->release_list);
712 break;
713 case IMSG_REQUEST_ADD_END:
714 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
715 &nbr->request_list);
716 break;
717 case IMSG_WITHDRAW_ADD_END:
718 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
719 &nbr->withdraw_list);
720 break;
721 }
722 break;
723 case IMSG_NOTIFICATION_SEND:
724 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
725 sizeof(struct notify_msg))
726 fatalx("invalid size of OE request");
727 nm = imsg.data;
728
729 nbr = nbr_find_peerid(imsg.hdr.peerid);
730 if (nbr == NULL) {
731 log_debug("ldpe_dispatch_lde: cannot find neighbor");
732 break;
733 }
734 if (nbr->state != NBR_STA_OPER)
735 break;
736
737 send_notification_full(nbr->tcp, nm);
738 break;
739 case IMSG_CTL_END:
740 case IMSG_CTL_SHOW_LIB_BEGIN:
741 case IMSG_CTL_SHOW_LIB_RCVD:
742 case IMSG_CTL_SHOW_LIB_SENT:
743 case IMSG_CTL_SHOW_LIB_END:
744 case IMSG_CTL_SHOW_L2VPN_PW:
745 case IMSG_CTL_SHOW_L2VPN_BINDING:
746 control_imsg_relay(&imsg);
747 break;
748 case IMSG_NBR_SHUTDOWN:
749 nbr = nbr_find_peerid(imsg.hdr.peerid);
750 if (nbr == NULL) {
751 log_debug("ldpe_dispatch_lde: cannot find neighbor");
752 break;
753 }
754 if (nbr->state != NBR_STA_OPER)
755 break;
756 session_shutdown(nbr,S_SHUTDOWN,0,0);
757 break;
758 default:
759 log_debug("ldpe_dispatch_lde: error handling imsg %d",
760 imsg.hdr.type);
761 break;
762 }
763 imsg_free(&imsg);
764 }
765 if (!shut)
766 imsg_event_add(iev);
767 else {
768 /* this pipe is dead, so remove the event handlers and exit */
769 thread_cancel(&iev->ev_read);
770 thread_cancel(&iev->ev_write);
771 ldpe_shutdown();
772 }
773
774 return (0);
775 }
776
777 #ifdef __OpenBSD__
778 /* ARGSUSED */
779 static int
780 ldpe_dispatch_pfkey(struct thread *thread)
781 {
782 int fd = THREAD_FD(thread);
783
784 thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock,
785 &pfkey_ev);
786
787 if (pfkey_read(fd, NULL) == -1)
788 fatal("pfkey_read failed, exiting...");
789
790 return (0);
791 }
792 #endif /* __OpenBSD__ */
793
794 static void
795 ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
796 int session_socket)
797 {
798 struct ldpd_af_global *af_global;
799
800 af_global = ldp_af_global_get(&global, af);
801
802 /* discovery socket */
803 af_global->ldp_disc_socket = disc_socket;
804 thread_add_read(master, disc_recv_packet, &af_global->disc_ev, af_global->ldp_disc_socket,
805 &af_global->disc_ev);
806
807 /* extended discovery socket */
808 af_global->ldp_edisc_socket = edisc_socket;
809 thread_add_read(master, disc_recv_packet, &af_global->edisc_ev, af_global->ldp_edisc_socket,
810 &af_global->edisc_ev);
811
812 /* session socket */
813 af_global->ldp_session_socket = session_socket;
814 accept_add(af_global->ldp_session_socket, session_accept, NULL);
815 }
816
817 static void
818 ldpe_close_sockets(int af)
819 {
820 struct ldpd_af_global *af_global;
821
822 af_global = ldp_af_global_get(&global, af);
823
824 /* discovery socket */
825 thread_cancel(&af_global->disc_ev);
826 if (af_global->ldp_disc_socket != -1) {
827 close(af_global->ldp_disc_socket);
828 af_global->ldp_disc_socket = -1;
829 }
830
831 /* extended discovery socket */
832 thread_cancel(&af_global->edisc_ev);
833 if (af_global->ldp_edisc_socket != -1) {
834 close(af_global->ldp_edisc_socket);
835 af_global->ldp_edisc_socket = -1;
836 }
837
838 /* session socket */
839 if (af_global->ldp_session_socket != -1) {
840 accept_del(af_global->ldp_session_socket);
841 close(af_global->ldp_session_socket);
842 af_global->ldp_session_socket = -1;
843 }
844 }
845
846 int
847 ldpe_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen)
848 {
849 return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen);
850 }
851
852 void
853 ldpe_reset_nbrs(int af)
854 {
855 struct nbr *nbr;
856
857 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
858 if (af == AF_UNSPEC || nbr->af == af)
859 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
860 }
861 }
862
863 void
864 ldpe_reset_ds_nbrs(void)
865 {
866 struct nbr *nbr;
867
868 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
869 if (nbr->ds_tlv)
870 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
871 }
872 }
873
874 void
875 ldpe_remove_dynamic_tnbrs(int af)
876 {
877 struct tnbr *tnbr, *safe;
878
879 RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) {
880 if (tnbr->af != af)
881 continue;
882
883 tnbr->flags &= ~F_TNBR_DYNAMIC;
884 tnbr_check(leconf, tnbr);
885 }
886 }
887
888 void
889 ldpe_stop_init_backoff(int af)
890 {
891 struct nbr *nbr;
892
893 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
894 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
895 nbr_stop_idtimer(nbr);
896 nbr_establish_connection(nbr);
897 }
898 }
899 }
900
901 static void
902 ldpe_iface_af_ctl(struct ctl_conn *c, int af, ifindex_t idx)
903 {
904 struct iface *iface;
905 struct iface_af *ia;
906 struct ctl_iface *ictl;
907
908 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
909 if (idx == 0 || idx == iface->ifindex) {
910 ia = iface_af_get(iface, af);
911 if (!ia->enabled)
912 continue;
913
914 ictl = if_to_ctl(ia);
915 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
916 0, 0, -1, ictl, sizeof(struct ctl_iface));
917 }
918 }
919 }
920
921 void
922 ldpe_iface_ctl(struct ctl_conn *c, ifindex_t idx)
923 {
924 ldpe_iface_af_ctl(c, AF_INET, idx);
925 ldpe_iface_af_ctl(c, AF_INET6, idx);
926 }
927
928 void
929 ldpe_adj_ctl(struct ctl_conn *c)
930 {
931 struct adj *adj;
932 struct ctl_adj *actl;
933
934 RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
935 actl = adj_to_ctl(adj);
936 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
937 -1, actl, sizeof(struct ctl_adj));
938 }
939
940 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
941 }
942
943 void
944 ldpe_adj_detail_ctl(struct ctl_conn *c)
945 {
946 struct iface *iface;
947 struct tnbr *tnbr;
948 struct adj *adj;
949 struct ctl_adj *actl;
950 struct ctl_disc_if ictl;
951 struct ctl_disc_tnbr tctl;
952
953 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
954
955 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
956 memset(&ictl, 0, sizeof(ictl));
957 ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
958 ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);
959
960 if (!ictl.active_v4 && !ictl.active_v6)
961 continue;
962
963 strlcpy(ictl.name, iface->name, sizeof(ictl.name));
964 if (RB_EMPTY(ia_adj_head, &iface->ipv4.adj_tree) &&
965 RB_EMPTY(ia_adj_head, &iface->ipv6.adj_tree))
966 ictl.no_adj = 1;
967 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
968 -1, &ictl, sizeof(ictl));
969
970 RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
971 actl = adj_to_ctl(adj);
972 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
973 0, 0, -1, actl, sizeof(struct ctl_adj));
974 }
975 RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
976 actl = adj_to_ctl(adj);
977 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
978 0, 0, -1, actl, sizeof(struct ctl_adj));
979 }
980 }
981
982 RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) {
983 memset(&tctl, 0, sizeof(tctl));
984 tctl.af = tnbr->af;
985 tctl.addr = tnbr->addr;
986 if (tnbr->adj == NULL)
987 tctl.no_adj = 1;
988
989 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0,
990 -1, &tctl, sizeof(tctl));
991
992 if (tnbr->adj == NULL)
993 continue;
994
995 actl = adj_to_ctl(tnbr->adj);
996 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0,
997 -1, actl, sizeof(struct ctl_adj));
998 }
999
1000 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1001 }
1002
1003 void
1004 ldpe_nbr_ctl(struct ctl_conn *c)
1005 {
1006 struct adj *adj;
1007 struct ctl_adj *actl;
1008 struct nbr *nbr;
1009 struct ctl_nbr *nctl;
1010
1011 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
1012 if (nbr->state == NBR_STA_PRESENT)
1013 continue;
1014
1015 nctl = nbr_to_ctl(nbr);
1016 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
1017 sizeof(struct ctl_nbr));
1018
1019 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
1020 actl = adj_to_ctl(adj);
1021 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
1022 0, 0, -1, actl, sizeof(struct ctl_adj));
1023 }
1024
1025 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1,
1026 NULL, 0);
1027 }
1028 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1029 }
1030
1031 void
1032 ldpe_ldp_sync_ctl(struct ctl_conn *c)
1033 {
1034 struct iface *iface;
1035 struct ctl_ldp_sync *ictl;
1036
1037 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
1038 ictl = ldp_sync_to_ctl(iface);
1039 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_LDP_SYNC,
1040 0, 0, -1, ictl, sizeof(struct ctl_ldp_sync));
1041 }
1042 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1043 }
1044
1045 void
1046 mapping_list_add(struct mapping_head *mh, struct map *map)
1047 {
1048 struct mapping_entry *me;
1049
1050 me = calloc(1, sizeof(*me));
1051 if (me == NULL)
1052 fatal(__func__);
1053 me->map = *map;
1054
1055 TAILQ_INSERT_TAIL(mh, me, entry);
1056 }
1057
1058 void
1059 mapping_list_clr(struct mapping_head *mh)
1060 {
1061 struct mapping_entry *me;
1062
1063 while ((me = TAILQ_FIRST(mh)) != NULL) {
1064 TAILQ_REMOVE(mh, me, entry);
1065 assert(me != TAILQ_FIRST(mh));
1066 free(me);
1067 }
1068 }
1069
1070 void
1071 ldpe_check_filter_af(int af, struct ldpd_af_conf *af_conf,
1072 const char *filter_name)
1073 {
1074 if (strcmp(af_conf->acl_thello_accept_from, filter_name) == 0)
1075 ldpe_remove_dynamic_tnbrs(af);
1076 }
1077
1078 void
1079 ldpe_set_config_change_time(void)
1080 {
1081 /* SNMP update time when ever there is a config change */
1082 leconf->config_change_time = time(NULL);
1083 }