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