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