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