]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldpe.c
ldpd: add synchronous IPC channels
[mirror_frr.git] / ldpd / ldpe.c
CommitLineData
8429abe0
RW
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
eac6e3f0 22#include <zebra.h>
8429abe0
RW
23
24#include "ldpd.h"
25#include "ldpe.h"
26#include "lde.h"
27#include "control.h"
28#include "log.h"
eac6e3f0
RW
29#include "ldp_debug.h"
30
31#include <lib/log.h>
32#include "memory.h"
33#include "privs.h"
34#include "sigevent.h"
35
36static void ldpe_shutdown(void);
37static int ldpe_dispatch_main(struct thread *);
38static int ldpe_dispatch_lde(struct thread *);
39#ifdef __OpenBSD__
40static int ldpe_dispatch_pfkey(struct thread *);
41#endif
8429abe0
RW
42static void ldpe_setup_sockets(int, int, int, int);
43static void ldpe_close_sockets(int);
44static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45
46struct ldpd_conf *leconf;
eac6e3f0 47#ifdef __OpenBSD__
8429abe0 48struct ldpd_sysdep sysdep;
eac6e3f0 49#endif
8429abe0 50
28e8294c 51static struct imsgev *iev_main, *iev_main_sync;
8429abe0 52static struct imsgev *iev_lde;
eac6e3f0
RW
53#ifdef __OpenBSD__
54static struct thread *pfkey_ev;
55#endif
8429abe0 56
eac6e3f0
RW
57/* Master of threads. */
58struct thread_master *master;
59
60/* ldpe privileges */
61static zebra_capabilities_t _caps_p [] =
62{
63 ZCAP_BIND,
64 ZCAP_NET_ADMIN
65};
66
67struct zebra_privs_t ldpe_privs =
68{
b2f36157
DL
69#if defined(FRR_USER) && defined(FRR_GROUP)
70 .user = FRR_USER,
71 .group = FRR_GROUP,
eac6e3f0
RW
72#endif
73#if defined(VTY_GROUP)
74 .vty_group = VTY_GROUP,
75#endif
76 .caps_p = _caps_p,
77 .cap_num_p = array_size(_caps_p),
78 .cap_num_i = 0
79};
80
81/* SIGINT / SIGTERM handler. */
8429abe0 82static void
eac6e3f0 83sigint(void)
8429abe0 84{
eac6e3f0 85 ldpe_shutdown();
8429abe0
RW
86}
87
eac6e3f0
RW
88static struct quagga_signal_t ldpe_signals[] =
89{
90 {
91 .signal = SIGINT,
92 .handler = &sigint,
93 },
94 {
95 .signal = SIGTERM,
96 .handler = &sigint,
97 },
98};
99
8429abe0
RW
100/* label distribution protocol engine */
101void
eac6e3f0 102ldpe(const char *user, const char *group)
8429abe0 103{
eac6e3f0 104 struct thread thread;
8429abe0
RW
105
106 leconf = config_new_empty();
107
eac6e3f0 108#ifdef HAVE_SETPROCTITLE
8429abe0 109 setproctitle("ldp engine");
eac6e3f0 110#endif
8429abe0
RW
111 ldpd_process = PROC_LDP_ENGINE;
112
8429abe0 113 LIST_INIT(&global.addr_list);
057d48bd 114 RB_INIT(&global.adj_tree);
8429abe0
RW
115 TAILQ_INIT(&global.pending_conns);
116 if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
117 fatal("inet_pton");
118 if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
119 fatal("inet_pton");
eac6e3f0 120#ifdef __OpenBSD__
8429abe0 121 global.pfkeysock = pfkey_init();
eac6e3f0 122#endif
8429abe0 123
eac6e3f0
RW
124 /* drop privileges */
125 if (user)
126 ldpe_privs.user = user;
127 if (group)
128 ldpe_privs.group = group;
129 zprivs_init(&ldpe_privs);
8429abe0 130
eac6e3f0
RW
131 if (control_init() == -1)
132 fatalx("control socket setup failed");
8429abe0 133
eac6e3f0 134#ifdef HAVE_PLEDGE
8429abe0
RW
135 if (pledge("stdio cpath inet mcast recvfd", NULL) == -1)
136 fatal("pledge");
eac6e3f0 137#endif
8429abe0 138
eac6e3f0 139 master = thread_master_create();
8429abe0
RW
140 accept_init();
141
142 /* setup signal handler */
eac6e3f0 143 signal_init(master, array_size(ldpe_signals), ldpe_signals);
8429abe0 144
28e8294c
RW
145 /* setup pipes and event handlers to the parent process */
146 if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
8429abe0 147 fatal(NULL);
28e8294c 148 imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
eac6e3f0
RW
149 iev_main->handler_read = ldpe_dispatch_main;
150 iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
151 iev_main, iev_main->ibuf.fd);
152 iev_main->handler_write = ldp_write_handler;
28e8294c
RW
153
154 if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
155 fatal(NULL);
156 imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
eac6e3f0
RW
157
158#ifdef __OpenBSD__
159 if (sysdep.no_pfkey == 0)
160 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
161 NULL, global.pfkeysock);
162#endif
8429abe0
RW
163
164 /* mark sockets as closed */
165 global.ipv4.ldp_disc_socket = -1;
166 global.ipv4.ldp_edisc_socket = -1;
167 global.ipv4.ldp_session_socket = -1;
168 global.ipv6.ldp_disc_socket = -1;
169 global.ipv6.ldp_edisc_socket = -1;
170 global.ipv6.ldp_session_socket = -1;
171
172 /* listen on ldpd control socket */
173 TAILQ_INIT(&ctl_conns);
174 control_listen();
175
176 if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
177 fatal(__func__);
178
eac6e3f0
RW
179 /* Fetch next active thread. */
180 while (thread_fetch(master, &thread))
181 thread_call(&thread);
8429abe0
RW
182}
183
eac6e3f0 184static void
8429abe0
RW
185ldpe_shutdown(void)
186{
187 struct if_addr *if_addr;
188 struct adj *adj;
189
190 /* close pipes */
191 msgbuf_write(&iev_lde->ibuf.w);
192 msgbuf_clear(&iev_lde->ibuf.w);
193 close(iev_lde->ibuf.fd);
194 msgbuf_write(&iev_main->ibuf.w);
195 msgbuf_clear(&iev_main->ibuf.w);
196 close(iev_main->ibuf.fd);
28e8294c
RW
197 msgbuf_clear(&iev_main_sync->ibuf.w);
198 close(iev_main_sync->ibuf.fd);
8429abe0
RW
199
200 control_cleanup();
201 config_clear(leconf);
202
eac6e3f0 203#ifdef __OpenBSD__
8429abe0 204 if (sysdep.no_pfkey == 0) {
eac6e3f0 205 THREAD_READ_OFF(pfkey_ev);
8429abe0
RW
206 close(global.pfkeysock);
207 }
eac6e3f0 208#endif
8429abe0
RW
209 ldpe_close_sockets(AF_INET);
210 ldpe_close_sockets(AF_INET6);
211
212 /* remove addresses from global list */
213 while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) {
214 LIST_REMOVE(if_addr, entry);
215 free(if_addr);
216 }
057d48bd 217 while ((adj = RB_ROOT(&global.adj_tree)) != NULL)
8429abe0
RW
218 adj_del(adj, S_SHUTDOWN);
219
220 /* clean up */
221 free(iev_lde);
222 free(iev_main);
28e8294c 223 free(iev_main_sync);
8429abe0
RW
224 free(pkt_ptr);
225
226 log_info("ldp engine exiting");
227 exit(0);
228}
229
230/* imesg */
231int
232ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
233{
234 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
235}
236
237int
238ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
239 uint16_t datalen)
240{
241 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
242 data, datalen));
243}
244
245/* ARGSUSED */
eac6e3f0
RW
246static int
247ldpe_dispatch_main(struct thread *thread)
8429abe0
RW
248{
249 static struct ldpd_conf *nconf;
250 struct iface *niface;
251 struct tnbr *ntnbr;
252 struct nbr_params *nnbrp;
253 static struct l2vpn *nl2vpn;
254 struct l2vpn_if *nlif;
255 struct l2vpn_pw *npw;
256 struct imsg imsg;
eac6e3f0
RW
257 int fd = THREAD_FD(thread);
258 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
259 struct imsgbuf *ibuf = &iev->ibuf;
260 struct iface *iface = NULL;
261 struct kif *kif;
262 int af;
263 enum socket_type *socket_type;
264 static int disc_socket = -1;
265 static int edisc_socket = -1;
266 static int session_socket = -1;
267 struct nbr *nbr;
eac6e3f0 268#ifdef __OpenBSD__
8429abe0 269 struct nbr_params *nbrp;
eac6e3f0 270#endif
8429abe0
RW
271 int n, shut = 0;
272
eac6e3f0
RW
273 iev->ev_read = NULL;
274
275 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
276 fatal("imsg_read error");
277 if (n == 0) /* connection closed */
278 shut = 1;
8429abe0
RW
279
280 for (;;) {
281 if ((n = imsg_get(ibuf, &imsg)) == -1)
282 fatal("ldpe_dispatch_main: imsg_get error");
283 if (n == 0)
284 break;
285
286 switch (imsg.hdr.type) {
287 case IMSG_IFSTATUS:
288 if (imsg.hdr.len != IMSG_HEADER_SIZE +
289 sizeof(struct kif))
290 fatalx("IFSTATUS imsg with wrong len");
291 kif = imsg.data;
292
eac6e3f0 293 iface = if_lookup_name(leconf, kif->ifname);
8429abe0
RW
294 if (!iface)
295 break;
296
eac6e3f0 297 if_update_info(iface, kif);
8429abe0
RW
298 if_update(iface, AF_UNSPEC);
299 break;
300 case IMSG_NEWADDR:
301 if (imsg.hdr.len != IMSG_HEADER_SIZE +
302 sizeof(struct kaddr))
303 fatalx("NEWADDR imsg with wrong len");
304
305 if_addr_add(imsg.data);
306 break;
307 case IMSG_DELADDR:
308 if (imsg.hdr.len != IMSG_HEADER_SIZE +
309 sizeof(struct kaddr))
310 fatalx("DELADDR imsg with wrong len");
311
312 if_addr_del(imsg.data);
313 break;
314 case IMSG_SOCKET_IPC:
315 if (iev_lde) {
316 log_warnx("%s: received unexpected imsg fd "
317 "to lde", __func__);
318 break;
319 }
320 if ((fd = imsg.fd) == -1) {
321 log_warnx("%s: expected to receive imsg fd to "
322 "lde but didn't receive any", __func__);
323 break;
324 }
325
326 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL)
327 fatal(NULL);
328 imsg_init(&iev_lde->ibuf, fd);
eac6e3f0
RW
329 iev_lde->handler_read = ldpe_dispatch_lde;
330 iev_lde->ev_read = thread_add_read(master,
331 iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd);
332 iev_lde->handler_write = ldp_write_handler;
333 iev_lde->ev_write = NULL;
8429abe0
RW
334 break;
335 case IMSG_CLOSE_SOCKETS:
336 af = imsg.hdr.peerid;
337
338 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
339 if (nbr->af != af)
340 continue;
341 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
eac6e3f0 342#ifdef __OpenBSD__
8429abe0 343 pfkey_remove(nbr);
eac6e3f0 344#endif
8429abe0
RW
345 }
346 ldpe_close_sockets(af);
347 if_update_all(af);
348 tnbr_update_all(af);
349
350 disc_socket = -1;
351 edisc_socket = -1;
352 session_socket = -1;
353 if ((ldp_af_conf_get(leconf, af))->flags &
354 F_LDPD_AF_ENABLED)
355 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
356 af, NULL, 0);
357 break;
358 case IMSG_SOCKET_NET:
359 if (imsg.hdr.len != IMSG_HEADER_SIZE +
360 sizeof(enum socket_type))
361 fatalx("SOCKET_NET imsg with wrong len");
362 socket_type = imsg.data;
363
364 switch (*socket_type) {
365 case LDP_SOCKET_DISC:
366 disc_socket = imsg.fd;
367 break;
368 case LDP_SOCKET_EDISC:
369 edisc_socket = imsg.fd;
370 break;
371 case LDP_SOCKET_SESSION:
372 session_socket = imsg.fd;
373 break;
374 }
375 break;
376 case IMSG_SETUP_SOCKETS:
377 af = imsg.hdr.peerid;
378 if (disc_socket == -1 || edisc_socket == -1 ||
379 session_socket == -1) {
380 if (disc_socket != -1)
381 close(disc_socket);
382 if (edisc_socket != -1)
383 close(edisc_socket);
384 if (session_socket != -1)
385 close(session_socket);
386 break;
387 }
388
389 ldpe_setup_sockets(af, disc_socket, edisc_socket,
390 session_socket);
391 if_update_all(af);
392 tnbr_update_all(af);
393 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
394 if (nbr->af != af)
395 continue;
396 nbr->laddr = (ldp_af_conf_get(leconf,
397 af))->trans_addr;
eac6e3f0 398#ifdef __OpenBSD__
8429abe0
RW
399 nbrp = nbr_params_find(leconf, nbr->id);
400 if (nbrp && pfkey_establish(nbr, nbrp) == -1)
401 fatalx("pfkey setup failed");
eac6e3f0 402#endif
8429abe0
RW
403 if (nbr_session_active_role(nbr))
404 nbr_establish_connection(nbr);
405 }
406 break;
eac6e3f0
RW
407 case IMSG_RTRID_UPDATE:
408 memcpy(&global.rtr_id, imsg.data,
409 sizeof(global.rtr_id));
410 if (leconf->rtr_id.s_addr == INADDR_ANY) {
411 ldpe_reset_nbrs(AF_INET);
412 ldpe_reset_nbrs(AF_INET6);
413 }
414 if_update_all(AF_UNSPEC);
415 tnbr_update_all(AF_UNSPEC);
416 break;
8429abe0
RW
417 case IMSG_RECONF_CONF:
418 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
419 NULL)
420 fatal(NULL);
421 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
422
7d3d7491 423 RB_INIT(&nconf->iface_tree);
7989cdba 424 RB_INIT(&nconf->tnbr_tree);
76c4abd1 425 RB_INIT(&nconf->nbrp_tree);
90d7e7bd 426 RB_INIT(&nconf->l2vpn_tree);
8429abe0
RW
427 break;
428 case IMSG_RECONF_IFACE:
429 if ((niface = malloc(sizeof(struct iface))) == NULL)
430 fatal(NULL);
431 memcpy(niface, imsg.data, sizeof(struct iface));
432
433 LIST_INIT(&niface->addr_list);
057d48bd
RW
434 RB_INIT(&niface->ipv4.adj_tree);
435 RB_INIT(&niface->ipv6.adj_tree);
8429abe0
RW
436 niface->ipv4.iface = niface;
437 niface->ipv6.iface = niface;
438
7d3d7491 439 RB_INSERT(iface_head, &nconf->iface_tree, niface);
8429abe0
RW
440 break;
441 case IMSG_RECONF_TNBR:
442 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
443 fatal(NULL);
444 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
445
7989cdba 446 RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
8429abe0
RW
447 break;
448 case IMSG_RECONF_NBRP:
449 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
450 fatal(NULL);
451 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
452
76c4abd1 453 RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
8429abe0
RW
454 break;
455 case IMSG_RECONF_L2VPN:
456 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
457 fatal(NULL);
458 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
459
029c1958 460 RB_INIT(&nl2vpn->if_tree);
20bacaeb
RW
461 RB_INIT(&nl2vpn->pw_tree);
462 RB_INIT(&nl2vpn->pw_inactive_tree);
8429abe0 463
90d7e7bd 464 RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
8429abe0
RW
465 break;
466 case IMSG_RECONF_L2VPN_IF:
467 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
468 fatal(NULL);
469 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
470
471 nlif->l2vpn = nl2vpn;
029c1958 472 RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
8429abe0
RW
473 break;
474 case IMSG_RECONF_L2VPN_PW:
475 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
476 fatal(NULL);
477 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
478
479 npw->l2vpn = nl2vpn;
20bacaeb 480 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
8429abe0 481 break;
eac6e3f0
RW
482 case IMSG_RECONF_L2VPN_IPW:
483 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
484 fatal(NULL);
485 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
486
487 npw->l2vpn = nl2vpn;
20bacaeb 488 RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
eac6e3f0 489 break;
8429abe0
RW
490 case IMSG_RECONF_END:
491 merge_config(leconf, nconf);
492 nconf = NULL;
493 global.conf_seqnum++;
494 break;
8429abe0
RW
495 case IMSG_CTL_END:
496 control_imsg_relay(&imsg);
497 break;
eac6e3f0
RW
498 case IMSG_DEBUG_UPDATE:
499 if (imsg.hdr.len != IMSG_HEADER_SIZE +
500 sizeof(ldp_debug)) {
501 log_warnx("%s: wrong imsg len", __func__);
502 break;
503 }
504 memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
505 break;
8429abe0
RW
506 default:
507 log_debug("ldpe_dispatch_main: error handling imsg %d",
508 imsg.hdr.type);
509 break;
510 }
511 imsg_free(&imsg);
512 }
513 if (!shut)
514 imsg_event_add(iev);
515 else {
eac6e3f0
RW
516 /* this pipe is dead, so remove the event handlers and exit */
517 THREAD_READ_OFF(iev->ev_read);
518 THREAD_WRITE_OFF(iev->ev_write);
519 ldpe_shutdown();
8429abe0 520 }
eac6e3f0
RW
521
522 return (0);
8429abe0
RW
523}
524
525/* ARGSUSED */
eac6e3f0
RW
526static int
527ldpe_dispatch_lde(struct thread *thread)
8429abe0 528{
eac6e3f0 529 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
530 struct imsgbuf *ibuf = &iev->ibuf;
531 struct imsg imsg;
532 struct map map;
533 struct notify_msg nm;
534 int n, shut = 0;
535 struct nbr *nbr = NULL;
536
eac6e3f0
RW
537 iev->ev_read = NULL;
538
539 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
540 fatal("imsg_read error");
541 if (n == 0) /* connection closed */
542 shut = 1;
8429abe0
RW
543
544 for (;;) {
545 if ((n = imsg_get(ibuf, &imsg)) == -1)
546 fatal("ldpe_dispatch_lde: imsg_get error");
547 if (n == 0)
548 break;
549
550 switch (imsg.hdr.type) {
551 case IMSG_MAPPING_ADD:
552 case IMSG_RELEASE_ADD:
553 case IMSG_REQUEST_ADD:
554 case IMSG_WITHDRAW_ADD:
555 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
556 fatalx("invalid size of map request");
557 memcpy(&map, imsg.data, sizeof(map));
558
559 nbr = nbr_find_peerid(imsg.hdr.peerid);
560 if (nbr == NULL) {
561 log_debug("ldpe_dispatch_lde: cannot find "
562 "neighbor");
563 break;
564 }
565 if (nbr->state != NBR_STA_OPER)
566 break;
567
568 switch (imsg.hdr.type) {
569 case IMSG_MAPPING_ADD:
570 mapping_list_add(&nbr->mapping_list, &map);
571 break;
572 case IMSG_RELEASE_ADD:
573 mapping_list_add(&nbr->release_list, &map);
574 break;
575 case IMSG_REQUEST_ADD:
576 mapping_list_add(&nbr->request_list, &map);
577 break;
578 case IMSG_WITHDRAW_ADD:
579 mapping_list_add(&nbr->withdraw_list, &map);
580 break;
581 }
582 break;
583 case IMSG_MAPPING_ADD_END:
584 case IMSG_RELEASE_ADD_END:
585 case IMSG_REQUEST_ADD_END:
586 case IMSG_WITHDRAW_ADD_END:
587 nbr = nbr_find_peerid(imsg.hdr.peerid);
588 if (nbr == NULL) {
589 log_debug("ldpe_dispatch_lde: cannot find "
590 "neighbor");
591 break;
592 }
593 if (nbr->state != NBR_STA_OPER)
594 break;
595
596 switch (imsg.hdr.type) {
597 case IMSG_MAPPING_ADD_END:
598 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
599 &nbr->mapping_list);
600 break;
601 case IMSG_RELEASE_ADD_END:
602 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
603 &nbr->release_list);
604 break;
605 case IMSG_REQUEST_ADD_END:
606 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
607 &nbr->request_list);
608 break;
609 case IMSG_WITHDRAW_ADD_END:
610 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
611 &nbr->withdraw_list);
612 break;
613 }
614 break;
615 case IMSG_NOTIFICATION_SEND:
616 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
617 fatalx("invalid size of OE request");
618 memcpy(&nm, imsg.data, sizeof(nm));
619
620 nbr = nbr_find_peerid(imsg.hdr.peerid);
621 if (nbr == NULL) {
622 log_debug("ldpe_dispatch_lde: cannot find "
623 "neighbor");
624 break;
625 }
626 if (nbr->state != NBR_STA_OPER)
627 break;
628
629 send_notification_full(nbr->tcp, &nm);
630 break;
631 case IMSG_CTL_END:
632 case IMSG_CTL_SHOW_LIB:
633 case IMSG_CTL_SHOW_L2VPN_PW:
634 case IMSG_CTL_SHOW_L2VPN_BINDING:
635 control_imsg_relay(&imsg);
636 break;
637 default:
638 log_debug("ldpe_dispatch_lde: error handling imsg %d",
639 imsg.hdr.type);
640 break;
641 }
642 imsg_free(&imsg);
643 }
644 if (!shut)
645 imsg_event_add(iev);
646 else {
eac6e3f0
RW
647 /* this pipe is dead, so remove the event handlers and exit */
648 THREAD_READ_OFF(iev->ev_read);
649 THREAD_WRITE_OFF(iev->ev_write);
650 ldpe_shutdown();
8429abe0 651 }
eac6e3f0
RW
652
653 return (0);
8429abe0
RW
654}
655
eac6e3f0 656#ifdef __OpenBSD__
8429abe0 657/* ARGSUSED */
eac6e3f0
RW
658static int
659ldpe_dispatch_pfkey(struct thread *thread)
8429abe0 660{
eac6e3f0
RW
661 int fd = THREAD_FD(thread);
662
663 pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey,
664 NULL, global.pfkeysock);
665
666 if (pfkey_read(fd, NULL) == -1)
667 fatal("pfkey_read failed, exiting...");
668
669 return (0);
8429abe0 670}
eac6e3f0 671#endif /* __OpenBSD__ */
8429abe0
RW
672
673static void
674ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
675 int session_socket)
676{
677 struct ldpd_af_global *af_global;
678
679 af_global = ldp_af_global_get(&global, af);
680
681 /* discovery socket */
682 af_global->ldp_disc_socket = disc_socket;
eac6e3f0
RW
683 af_global->disc_ev = thread_add_read(master, disc_recv_packet,
684 &af_global->disc_ev, af_global->ldp_disc_socket);
8429abe0
RW
685
686 /* extended discovery socket */
687 af_global->ldp_edisc_socket = edisc_socket;
eac6e3f0
RW
688 af_global->edisc_ev = thread_add_read(master, disc_recv_packet,
689 &af_global->edisc_ev, af_global->ldp_edisc_socket);
8429abe0
RW
690
691 /* session socket */
692 af_global->ldp_session_socket = session_socket;
693 accept_add(af_global->ldp_session_socket, session_accept, NULL);
694}
695
696static void
697ldpe_close_sockets(int af)
698{
699 struct ldpd_af_global *af_global;
700
701 af_global = ldp_af_global_get(&global, af);
702
703 /* discovery socket */
eac6e3f0 704 THREAD_READ_OFF(af_global->disc_ev);
8429abe0
RW
705 if (af_global->ldp_disc_socket != -1) {
706 close(af_global->ldp_disc_socket);
707 af_global->ldp_disc_socket = -1;
708 }
709
710 /* extended discovery socket */
eac6e3f0 711 THREAD_READ_OFF(af_global->edisc_ev);
8429abe0
RW
712 if (af_global->ldp_edisc_socket != -1) {
713 close(af_global->ldp_edisc_socket);
714 af_global->ldp_edisc_socket = -1;
715 }
716
717 /* session socket */
718 if (af_global->ldp_session_socket != -1) {
719 accept_del(af_global->ldp_session_socket);
720 close(af_global->ldp_session_socket);
721 af_global->ldp_session_socket = -1;
722 }
723}
724
725void
726ldpe_reset_nbrs(int af)
727{
728 struct nbr *nbr;
729
730 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
731 if (nbr->af == af)
732 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
733 }
734}
735
736void
737ldpe_reset_ds_nbrs(void)
738{
739 struct nbr *nbr;
740
741 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
742 if (nbr->ds_tlv)
743 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
744 }
745}
746
747void
748ldpe_remove_dynamic_tnbrs(int af)
749{
750 struct tnbr *tnbr, *safe;
751
7989cdba 752 RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) {
8429abe0
RW
753 if (tnbr->af != af)
754 continue;
755
756 tnbr->flags &= ~F_TNBR_DYNAMIC;
7989cdba 757 tnbr_check(leconf, tnbr);
8429abe0
RW
758 }
759}
760
761void
762ldpe_stop_init_backoff(int af)
763{
764 struct nbr *nbr;
765
766 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
767 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
768 nbr_stop_idtimer(nbr);
769 nbr_establish_connection(nbr);
770 }
771 }
772}
773
774static void
775ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
776{
777 struct iface *iface;
778 struct iface_af *ia;
779 struct ctl_iface *ictl;
780
7d3d7491 781 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
8429abe0
RW
782 if (idx == 0 || idx == iface->ifindex) {
783 ia = iface_af_get(iface, af);
784 if (!ia->enabled)
785 continue;
786
787 ictl = if_to_ctl(ia);
788 imsg_compose_event(&c->iev,
789 IMSG_CTL_SHOW_INTERFACE,
790 0, 0, -1, ictl, sizeof(struct ctl_iface));
791 }
792 }
793}
794
795void
796ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
797{
798 ldpe_iface_af_ctl(c, AF_INET, idx);
799 ldpe_iface_af_ctl(c, AF_INET6, idx);
800}
801
802void
803ldpe_adj_ctl(struct ctl_conn *c)
804{
eac6e3f0
RW
805 struct iface *iface;
806 struct tnbr *tnbr;
807 struct adj *adj;
808 struct ctl_adj *actl;
809 struct ctl_disc_if ictl;
810 struct ctl_disc_tnbr tctl;
8429abe0 811
eac6e3f0
RW
812 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
813
7d3d7491 814 RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
eac6e3f0
RW
815 memset(&ictl, 0, sizeof(ictl));
816 ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
817 ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);
818
819 if (!ictl.active_v4 && !ictl.active_v6)
820 continue;
821
822 strlcpy(ictl.name, iface->name, sizeof(ictl.name));
057d48bd
RW
823 if (RB_EMPTY(&iface->ipv4.adj_tree) &&
824 RB_EMPTY(&iface->ipv6.adj_tree))
eac6e3f0
RW
825 ictl.no_adj = 1;
826 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
827 -1, &ictl, sizeof(ictl));
828
057d48bd 829 RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
8429abe0 830 actl = adj_to_ctl(adj);
eac6e3f0
RW
831 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
832 0, 0, -1, actl, sizeof(struct ctl_adj));
833 }
057d48bd 834 RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
eac6e3f0
RW
835 actl = adj_to_ctl(adj);
836 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
8429abe0
RW
837 0, 0, -1, actl, sizeof(struct ctl_adj));
838 }
839 }
eac6e3f0 840
7989cdba 841 RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) {
eac6e3f0
RW
842 memset(&tctl, 0, sizeof(tctl));
843 tctl.af = tnbr->af;
844 tctl.addr = tnbr->addr;
845 if (tnbr->adj == NULL)
846 tctl.no_adj = 1;
847
848 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0,
849 -1, &tctl, sizeof(tctl));
850
851 if (tnbr->adj == NULL)
8429abe0
RW
852 continue;
853
eac6e3f0
RW
854 actl = adj_to_ctl(tnbr->adj);
855 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0,
8429abe0
RW
856 -1, actl, sizeof(struct ctl_adj));
857 }
858
859 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
860}
861
862void
863ldpe_nbr_ctl(struct ctl_conn *c)
864{
eac6e3f0
RW
865 struct adj *adj;
866 struct ctl_adj *actl;
8429abe0
RW
867 struct nbr *nbr;
868 struct ctl_nbr *nctl;
869
870 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
eac6e3f0
RW
871 if (nbr->state == NBR_STA_PRESENT)
872 continue;
873
8429abe0
RW
874 nctl = nbr_to_ctl(nbr);
875 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
876 sizeof(struct ctl_nbr));
eac6e3f0 877
057d48bd 878 RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
eac6e3f0
RW
879 actl = adj_to_ctl(adj);
880 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
881 0, 0, -1, actl, sizeof(struct ctl_adj));
882 }
883
884 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1,
885 NULL, 0);
8429abe0
RW
886 }
887 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
888}
889
890void
891mapping_list_add(struct mapping_head *mh, struct map *map)
892{
893 struct mapping_entry *me;
894
895 me = calloc(1, sizeof(*me));
896 if (me == NULL)
897 fatal(__func__);
898 me->map = *map;
899
900 TAILQ_INSERT_TAIL(mh, me, entry);
901}
902
903void
904mapping_list_clr(struct mapping_head *mh)
905{
906 struct mapping_entry *me;
907
908 while ((me = TAILQ_FIRST(mh)) != NULL) {
909 TAILQ_REMOVE(mh, me, entry);
910 free(me);
911 }
912}