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