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