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