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