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