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