]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/ldpd.c
ldpd: ignore the SIGHUP signal in the child processes
[mirror_frr.git] / ldpd / ldpd.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 23#include <sys/wait.h>
8429abe0
RW
24
25#include "ldpd.h"
26#include "ldpe.h"
27#include "lde.h"
28#include "log.h"
eac6e3f0
RW
29#include "ldp_vty.h"
30#include "ldp_debug.h"
31
32#include <lib/version.h>
33#include <lib/log.h>
34#include "getopt.h"
35#include "vty.h"
36#include "command.h"
37#include "memory.h"
38#include "privs.h"
39#include "sigevent.h"
40#include "zclient.h"
41#include "vrf.h"
45a8eba9 42#include "filter.h"
4af8997d 43#include "qobj.h"
4f04a76b 44#include "libfrr.h"
eac6e3f0
RW
45
46static void ldpd_shutdown(void);
28e8294c 47static pid_t start_child(enum ldpd_process, char *, int, int,
fea12efb 48 const char *, const char *, const char *, const char *);
eac6e3f0
RW
49static int main_dispatch_ldpe(struct thread *);
50static int main_dispatch_lde(struct thread *);
8429abe0
RW
51static int main_imsg_send_ipc_sockets(struct imsgbuf *,
52 struct imsgbuf *);
53static void main_imsg_send_net_sockets(int);
54static void main_imsg_send_net_socket(int, enum socket_type);
55static int main_imsg_send_config(struct ldpd_conf *);
56b8a8d2
RW
56static void ldp_config_normalize(struct ldpd_conf *);
57static void ldp_config_reset_main(struct ldpd_conf *);
58static void ldp_config_reset_af(struct ldpd_conf *, int);
8429abe0
RW
59static void merge_global(struct ldpd_conf *, struct ldpd_conf *);
60static void merge_af(int, struct ldpd_af_conf *,
61 struct ldpd_af_conf *);
56b8a8d2 62static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *);
8429abe0 63static void merge_iface_af(struct iface_af *, struct iface_af *);
56b8a8d2
RW
64static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *);
65static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *);
66static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *);
8429abe0 67static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *,
56b8a8d2 68 struct l2vpn *);
8429abe0 69
4af8997d
RW
70DEFINE_QOBJ_TYPE(iface)
71DEFINE_QOBJ_TYPE(tnbr)
72DEFINE_QOBJ_TYPE(nbr_params)
73DEFINE_QOBJ_TYPE(l2vpn_if)
74DEFINE_QOBJ_TYPE(l2vpn_pw)
75DEFINE_QOBJ_TYPE(l2vpn)
76DEFINE_QOBJ_TYPE(ldpd_conf)
77
8429abe0 78struct ldpd_global global;
56b8a8d2 79struct ldpd_conf *ldpd_conf, *vty_conf;
8429abe0 80
28e8294c
RW
81static struct imsgev *iev_ldpe, *iev_ldpe_sync;
82static struct imsgev *iev_lde, *iev_lde_sync;
8429abe0
RW
83static pid_t ldpe_pid;
84static pid_t lde_pid;
85
eac6e3f0
RW
86#define LDP_DEFAULT_CONFIG "ldpd.conf"
87#define LDP_VTY_PORT 2612
88
89/* Master of threads. */
90struct thread_master *master;
91
eac6e3f0
RW
92/* ldpd privileges */
93static zebra_capabilities_t _caps_p [] =
8429abe0 94{
eac6e3f0
RW
95 ZCAP_BIND,
96 ZCAP_NET_ADMIN
97};
98
99struct zebra_privs_t ldpd_privs =
100{
b2f36157
DL
101#if defined(FRR_USER) && defined(FRR_GROUP)
102 .user = FRR_USER,
103 .group = FRR_GROUP,
eac6e3f0
RW
104#endif
105#if defined(VTY_GROUP)
106 .vty_group = VTY_GROUP,
107#endif
108 .caps_p = _caps_p,
109 .cap_num_p = array_size(_caps_p),
110 .cap_num_i = 0
111};
112
372b8bd3
RW
113/* CTL Socket path */
114char ctl_sock_path[MAXPATHLEN] = LDPD_SOCKET;
115
eac6e3f0 116/* LDPd options. */
372b8bd3 117#define OPTION_CTLSOCK 1001
eac6e3f0
RW
118static struct option longopts[] =
119{
372b8bd3 120 { "ctl_socket", required_argument, NULL, OPTION_CTLSOCK},
fea12efb 121 { "instance", required_argument, NULL, 'n'},
eac6e3f0
RW
122 { 0 }
123};
124
eac6e3f0
RW
125/* SIGHUP handler. */
126static void
127sighup(void)
128{
129 log_info("SIGHUP received");
130}
131
132/* SIGINT / SIGTERM handler. */
133static void
134sigint(void)
8429abe0 135{
eac6e3f0
RW
136 log_info("SIGINT received");
137 ldpd_shutdown();
138}
8429abe0 139
eac6e3f0
RW
140/* SIGUSR1 handler. */
141static void
142sigusr1(void)
143{
dd8376fe 144 zlog_rotate();
8429abe0
RW
145}
146
eac6e3f0
RW
147static struct quagga_signal_t ldp_signals[] =
148{
149 {
150 .signal = SIGHUP,
151 .handler = &sighup,
152 },
153 {
154 .signal = SIGINT,
155 .handler = &sigint,
156 },
157 {
158 .signal = SIGTERM,
159 .handler = &sigint,
160 },
161 {
162 .signal = SIGUSR1,
163 .handler = &sigusr1,
164 }
165};
166
4f04a76b
DL
167FRR_DAEMON_INFO(ldpd, LDP,
168 .vty_port = LDP_VTY_PORT,
169
170 .proghelp = "Implementation of the LDP protocol.",
171
172 .signals = ldp_signals,
173 .n_signals = array_size(ldp_signals),
174
175 .privs = &ldpd_privs,
176)
177
8429abe0
RW
178int
179main(int argc, char *argv[])
180{
8429abe0 181 char *saved_argv0;
eac6e3f0 182 int lflag = 0, eflag = 0;
28e8294c
RW
183 int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
184 int pipe_parent2lde[2], pipe_parent2lde_sync[2];
372b8bd3
RW
185 char *ctl_sock_custom_path = NULL;
186 char *ctl_sock_name;
eac6e3f0
RW
187 const char *user = NULL;
188 const char *group = NULL;
fea12efb 189 u_short instance = 0;
190 const char *instance_char = NULL;
8429abe0 191
8429abe0
RW
192 ldpd_process = PROC_MAIN;
193
8429abe0
RW
194 saved_argv0 = argv[0];
195 if (saved_argv0 == NULL)
eac6e3f0 196 saved_argv0 = (char *)"ldpd";
8429abe0 197
4f04a76b 198 frr_preinit(&ldpd_di, argc, argv);
fea12efb 199 frr_opt_add("LEn:", longopts,
200 " --ctl_socket Override ctl socket path\n"
201 "-n, --instance Instance id\n");
4f04a76b 202
eac6e3f0
RW
203 while (1) {
204 int opt;
205
4f04a76b 206 opt = frr_getopt(argc, argv, NULL);
eac6e3f0
RW
207
208 if (opt == EOF)
8429abe0 209 break;
eac6e3f0
RW
210
211 switch (opt) {
212 case 0:
213 break;
372b8bd3
RW
214 case OPTION_CTLSOCK:
215 ctl_sock_name = strrchr(LDPD_SOCKET, '/');
216 if (ctl_sock_name)
217 /* skip '/' */
218 ctl_sock_name++;
219 else
220 /*
221 * LDPD_SOCKET configured as relative path
222 * during config? Should really never happen for
223 * sensible config
224 */
225 ctl_sock_name = (char *)LDPD_SOCKET;
226 ctl_sock_custom_path = optarg;
227 strlcpy(ctl_sock_path, ctl_sock_custom_path,
228 sizeof(ctl_sock_path));
229 strlcat(ctl_sock_path, "/", sizeof(ctl_sock_path));
230 strlcat(ctl_sock_path, ctl_sock_name,
231 sizeof(ctl_sock_path));
232 break;
fea12efb 233 case 'n':
234 instance = atoi(optarg);
235 instance_char = optarg;
236 if (instance < 1)
237 exit(0);
238 break;
8429abe0
RW
239 case 'L':
240 lflag = 1;
241 break;
242 case 'E':
243 eflag = 1;
244 break;
245 default:
4f04a76b 246 frr_help_exit(1);
eac6e3f0 247 break;
8429abe0
RW
248 }
249 }
250
4f04a76b
DL
251 user = ldpd_privs.user;
252 group = ldpd_privs.group;
253
8429abe0
RW
254 argc -= optind;
255 argv += optind;
256 if (argc > 0 || (lflag && eflag))
4f04a76b 257 frr_help_exit(1);
8429abe0 258
eac6e3f0
RW
259 /* check for root privileges */
260 if (geteuid() != 0) {
261 errno = EPERM;
4f04a76b 262 perror(ldpd_di.progname);
8429abe0
RW
263 exit(1);
264 }
265
eac6e3f0 266 if (lflag)
fea12efb 267 lde(user, group, instance);
eac6e3f0 268 else if (eflag)
372b8bd3 269 ldpe(user, group, ctl_sock_path);
8429abe0 270
83139e57
RW
271 openzlog(ldpd_di.progname, "LDP", 0,
272 LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
4af8997d 273
eac6e3f0 274 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
8429abe0 275 fatal("socketpair");
28e8294c
RW
276 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
277 pipe_parent2ldpe_sync) == -1)
278 fatal("socketpair");
eac6e3f0 279 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
8429abe0 280 fatal("socketpair");
28e8294c
RW
281 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
282 pipe_parent2lde_sync) == -1)
283 fatal("socketpair");
eac6e3f0
RW
284 sock_set_nonblock(pipe_parent2ldpe[0]);
285 sock_set_cloexec(pipe_parent2ldpe[0]);
286 sock_set_nonblock(pipe_parent2ldpe[1]);
287 sock_set_cloexec(pipe_parent2ldpe[1]);
28e8294c
RW
288 sock_set_nonblock(pipe_parent2ldpe_sync[0]);
289 sock_set_cloexec(pipe_parent2ldpe_sync[0]);
290 sock_set_cloexec(pipe_parent2ldpe_sync[1]);
eac6e3f0
RW
291 sock_set_nonblock(pipe_parent2lde[0]);
292 sock_set_cloexec(pipe_parent2lde[0]);
293 sock_set_nonblock(pipe_parent2lde[1]);
294 sock_set_cloexec(pipe_parent2lde[1]);
28e8294c
RW
295 sock_set_nonblock(pipe_parent2lde_sync[0]);
296 sock_set_cloexec(pipe_parent2lde_sync[0]);
297 sock_set_cloexec(pipe_parent2lde_sync[1]);
8429abe0
RW
298
299 /* start children */
300 lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
1a35e2e5 301 pipe_parent2lde[1], pipe_parent2lde_sync[1],
fea12efb 302 user, group, ctl_sock_custom_path, instance_char);
8429abe0 303 ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
1a35e2e5 304 pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1],
fea12efb 305 user, group, ctl_sock_custom_path, instance_char);
8429abe0 306
eac6e3f0 307 /* drop privileges */
eac6e3f0 308 zprivs_init(&ldpd_privs);
8429abe0
RW
309
310 /* setup signal handler */
eac6e3f0
RW
311 signal_init(master, array_size(ldp_signals), ldp_signals);
312
83139e57
RW
313 /* thread master */
314 master = thread_master_create();
315
eac6e3f0 316 /* library inits */
83139e57
RW
317 cmd_init(1);
318 vty_config_lockless();
319 vty_init(master);
320 vrf_init();
321 access_list_init();
322 ldp_vty_init();
323 ldp_vty_if_init();
eac6e3f0 324 ldp_zebra_init(master);
8429abe0 325
56b8a8d2 326 /* create base configuration with sane defaults */
83139e57 327 ldpd_conf = config_new_empty();
56b8a8d2 328 ldp_config_reset_main(ldpd_conf);
83139e57 329 QOBJ_REG(ldpd_conf, ldpd_conf);
56b8a8d2
RW
330
331 /*
332 * Create vty_conf as a duplicate of the main configuration. All
333 * configuration requests (e.g. CLI) act on vty_conf and then call
334 * ldp_reload() to merge the changes into ldpd_conf.
335 */
336 vty_conf = ldp_dup_config(ldpd_conf);
337
338 /* read configuration file and daemonize */
83139e57
RW
339 frr_config_fork();
340
8429abe0 341 /* setup pipes to children */
28e8294c
RW
342 if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL ||
343 (iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL ||
344 (iev_lde = calloc(1, sizeof(struct imsgev))) == NULL ||
345 (iev_lde_sync = calloc(1, sizeof(struct imsgev))) == NULL)
8429abe0
RW
346 fatal(NULL);
347 imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
eac6e3f0
RW
348 iev_ldpe->handler_read = main_dispatch_ldpe;
349 iev_ldpe->ev_read = thread_add_read(master, iev_ldpe->handler_read,
350 iev_ldpe, iev_ldpe->ibuf.fd);
351 iev_ldpe->handler_write = ldp_write_handler;
28e8294c
RW
352
353 imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]);
354 iev_ldpe_sync->handler_read = main_dispatch_ldpe;
355 iev_ldpe_sync->ev_read = thread_add_read(master,
356 iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd);
357 iev_ldpe_sync->handler_write = ldp_write_handler;
8429abe0 358
eac6e3f0
RW
359 imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
360 iev_lde->handler_read = main_dispatch_lde;
361 iev_lde->ev_read = thread_add_read(master, iev_lde->handler_read,
362 iev_lde, iev_lde->ibuf.fd);
363 iev_lde->handler_write = ldp_write_handler;
28e8294c
RW
364
365 imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]);
366 iev_lde_sync->handler_read = main_dispatch_lde;
367 iev_lde_sync->ev_read = thread_add_read(master,
368 iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd);
369 iev_lde_sync->handler_write = ldp_write_handler;
8429abe0
RW
370
371 if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
372 fatal("could not establish imsg links");
eac6e3f0
RW
373 main_imsg_compose_both(IMSG_DEBUG_UPDATE, &ldp_debug,
374 sizeof(ldp_debug));
8429abe0
RW
375 main_imsg_send_config(ldpd_conf);
376
8429abe0
RW
377 if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
378 main_imsg_send_net_sockets(AF_INET);
379 if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
380 main_imsg_send_net_sockets(AF_INET6);
381
16077f2f 382 frr_run(master);
8429abe0 383
8429abe0
RW
384 /* NOTREACHED */
385 return (0);
386}
387
eac6e3f0 388static void
8429abe0
RW
389ldpd_shutdown(void)
390{
391 pid_t pid;
392 int status;
393
394 /* close pipes */
395 msgbuf_clear(&iev_ldpe->ibuf.w);
396 close(iev_ldpe->ibuf.fd);
397 msgbuf_clear(&iev_lde->ibuf.w);
398 close(iev_lde->ibuf.fd);
399
8429abe0 400 config_clear(ldpd_conf);
83139e57 401 QOBJ_UNREG(ldpd_conf);
8429abe0
RW
402
403 log_debug("waiting for children to terminate");
404 do {
405 pid = wait(&status);
406 if (pid == -1) {
407 if (errno != EINTR && errno != ECHILD)
408 fatal("wait");
409 } else if (WIFSIGNALED(status))
410 log_warnx("%s terminated; signal %d",
411 (pid == lde_pid) ? "label decision engine" :
412 "ldp engine", WTERMSIG(status));
413 } while (pid != -1 || (pid == -1 && errno == EINTR));
414
415 free(iev_ldpe);
416 free(iev_lde);
417
418 log_info("terminating");
64dffe25
RW
419
420 vrf_terminate();
45a8eba9 421 access_list_reset();
64dffe25
RW
422 cmd_terminate();
423 vty_terminate();
424 ldp_zebra_destroy();
425 zprivs_terminate(&ldpd_privs);
426 thread_master_free(master);
bf1013e6 427 closezlog();
64dffe25 428
8429abe0
RW
429 exit(0);
430}
431
432static pid_t
28e8294c 433start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
fea12efb 434 const char *user, const char *group, const char *ctl_sock_custom_path,
435 const char *instance)
8429abe0 436{
fea12efb 437 char *argv[13];
8429abe0
RW
438 int argc = 0;
439 pid_t pid;
440
441 switch (pid = fork()) {
442 case -1:
443 fatal("cannot fork");
444 case 0:
445 break;
446 default:
28e8294c
RW
447 close(fd_async);
448 close(fd_sync);
8429abe0
RW
449 return (pid);
450 }
451
28e8294c
RW
452 if (dup2(fd_async, LDPD_FD_ASYNC) == -1)
453 fatal("cannot setup imsg async fd");
454 if (dup2(fd_sync, LDPD_FD_SYNC) == -1)
455 fatal("cannot setup imsg sync fd");
8429abe0
RW
456
457 argv[argc++] = argv0;
458 switch (p) {
459 case PROC_MAIN:
460 fatalx("Can not start main process");
461 case PROC_LDE_ENGINE:
eac6e3f0 462 argv[argc++] = (char *)"-L";
8429abe0
RW
463 break;
464 case PROC_LDP_ENGINE:
eac6e3f0 465 argv[argc++] = (char *)"-E";
8429abe0
RW
466 break;
467 }
eac6e3f0
RW
468 if (user) {
469 argv[argc++] = (char *)"-u";
470 argv[argc++] = (char *)user;
471 }
472 if (group) {
473 argv[argc++] = (char *)"-g";
474 argv[argc++] = (char *)group;
475 }
372b8bd3
RW
476 if (ctl_sock_custom_path) {
477 argv[argc++] = (char *)"--ctl_socket";
478 argv[argc++] = (char *)ctl_sock_custom_path;
479 }
fea12efb 480 /* zclient serv path */
481 argv[argc++] = (char *)"-z";
482 argv[argc++] = (char *)zclient_serv_path_get();
483 /* instance */
484 if (instance) {
485 argv[argc++] = (char *)"-n";
486 argv[argc++] = (char *)instance;
487 }
8429abe0
RW
488 argv[argc++] = NULL;
489
490 execvp(argv0, argv);
491 fatal("execvp");
492}
493
494/* imsg handling */
495/* ARGSUSED */
eac6e3f0
RW
496static int
497main_dispatch_ldpe(struct thread *thread)
8429abe0 498{
eac6e3f0 499 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
500 struct imsgbuf *ibuf = &iev->ibuf;
501 struct imsg imsg;
502 int af;
503 ssize_t n;
eac6e3f0 504 int shut = 0;
8429abe0 505
eac6e3f0
RW
506 iev->ev_read = NULL;
507
508 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
509 fatal("imsg_read error");
510 if (n == 0) /* connection closed */
511 shut = 1;
8429abe0
RW
512
513 for (;;) {
514 if ((n = imsg_get(ibuf, &imsg)) == -1)
515 fatal("imsg_get");
516
517 if (n == 0)
518 break;
519
520 switch (imsg.hdr.type) {
eac6e3f0
RW
521 case IMSG_LOG:
522 logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
523 break;
8429abe0
RW
524 case IMSG_REQUEST_SOCKETS:
525 af = imsg.hdr.pid;
526 main_imsg_send_net_sockets(af);
527 break;
45a8eba9
RW
528 case IMSG_ACL_CHECK:
529 if (imsg.hdr.len != IMSG_HEADER_SIZE +
530 sizeof(struct acl_check))
531 fatalx("IMSG_ACL_CHECK imsg with wrong len");
532 ldp_acl_reply(iev, (struct acl_check *)imsg.data);
533 break;
8429abe0
RW
534 default:
535 log_debug("%s: error handling imsg %d", __func__,
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_pid = 0;
548 if (lde_pid == 0)
549 ldpd_shutdown();
550 else
551 kill(lde_pid, SIGTERM);
8429abe0 552 }
eac6e3f0
RW
553
554 return (0);
8429abe0
RW
555}
556
557/* ARGSUSED */
eac6e3f0
RW
558static int
559main_dispatch_lde(struct thread *thread)
8429abe0 560{
eac6e3f0 561 struct imsgev *iev = THREAD_ARG(thread);
8429abe0
RW
562 struct imsgbuf *ibuf = &iev->ibuf;
563 struct imsg imsg;
564 ssize_t n;
565 int shut = 0;
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("imsg_get");
577
578 if (n == 0)
579 break;
580
581 switch (imsg.hdr.type) {
eac6e3f0
RW
582 case IMSG_LOG:
583 logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
584 break;
8429abe0
RW
585 case IMSG_KLABEL_CHANGE:
586 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
587 sizeof(struct kroute))
588 fatalx("invalid size of IMSG_KLABEL_CHANGE");
589 if (kr_change(imsg.data))
590 log_warnx("%s: error changing route", __func__);
591 break;
592 case IMSG_KLABEL_DELETE:
593 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
594 sizeof(struct kroute))
595 fatalx("invalid size of IMSG_KLABEL_DELETE");
596 if (kr_delete(imsg.data))
597 log_warnx("%s: error deleting route", __func__);
598 break;
599 case IMSG_KPWLABEL_CHANGE:
600 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
601 sizeof(struct kpw))
602 fatalx("invalid size of IMSG_KPWLABEL_CHANGE");
603 if (kmpw_set(imsg.data))
604 log_warnx("%s: error changing pseudowire",
605 __func__);
606 break;
607 case IMSG_KPWLABEL_DELETE:
608 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
609 sizeof(struct kpw))
610 fatalx("invalid size of IMSG_KPWLABEL_DELETE");
611 if (kmpw_unset(imsg.data))
612 log_warnx("%s: error unsetting pseudowire",
613 __func__);
614 break;
45a8eba9
RW
615 case IMSG_ACL_CHECK:
616 if (imsg.hdr.len != IMSG_HEADER_SIZE +
617 sizeof(struct acl_check))
618 fatalx("IMSG_ACL_CHECK imsg with wrong len");
619 ldp_acl_reply(iev, (struct acl_check *)imsg.data);
620 break;
8429abe0
RW
621 default:
622 log_debug("%s: error handling imsg %d", __func__,
623 imsg.hdr.type);
624 break;
625 }
626 imsg_free(&imsg);
627 }
628 if (!shut)
629 imsg_event_add(iev);
630 else {
eac6e3f0
RW
631 /* this pipe is dead, so remove the event handlers and exit */
632 THREAD_READ_OFF(iev->ev_read);
633 THREAD_WRITE_OFF(iev->ev_write);
634 lde_pid = 0;
635 if (ldpe_pid == 0)
636 ldpd_shutdown();
637 else
638 kill(ldpe_pid, SIGTERM);
8429abe0 639 }
eac6e3f0
RW
640
641 return (0);
642}
643
644/* ARGSUSED */
645int
646ldp_write_handler(struct thread *thread)
647{
648 struct imsgev *iev = THREAD_ARG(thread);
649 struct imsgbuf *ibuf = &iev->ibuf;
650 ssize_t n;
651
652 iev->ev_write = NULL;
653
654 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
655 fatal("msgbuf_write");
656 if (n == 0) {
657 /* this pipe is dead, so remove the event handlers */
658 THREAD_READ_OFF(iev->ev_read);
659 THREAD_WRITE_OFF(iev->ev_write);
660 return (0);
661 }
662
663 imsg_event_add(iev);
664
665 return (0);
8429abe0
RW
666}
667
668void
669main_imsg_compose_ldpe(int type, pid_t pid, void *data, uint16_t datalen)
670{
671 if (iev_ldpe == NULL)
672 return;
673 imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen);
674}
675
676void
677main_imsg_compose_lde(int type, pid_t pid, void *data, uint16_t datalen)
678{
679 imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen);
680}
681
eac6e3f0 682int
8429abe0
RW
683main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len)
684{
eac6e3f0
RW
685 if (iev_ldpe == NULL || iev_lde == NULL)
686 return (0);
8429abe0
RW
687 if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1)
688 return (-1);
689 if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1)
690 return (-1);
691 return (0);
692}
693
694void
695imsg_event_add(struct imsgev *iev)
696{
28e8294c
RW
697 if (iev->handler_read)
698 THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev,
699 iev->ibuf.fd);
8429abe0 700
28e8294c 701 if (iev->handler_write && iev->ibuf.w.queued)
eac6e3f0
RW
702 THREAD_WRITE_ON(master, iev->ev_write, iev->handler_write, iev,
703 iev->ibuf.fd);
8429abe0
RW
704}
705
706int
707imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
708 pid_t pid, int fd, void *data, uint16_t datalen)
709{
710 int ret;
711
712 if ((ret = imsg_compose(&iev->ibuf, type, peerid,
713 pid, fd, data, datalen)) != -1)
714 imsg_event_add(iev);
715 return (ret);
716}
717
718void
719evbuf_enqueue(struct evbuf *eb, struct ibuf *buf)
720{
721 ibuf_close(&eb->wbuf, buf);
722 evbuf_event_add(eb);
723}
724
725void
726evbuf_event_add(struct evbuf *eb)
727{
728 if (eb->wbuf.queued)
eac6e3f0
RW
729 THREAD_WRITE_ON(master, eb->ev, eb->handler, eb->arg,
730 eb->wbuf.fd);
8429abe0
RW
731}
732
733void
eac6e3f0 734evbuf_init(struct evbuf *eb, int fd, int (*handler)(struct thread *),
8429abe0
RW
735 void *arg)
736{
737 msgbuf_init(&eb->wbuf);
738 eb->wbuf.fd = fd;
eac6e3f0
RW
739 eb->handler = handler;
740 eb->arg = arg;
8429abe0
RW
741}
742
743void
744evbuf_clear(struct evbuf *eb)
745{
eac6e3f0 746 THREAD_WRITE_OFF(eb->ev);
8429abe0
RW
747 msgbuf_clear(&eb->wbuf);
748 eb->wbuf.fd = -1;
749}
750
751static int
752main_imsg_send_ipc_sockets(struct imsgbuf *ldpe_buf, struct imsgbuf *lde_buf)
753{
754 int pipe_ldpe2lde[2];
755
eac6e3f0 756 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_ldpe2lde) == -1)
8429abe0 757 return (-1);
eac6e3f0
RW
758 sock_set_nonblock(pipe_ldpe2lde[0]);
759 sock_set_nonblock(pipe_ldpe2lde[1]);
8429abe0
RW
760
761 if (imsg_compose(ldpe_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[0],
762 NULL, 0) == -1)
763 return (-1);
764 if (imsg_compose(lde_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[1],
765 NULL, 0) == -1)
766 return (-1);
767
768 return (0);
769}
770
771static void
772main_imsg_send_net_sockets(int af)
773{
eac6e3f0
RW
774 if (!ldp_addrisset(af, &(ldp_af_conf_get(ldpd_conf, af))->trans_addr))
775 return;
776
8429abe0
RW
777 main_imsg_send_net_socket(af, LDP_SOCKET_DISC);
778 main_imsg_send_net_socket(af, LDP_SOCKET_EDISC);
779 main_imsg_send_net_socket(af, LDP_SOCKET_SESSION);
780 imsg_compose_event(iev_ldpe, IMSG_SETUP_SOCKETS, af, 0, -1, NULL, 0);
781}
782
783static void
784main_imsg_send_net_socket(int af, enum socket_type type)
785{
786 int fd;
787
788 fd = ldp_create_socket(af, type);
789 if (fd == -1) {
790 log_warnx("%s: failed to create %s socket for address-family "
791 "%s", __func__, socket_name(type), af_name(af));
792 return;
793 }
794
795 imsg_compose_event(iev_ldpe, IMSG_SOCKET_NET, af, 0, fd, &type,
796 sizeof(type));
797}
798
45a8eba9
RW
799int
800ldp_acl_request(struct imsgev *iev, char *acl_name, int af,
801 union ldpd_addr *addr, uint8_t prefixlen)
802{
803 struct imsg imsg;
804 ssize_t n;
805 struct acl_check acl_check;
806
807 if (acl_name[0] == '\0')
808 return FILTER_PERMIT;
809
810 /* build request */
811 strlcpy(acl_check.acl, acl_name, sizeof(acl_check.acl));
812 acl_check.af = af;
813 acl_check.addr = *addr;
814 acl_check.prefixlen = prefixlen;
815
816 /* send (blocking) */
817 imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &acl_check,
818 sizeof(acl_check));
819 imsg_flush(&iev->ibuf);
820
821 /* receive (blocking) and parse result */
822 if ((n = imsg_read(&iev->ibuf)) == -1)
823 fatal("imsg_read error");
824 if ((n = imsg_get(&iev->ibuf, &imsg)) == -1)
825 fatal("imsg_get");
826 if (imsg.hdr.type != IMSG_ACL_CHECK ||
827 imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(int))
828 fatalx("ldp_acl_request: invalid response");
829
830 return (*((int *)imsg.data));
831}
832
833void
834ldp_acl_reply(struct imsgev *iev, struct acl_check *acl_check)
835{
836 struct access_list *alist;
837 struct prefix prefix;
838 int result;
839
840 alist = access_list_lookup(family2afi(acl_check->af), acl_check->acl);
841 if (alist == NULL)
842 result = FILTER_DENY;
843 else {
844 prefix.family = acl_check->af;
845 switch (prefix.family) {
846 case AF_INET:
847 prefix.u.prefix4 = acl_check->addr.v4;
848 break;
849 case AF_INET6:
850 prefix.u.prefix6 = acl_check->addr.v6;
851 break;
852 default:
853 fatalx("ldp_acl_reply: unknown af");
854 }
855 prefix.prefixlen = acl_check->prefixlen;
856 result = access_list_apply(alist, &prefix);
857 }
858
859 imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &result,
860 sizeof(result));
861}
862
8429abe0
RW
863struct ldpd_af_conf *
864ldp_af_conf_get(struct ldpd_conf *xconf, int af)
865{
866 switch (af) {
867 case AF_INET:
868 return (&xconf->ipv4);
869 case AF_INET6:
870 return (&xconf->ipv6);
871 default:
872 fatalx("ldp_af_conf_get: unknown af");
873 }
874}
875
876struct ldpd_af_global *
877ldp_af_global_get(struct ldpd_global *xglobal, int af)
878{
879 switch (af) {
880 case AF_INET:
881 return (&xglobal->ipv4);
882 case AF_INET6:
883 return (&xglobal->ipv6);
884 default:
885 fatalx("ldp_af_global_get: unknown af");
886 }
887}
888
889int
890ldp_is_dual_stack(struct ldpd_conf *xconf)
891{
892 return ((xconf->ipv4.flags & F_LDPD_AF_ENABLED) &&
893 (xconf->ipv6.flags & F_LDPD_AF_ENABLED));
894}
895
eac6e3f0
RW
896in_addr_t
897ldp_rtr_id_get(struct ldpd_conf *xconf)
898{
899 if (xconf->rtr_id.s_addr != INADDR_ANY)
900 return (xconf->rtr_id.s_addr);
901 else
902 return (global.rtr_id.s_addr);
903}
904
8429abe0
RW
905static int
906main_imsg_send_config(struct ldpd_conf *xconf)
907{
908 struct iface *iface;
909 struct tnbr *tnbr;
910 struct nbr_params *nbrp;
911 struct l2vpn *l2vpn;
912 struct l2vpn_if *lif;
913 struct l2vpn_pw *pw;
914
915 if (main_imsg_compose_both(IMSG_RECONF_CONF, xconf,
916 sizeof(*xconf)) == -1)
917 return (-1);
918
7d3d7491 919 RB_FOREACH(iface, iface_head, &xconf->iface_tree) {
8429abe0
RW
920 if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface,
921 sizeof(*iface)) == -1)
922 return (-1);
923 }
924
7989cdba 925 RB_FOREACH(tnbr, tnbr_head, &xconf->tnbr_tree) {
8429abe0
RW
926 if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr,
927 sizeof(*tnbr)) == -1)
928 return (-1);
929 }
930
76c4abd1 931 RB_FOREACH(nbrp, nbrp_head, &xconf->nbrp_tree) {
8429abe0
RW
932 if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp,
933 sizeof(*nbrp)) == -1)
934 return (-1);
935 }
936
90d7e7bd 937 RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
8429abe0
RW
938 if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn,
939 sizeof(*l2vpn)) == -1)
940 return (-1);
941
029c1958 942 RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
8429abe0
RW
943 if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif,
944 sizeof(*lif)) == -1)
945 return (-1);
946 }
20bacaeb 947 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
8429abe0
RW
948 if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw,
949 sizeof(*pw)) == -1)
950 return (-1);
951 }
20bacaeb 952 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
eac6e3f0
RW
953 if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IPW, pw,
954 sizeof(*pw)) == -1)
955 return (-1);
956 }
8429abe0
RW
957 }
958
959 if (main_imsg_compose_both(IMSG_RECONF_END, NULL, 0) == -1)
960 return (-1);
961
962 return (0);
963}
964
eac6e3f0 965int
56b8a8d2 966ldp_reload(struct ldpd_conf *xconf)
8429abe0 967{
56b8a8d2 968 ldp_config_normalize(xconf);
8429abe0
RW
969
970 if (main_imsg_send_config(xconf) == -1)
971 return (-1);
972
56b8a8d2 973 merge_config(ldpd_conf, xconf);
8429abe0 974
56b8a8d2 975 vty_conf = ldp_dup_config(ldpd_conf);
8429abe0 976
56b8a8d2 977 return (0);
b67c140b
RW
978}
979
eac6e3f0 980static void
56b8a8d2 981ldp_config_normalize(struct ldpd_conf *xconf)
eac6e3f0
RW
982{
983 struct l2vpn *l2vpn;
984 struct l2vpn_pw *pw;
985
986 if (!(xconf->flags & F_LDPD_ENABLED))
56b8a8d2 987 ldp_config_reset_main(xconf);
eac6e3f0
RW
988 else {
989 if (!(xconf->ipv4.flags & F_LDPD_AF_ENABLED))
56b8a8d2 990 ldp_config_reset_af(xconf, AF_INET);
eac6e3f0 991 if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED))
56b8a8d2 992 ldp_config_reset_af(xconf, AF_INET6);
eac6e3f0
RW
993 }
994
90d7e7bd 995 RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
20bacaeb 996 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
eac6e3f0
RW
997 if (pw->flags & F_PW_STATIC_NBR_ADDR)
998 continue;
999
1000 pw->af = AF_INET;
1001 pw->addr.v4 = pw->lsr_id;
1002 }
20bacaeb 1003 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
eac6e3f0
RW
1004 if (pw->flags & F_PW_STATIC_NBR_ADDR)
1005 continue;
1006
1007 pw->af = AF_INET;
1008 pw->addr.v4 = pw->lsr_id;
1009 }
1010 }
1011}
1012
1013static void
56b8a8d2 1014ldp_config_reset_main(struct ldpd_conf *conf)
eac6e3f0
RW
1015{
1016 struct iface *iface;
1017 struct nbr_params *nbrp;
1018
7d3d7491 1019 while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) {
7d3d7491 1020 RB_REMOVE(iface_head, &conf->iface_tree, iface);
eac6e3f0
RW
1021 free(iface);
1022 }
1023
76c4abd1 1024 while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) {
76c4abd1 1025 RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
eac6e3f0
RW
1026 free(nbrp);
1027 }
1028
1029 conf->rtr_id.s_addr = INADDR_ANY;
56b8a8d2
RW
1030 ldp_config_reset_af(conf, AF_INET);
1031 ldp_config_reset_af(conf, AF_INET6);
eac6e3f0
RW
1032 conf->lhello_holdtime = LINK_DFLT_HOLDTIME;
1033 conf->lhello_interval = DEFAULT_HELLO_INTERVAL;
1034 conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
1035 conf->thello_interval = DEFAULT_HELLO_INTERVAL;
1036 conf->trans_pref = DUAL_STACK_LDPOV6;
1037 conf->flags = 0;
1038}
1039
1040static void
56b8a8d2 1041ldp_config_reset_af(struct ldpd_conf *conf, int af)
eac6e3f0
RW
1042{
1043 struct ldpd_af_conf *af_conf;
1044 struct iface *iface;
1045 struct iface_af *ia;
1046 struct tnbr *tnbr, *ttmp;
1047
7d3d7491 1048 RB_FOREACH(iface, iface_head, &conf->iface_tree) {
eac6e3f0
RW
1049 ia = iface_af_get(iface, af);
1050 ia->enabled = 0;
1051 }
1052
7989cdba 1053 RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
eac6e3f0
RW
1054 if (tnbr->af != af)
1055 continue;
1056
7989cdba 1057 RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
eac6e3f0
RW
1058 free(tnbr);
1059 }
1060
1061 af_conf = ldp_af_conf_get(conf, af);
1062 af_conf->keepalive = 180;
1063 af_conf->lhello_holdtime = 0;
1064 af_conf->lhello_interval = 0;
1065 af_conf->thello_holdtime = 0;
1066 af_conf->thello_interval = 0;
1067 memset(&af_conf->trans_addr, 0, sizeof(af_conf->trans_addr));
1068 af_conf->flags = 0;
1069}
1070
1071struct ldpd_conf *
56b8a8d2 1072ldp_dup_config(struct ldpd_conf *conf)
eac6e3f0
RW
1073{
1074 struct ldpd_conf *xconf;
1075 struct iface *iface, *xi;
1076 struct tnbr *tnbr, *xt;
1077 struct nbr_params *nbrp, *xn;
1078 struct l2vpn *l2vpn, *xl;
1079 struct l2vpn_if *lif, *xf;
1080 struct l2vpn_pw *pw, *xp;
1081
b67c140b
RW
1082#define COPY(a, b) do { \
1083 a = calloc(1, sizeof(*a)); \
1084 if (a == NULL) \
1085 fatal(__func__); \
1086 *a = *b; \
b67c140b
RW
1087 } while (0)
1088
1089 COPY(xconf, conf);
7d3d7491 1090 RB_INIT(&xconf->iface_tree);
7989cdba 1091 RB_INIT(&xconf->tnbr_tree);
76c4abd1 1092 RB_INIT(&xconf->nbrp_tree);
90d7e7bd 1093 RB_INIT(&xconf->l2vpn_tree);
eac6e3f0 1094
7d3d7491 1095 RB_FOREACH(iface, iface_head, &conf->iface_tree) {
b67c140b 1096 COPY(xi, iface);
eac6e3f0
RW
1097 xi->ipv4.iface = xi;
1098 xi->ipv6.iface = xi;
7d3d7491 1099 RB_INSERT(iface_head, &xconf->iface_tree, xi);
eac6e3f0 1100 }
7989cdba 1101 RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) {
b67c140b 1102 COPY(xt, tnbr);
7989cdba 1103 RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt);
eac6e3f0 1104 }
76c4abd1 1105 RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) {
b67c140b 1106 COPY(xn, nbrp);
76c4abd1 1107 RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn);
eac6e3f0 1108 }
90d7e7bd 1109 RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) {
b67c140b 1110 COPY(xl, l2vpn);
029c1958 1111 RB_INIT(&xl->if_tree);
20bacaeb
RW
1112 RB_INIT(&xl->pw_tree);
1113 RB_INIT(&xl->pw_inactive_tree);
90d7e7bd 1114 RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl);
eac6e3f0 1115
029c1958 1116 RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
b67c140b 1117 COPY(xf, lif);
eac6e3f0 1118 xf->l2vpn = xl;
029c1958 1119 RB_INSERT(l2vpn_if_head, &xl->if_tree, xf);
eac6e3f0 1120 }
20bacaeb 1121 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
b67c140b 1122 COPY(xp, pw);
eac6e3f0 1123 xp->l2vpn = xl;
20bacaeb 1124 RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp);
eac6e3f0 1125 }
20bacaeb 1126 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
b67c140b 1127 COPY(xp, pw);
eac6e3f0 1128 xp->l2vpn = xl;
20bacaeb 1129 RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
eac6e3f0
RW
1130 }
1131 }
b67c140b 1132#undef COPY
eac6e3f0
RW
1133
1134 return (xconf);
1135}
1136
1137void
1138ldp_clear_config(struct ldpd_conf *xconf)
1139{
1140 struct iface *iface;
1141 struct tnbr *tnbr;
1142 struct nbr_params *nbrp;
1143 struct l2vpn *l2vpn;
1144
7d3d7491
RW
1145 while ((iface = RB_ROOT(&xconf->iface_tree)) != NULL) {
1146 RB_REMOVE(iface_head, &xconf->iface_tree, iface);
eac6e3f0
RW
1147 free(iface);
1148 }
7989cdba
RW
1149 while ((tnbr = RB_ROOT(&xconf->tnbr_tree)) != NULL) {
1150 RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
eac6e3f0
RW
1151 free(tnbr);
1152 }
76c4abd1
RW
1153 while ((nbrp = RB_ROOT(&xconf->nbrp_tree)) != NULL) {
1154 RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp);
eac6e3f0
RW
1155 free(nbrp);
1156 }
90d7e7bd
RW
1157 while ((l2vpn = RB_ROOT(&xconf->l2vpn_tree)) != NULL) {
1158 RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, l2vpn);
eac6e3f0
RW
1159 l2vpn_del(l2vpn);
1160 }
1161
1162 free(xconf);
1163}
1164
56b8a8d2
RW
1165void
1166merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
8429abe0
RW
1167{
1168 merge_global(conf, xconf);
1169 merge_af(AF_INET, &conf->ipv4, &xconf->ipv4);
1170 merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6);
56b8a8d2
RW
1171 merge_ifaces(conf, xconf);
1172 merge_tnbrs(conf, xconf);
1173 merge_nbrps(conf, xconf);
1174 merge_l2vpns(conf, xconf);
8429abe0
RW
1175 free(xconf);
1176}
1177
1178static void
1179merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
1180{
1181 /* change of router-id requires resetting all neighborships */
1182 if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
1183 if (ldpd_process == PROC_LDP_ENGINE) {
45a8eba9 1184 ldpe_reset_nbrs(AF_UNSPEC);
8429abe0
RW
1185 if (conf->rtr_id.s_addr == INADDR_ANY ||
1186 xconf->rtr_id.s_addr == INADDR_ANY) {
1187 if_update_all(AF_UNSPEC);
1188 tnbr_update_all(AF_UNSPEC);
1189 }
1190 }
1191 conf->rtr_id = xconf->rtr_id;
1192 }
1193
eac6e3f0
RW
1194 conf->lhello_holdtime = xconf->lhello_holdtime;
1195 conf->lhello_interval = xconf->lhello_interval;
1196 conf->thello_holdtime = xconf->thello_holdtime;
1197 conf->thello_interval = xconf->thello_interval;
1198
8429abe0
RW
1199 if (conf->trans_pref != xconf->trans_pref) {
1200 if (ldpd_process == PROC_LDP_ENGINE)
1201 ldpe_reset_ds_nbrs();
1202 conf->trans_pref = xconf->trans_pref;
1203 }
1204
1205 if ((conf->flags & F_LDPD_DS_CISCO_INTEROP) !=
1206 (xconf->flags & F_LDPD_DS_CISCO_INTEROP)) {
1207 if (ldpd_process == PROC_LDP_ENGINE)
1208 ldpe_reset_ds_nbrs();
1209 }
1210
1211 conf->flags = xconf->flags;
1212}
1213
1214static void
1215merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
1216{
45a8eba9
RW
1217 int stop_init_backoff = 0;
1218 int remove_dynamic_tnbrs = 0;
1219 int change_egress_label = 0;
1220 int reset_nbrs_ipv4 = 0;
1221 int reset_nbrs = 0;
1222 int update_sockets = 0;
1223
1224 /* update timers */
8429abe0
RW
1225 if (af_conf->keepalive != xa->keepalive) {
1226 af_conf->keepalive = xa->keepalive;
45a8eba9 1227 stop_init_backoff = 1;
8429abe0 1228 }
eac6e3f0
RW
1229 af_conf->lhello_holdtime = xa->lhello_holdtime;
1230 af_conf->lhello_interval = xa->lhello_interval;
8429abe0
RW
1231 af_conf->thello_holdtime = xa->thello_holdtime;
1232 af_conf->thello_interval = xa->thello_interval;
1233
1234 /* update flags */
45a8eba9 1235 if ((af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
8429abe0 1236 !(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
45a8eba9 1237 remove_dynamic_tnbrs = 1;
8429abe0
RW
1238 if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
1239 (xa->flags & F_LDPD_AF_NO_GTSM)) {
1240 if (af == AF_INET6)
1241 /* need to set/unset IPV6_MINHOPCOUNT */
1242 update_sockets = 1;
45a8eba9 1243 else
8429abe0 1244 /* for LDPv4 just resetting the neighbors is enough */
45a8eba9 1245 reset_nbrs_ipv4 = 1;
8429abe0 1246 }
8429abe0
RW
1247 if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
1248 (xa->flags & F_LDPD_AF_EXPNULL))
45a8eba9 1249 change_egress_label = 1;
8429abe0
RW
1250 af_conf->flags = xa->flags;
1251
45a8eba9 1252 /* update the transport address */
8429abe0
RW
1253 if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
1254 af_conf->trans_addr = xa->trans_addr;
1255 update_sockets = 1;
1256 }
1257
45a8eba9
RW
1258 /* update ACLs */
1259 if (strcmp(af_conf->acl_label_advertise_to,
1260 xa->acl_label_advertise_to) ||
1261 strcmp(af_conf->acl_label_advertise_for,
1262 xa->acl_label_advertise_for) ||
1263 strcmp(af_conf->acl_label_accept_from,
1264 xa->acl_label_accept_from) ||
1265 strcmp(af_conf->acl_label_accept_for,
1266 xa->acl_label_accept_for))
1267 reset_nbrs = 1;
1268 if (strcmp(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from))
1269 remove_dynamic_tnbrs = 1;
1270 if (strcmp(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for))
1271 change_egress_label = 1;
1272 strlcpy(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from,
1273 sizeof(af_conf->acl_thello_accept_from));
1274 strlcpy(af_conf->acl_label_allocate_for, xa->acl_label_allocate_for,
1275 sizeof(af_conf->acl_label_allocate_for));
1276 strlcpy(af_conf->acl_label_advertise_to, xa->acl_label_advertise_to,
1277 sizeof(af_conf->acl_label_advertise_to));
1278 strlcpy(af_conf->acl_label_advertise_for, xa->acl_label_advertise_for,
1279 sizeof(af_conf->acl_label_advertise_for));
1280 strlcpy(af_conf->acl_label_accept_from, xa->acl_label_accept_from,
1281 sizeof(af_conf->acl_label_accept_from));
1282 strlcpy(af_conf->acl_label_accept_for, xa->acl_label_accept_for,
1283 sizeof(af_conf->acl_label_accept_for));
1284 strlcpy(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for,
1285 sizeof(af_conf->acl_label_expnull_for));
1286
1287 /* apply the new configuration */
1288 switch (ldpd_process) {
1289 case PROC_LDE_ENGINE:
1290 if (change_egress_label)
1291 lde_change_egress_label(af);
1292 break;
1293 case PROC_LDP_ENGINE:
1294 if (stop_init_backoff)
1295 ldpe_stop_init_backoff(af);
1296 if (remove_dynamic_tnbrs)
1297 ldpe_remove_dynamic_tnbrs(af);
1298 if (reset_nbrs)
1299 ldpe_reset_nbrs(AF_UNSPEC);
1300 else if (reset_nbrs_ipv4)
1301 ldpe_reset_nbrs(AF_INET);
1302 break;
1303 case PROC_MAIN:
1304 if (update_sockets && iev_ldpe)
1305 imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af,
1306 0, -1, NULL, 0);
1307 break;
1308 }
8429abe0
RW
1309}
1310
1311static void
56b8a8d2 1312merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
8429abe0
RW
1313{
1314 struct iface *iface, *itmp, *xi;
1315
7d3d7491 1316 RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
8429abe0 1317 /* find deleted interfaces */
eac6e3f0 1318 if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
7d3d7491 1319 RB_REMOVE(iface_head, &conf->iface_tree, iface);
4af8997d
RW
1320
1321 switch (ldpd_process) {
1322 case PROC_LDE_ENGINE:
1323 break;
1324 case PROC_LDP_ENGINE:
8429abe0 1325 if_exit(iface);
4af8997d
RW
1326 break;
1327 case PROC_MAIN:
1328 QOBJ_UNREG (iface);
1329 break;
1330 }
8429abe0
RW
1331 free(iface);
1332 }
1333 }
7d3d7491 1334 RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
8429abe0 1335 /* find new interfaces */
eac6e3f0 1336 if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
7d3d7491
RW
1337 RB_REMOVE(iface_head, &xconf->iface_tree, xi);
1338 RB_INSERT(iface_head, &conf->iface_tree, xi);
8429abe0 1339
4af8997d
RW
1340 if (ldpd_process == PROC_MAIN) {
1341 QOBJ_REG (xi, iface);
1342 /* resend addresses to activate new interfaces */
8429abe0 1343 kif_redistribute(xi->name);
4af8997d 1344 }
8429abe0
RW
1345 continue;
1346 }
1347
1348 /* update existing interfaces */
1349 merge_iface_af(&iface->ipv4, &xi->ipv4);
1350 merge_iface_af(&iface->ipv6, &xi->ipv6);
7d3d7491 1351 RB_REMOVE(iface_head, &xconf->iface_tree, xi);
8429abe0
RW
1352 free(xi);
1353 }
1354}
1355
1356static void
1357merge_iface_af(struct iface_af *ia, struct iface_af *xi)
1358{
1359 if (ia->enabled != xi->enabled) {
1360 ia->enabled = xi->enabled;
1361 if (ldpd_process == PROC_LDP_ENGINE)
61cd1100 1362 ldp_if_update(ia->iface, ia->af);
8429abe0
RW
1363 }
1364 ia->hello_holdtime = xi->hello_holdtime;
1365 ia->hello_interval = xi->hello_interval;
1366}
1367
1368static void
56b8a8d2 1369merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
8429abe0
RW
1370{
1371 struct tnbr *tnbr, *ttmp, *xt;
1372
7989cdba 1373 RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
8429abe0
RW
1374 if (!(tnbr->flags & F_TNBR_CONFIGURED))
1375 continue;
1376
1377 /* find deleted tnbrs */
1378 if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) {
4af8997d
RW
1379 switch (ldpd_process) {
1380 case PROC_LDE_ENGINE:
7989cdba 1381 RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
4af8997d
RW
1382 free(tnbr);
1383 break;
1384 case PROC_LDP_ENGINE:
8429abe0 1385 tnbr->flags &= ~F_TNBR_CONFIGURED;
7989cdba 1386 tnbr_check(conf, tnbr);
4af8997d
RW
1387 break;
1388 case PROC_MAIN:
7989cdba 1389 RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
4af8997d 1390 QOBJ_UNREG (tnbr);
8429abe0 1391 free(tnbr);
4af8997d 1392 break;
8429abe0
RW
1393 }
1394 }
1395 }
7989cdba 1396 RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) {
8429abe0
RW
1397 /* find new tnbrs */
1398 if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
7989cdba
RW
1399 RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
1400 RB_INSERT(tnbr_head, &conf->tnbr_tree, xt);
8429abe0 1401
4af8997d
RW
1402 switch (ldpd_process) {
1403 case PROC_LDE_ENGINE:
1404 break;
1405 case PROC_LDP_ENGINE:
8429abe0 1406 tnbr_update(xt);
4af8997d
RW
1407 break;
1408 case PROC_MAIN:
1409 QOBJ_REG (xt, tnbr);
1410 break;
1411 }
8429abe0
RW
1412 continue;
1413 }
1414
1415 /* update existing tnbrs */
1416 if (!(tnbr->flags & F_TNBR_CONFIGURED))
1417 tnbr->flags |= F_TNBR_CONFIGURED;
7989cdba 1418 RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
8429abe0
RW
1419 free(xt);
1420 }
1421}
1422
1423static void
56b8a8d2 1424merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
8429abe0
RW
1425{
1426 struct nbr_params *nbrp, *ntmp, *xn;
1427 struct nbr *nbr;
1428 int nbrp_changed;
1429
76c4abd1 1430 RB_FOREACH_SAFE(nbrp, nbrp_head, &conf->nbrp_tree, ntmp) {
8429abe0
RW
1431 /* find deleted nbrps */
1432 if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
4af8997d
RW
1433 switch (ldpd_process) {
1434 case PROC_LDE_ENGINE:
1435 break;
1436 case PROC_LDP_ENGINE:
8429abe0
RW
1437 nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
1438 if (nbr) {
1439 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
eac6e3f0 1440#ifdef __OpenBSD__
8429abe0 1441 pfkey_remove(nbr);
eac6e3f0
RW
1442#else
1443 sock_set_md5sig(
1444 (ldp_af_global_get(&global,
1445 nbr->af))->ldp_session_socket,
1446 nbr->af, &nbr->raddr, NULL);
1447#endif
0f7b5df9 1448 nbr->auth.method = AUTH_NONE;
8429abe0
RW
1449 if (nbr_session_active_role(nbr))
1450 nbr_establish_connection(nbr);
1451 }
4af8997d
RW
1452 break;
1453 case PROC_MAIN:
1454 QOBJ_UNREG (nbrp);
1455 break;
8429abe0 1456 }
76c4abd1 1457 RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
8429abe0
RW
1458 free(nbrp);
1459 }
1460 }
76c4abd1 1461 RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) {
8429abe0
RW
1462 /* find new nbrps */
1463 if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
76c4abd1
RW
1464 RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
1465 RB_INSERT(nbrp_head, &conf->nbrp_tree, xn);
8429abe0 1466
4af8997d
RW
1467 switch (ldpd_process) {
1468 case PROC_LDE_ENGINE:
1469 break;
1470 case PROC_LDP_ENGINE:
8429abe0
RW
1471 nbr = nbr_find_ldpid(xn->lsr_id.s_addr);
1472 if (nbr) {
1473 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
0f7b5df9 1474 nbr->auth.method = xn->auth.method;
eac6e3f0 1475#ifdef __OpenBSD__
8429abe0
RW
1476 if (pfkey_establish(nbr, xn) == -1)
1477 fatalx("pfkey setup failed");
eac6e3f0
RW
1478#else
1479 sock_set_md5sig(
1480 (ldp_af_global_get(&global,
1481 nbr->af))->ldp_session_socket,
1482 nbr->af, &nbr->raddr,
1483 xn->auth.md5key);
1484#endif
8429abe0
RW
1485 if (nbr_session_active_role(nbr))
1486 nbr_establish_connection(nbr);
1487 }
4af8997d
RW
1488 break;
1489 case PROC_MAIN:
1490 QOBJ_REG (xn, nbr_params);
1491 break;
8429abe0
RW
1492 }
1493 continue;
1494 }
1495
1496 /* update existing nbrps */
1497 if (nbrp->flags != xn->flags ||
1498 nbrp->keepalive != xn->keepalive ||
1499 nbrp->gtsm_enabled != xn->gtsm_enabled ||
1500 nbrp->gtsm_hops != xn->gtsm_hops ||
1501 nbrp->auth.method != xn->auth.method ||
1502 strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0)
1503 nbrp_changed = 1;
1504 else
1505 nbrp_changed = 0;
1506
1507 nbrp->keepalive = xn->keepalive;
1508 nbrp->gtsm_enabled = xn->gtsm_enabled;
1509 nbrp->gtsm_hops = xn->gtsm_hops;
1510 nbrp->auth.method = xn->auth.method;
1511 strlcpy(nbrp->auth.md5key, xn->auth.md5key,
1512 sizeof(nbrp->auth.md5key));
1513 nbrp->auth.md5key_len = xn->auth.md5key_len;
1514 nbrp->flags = xn->flags;
1515
1516 if (ldpd_process == PROC_LDP_ENGINE) {
1517 nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
1518 if (nbr && nbrp_changed) {
1519 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
eac6e3f0 1520#ifdef __OpenBSD__
8429abe0 1521 pfkey_remove(nbr);
0f7b5df9 1522 nbr->auth.method = nbrp->auth.method;
8429abe0
RW
1523 if (pfkey_establish(nbr, nbrp) == -1)
1524 fatalx("pfkey setup failed");
eac6e3f0 1525#else
0f7b5df9 1526 nbr->auth.method = nbrp->auth.method;
eac6e3f0
RW
1527 sock_set_md5sig((ldp_af_global_get(&global,
1528 nbr->af))->ldp_session_socket, nbr->af,
1529 &nbr->raddr, nbrp->auth.md5key);
1530#endif
8429abe0
RW
1531 if (nbr_session_active_role(nbr))
1532 nbr_establish_connection(nbr);
1533 }
1534 }
76c4abd1 1535 RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
8429abe0
RW
1536 free(xn);
1537 }
1538}
1539
1540static void
56b8a8d2 1541merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
8429abe0
RW
1542{
1543 struct l2vpn *l2vpn, *ltmp, *xl;
4af8997d
RW
1544 struct l2vpn_if *lif;
1545 struct l2vpn_pw *pw;
8429abe0 1546
90d7e7bd 1547 RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
8429abe0
RW
1548 /* find deleted l2vpns */
1549 if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
90d7e7bd 1550 RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
8429abe0
RW
1551
1552 switch (ldpd_process) {
1553 case PROC_LDE_ENGINE:
1554 l2vpn_exit(l2vpn);
1555 break;
1556 case PROC_LDP_ENGINE:
1557 ldpe_l2vpn_exit(l2vpn);
1558 break;
1559 case PROC_MAIN:
029c1958 1560 RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
4af8997d 1561 QOBJ_UNREG (lif);
20bacaeb 1562 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
4af8997d 1563 QOBJ_UNREG (pw);
20bacaeb 1564 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
4af8997d
RW
1565 QOBJ_UNREG (pw);
1566 QOBJ_UNREG (l2vpn);
8429abe0
RW
1567 break;
1568 }
1569 l2vpn_del(l2vpn);
1570 }
1571 }
90d7e7bd 1572 RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
8429abe0
RW
1573 /* find new l2vpns */
1574 if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
90d7e7bd
RW
1575 RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
1576 RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl);
8429abe0
RW
1577
1578 switch (ldpd_process) {
1579 case PROC_LDE_ENGINE:
1580 l2vpn_init(xl);
1581 break;
1582 case PROC_LDP_ENGINE:
1583 ldpe_l2vpn_init(xl);
1584 break;
1585 case PROC_MAIN:
4af8997d 1586 QOBJ_REG (xl, l2vpn);
8429abe0
RW
1587 break;
1588 }
1589 continue;
1590 }
1591
1592 /* update existing l2vpns */
56b8a8d2 1593 merge_l2vpn(conf, l2vpn, xl);
90d7e7bd 1594 RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
8429abe0
RW
1595 free(xl);
1596 }
1597}
1598
1599static void
56b8a8d2 1600merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
8429abe0
RW
1601{
1602 struct l2vpn_if *lif, *ftmp, *xf;
1603 struct l2vpn_pw *pw, *ptmp, *xp;
1604 struct nbr *nbr;
1605 int reset_nbr, reinstall_pwfec, reinstall_tnbr;
20bacaeb 1606 struct l2vpn_pw_head pw_aux_list;
8429abe0
RW
1607 int previous_pw_type, previous_mtu;
1608
1609 previous_pw_type = l2vpn->pw_type;
1610 previous_mtu = l2vpn->mtu;
1611
1612 /* merge intefaces */
029c1958 1613 RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
8429abe0 1614 /* find deleted interfaces */
eac6e3f0 1615 if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) {
4af8997d
RW
1616 if (ldpd_process == PROC_MAIN)
1617 QOBJ_UNREG (lif);
029c1958 1618 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
8429abe0
RW
1619 free(lif);
1620 }
1621 }
029c1958 1622 RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) {
8429abe0 1623 /* find new interfaces */
eac6e3f0 1624 if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) {
029c1958
RW
1625 RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
1626 RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
8429abe0 1627 xf->l2vpn = l2vpn;
4af8997d
RW
1628 if (ldpd_process == PROC_MAIN)
1629 QOBJ_REG (xf, l2vpn_if);
8429abe0
RW
1630 continue;
1631 }
1632
029c1958 1633 RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
8429abe0
RW
1634 free(xf);
1635 }
1636
eac6e3f0 1637 /* merge active pseudowires */
20bacaeb
RW
1638 RB_INIT(&pw_aux_list);
1639 RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
eac6e3f0
RW
1640 /* find deleted active pseudowires */
1641 if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) {
8429abe0
RW
1642 switch (ldpd_process) {
1643 case PROC_LDE_ENGINE:
1644 l2vpn_pw_exit(pw);
1645 break;
1646 case PROC_LDP_ENGINE:
1647 ldpe_l2vpn_pw_exit(pw);
1648 break;
1649 case PROC_MAIN:
4af8997d 1650 QOBJ_UNREG (pw);
8429abe0
RW
1651 break;
1652 }
1653
20bacaeb 1654 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
8429abe0
RW
1655 free(pw);
1656 }
1657 }
20bacaeb 1658 RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
eac6e3f0
RW
1659 /* find new active pseudowires */
1660 if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
20bacaeb
RW
1661 RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
1662 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp);
8429abe0
RW
1663 xp->l2vpn = l2vpn;
1664
1665 switch (ldpd_process) {
1666 case PROC_LDE_ENGINE:
1667 l2vpn_pw_init(xp);
1668 break;
1669 case PROC_LDP_ENGINE:
1670 ldpe_l2vpn_pw_init(xp);
1671 break;
1672 case PROC_MAIN:
4af8997d 1673 QOBJ_REG (xp, l2vpn_pw);
8429abe0
RW
1674 break;
1675 }
1676 continue;
1677 }
1678
eac6e3f0 1679 /* update existing active pseudowire */
8429abe0
RW
1680 if (pw->af != xp->af ||
1681 ldp_addrcmp(pw->af, &pw->addr, &xp->addr))
1682 reinstall_tnbr = 1;
1683 else
1684 reinstall_tnbr = 0;
1685
1686 /* changes that require a session restart */
1687 if ((pw->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)) !=
1688 (xp->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)))
1689 reset_nbr = 1;
1690 else
1691 reset_nbr = 0;
1692
1693 if (l2vpn->pw_type != xl->pw_type || l2vpn->mtu != xl->mtu ||
1694 pw->pwid != xp->pwid || reinstall_tnbr || reset_nbr ||
1695 pw->lsr_id.s_addr != xp->lsr_id.s_addr)
1696 reinstall_pwfec = 1;
1697 else
1698 reinstall_pwfec = 0;
1699
eac6e3f0
RW
1700 /* check if the pseudowire should be disabled */
1701 if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) {
1702 reinstall_tnbr = 0;
1703 reset_nbr = 0;
1704 reinstall_pwfec = 0;
1705
1706 switch (ldpd_process) {
1707 case PROC_LDE_ENGINE:
1708 l2vpn_pw_exit(pw);
1709 break;
1710 case PROC_LDP_ENGINE:
1711 ldpe_l2vpn_pw_exit(pw);
1712 break;
1713 case PROC_MAIN:
1714 break;
1715 }
1716
1717 /* remove from active list */
20bacaeb
RW
1718 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
1719 RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw);
eac6e3f0
RW
1720 }
1721
8429abe0
RW
1722 if (ldpd_process == PROC_LDP_ENGINE) {
1723 if (reinstall_tnbr)
1724 ldpe_l2vpn_pw_exit(pw);
1725 if (reset_nbr) {
1726 nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
1727 if (nbr && nbr->state == NBR_STA_OPER)
1728 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
1729 }
1730 }
1731 if (ldpd_process == PROC_LDE_ENGINE &&
1732 !reset_nbr && reinstall_pwfec)
1733 l2vpn_pw_exit(pw);
1734 pw->lsr_id = xp->lsr_id;
1735 pw->af = xp->af;
1736 pw->addr = xp->addr;
1737 pw->pwid = xp->pwid;
1738 strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
1739 pw->ifindex = xp->ifindex;
1740 if (xp->flags & F_PW_CWORD_CONF)
1741 pw->flags |= F_PW_CWORD_CONF;
1742 else
1743 pw->flags &= ~F_PW_CWORD_CONF;
1744 if (xp->flags & F_PW_STATUSTLV_CONF)
1745 pw->flags |= F_PW_STATUSTLV_CONF;
1746 else
1747 pw->flags &= ~F_PW_STATUSTLV_CONF;
eac6e3f0
RW
1748 if (xp->flags & F_PW_STATIC_NBR_ADDR)
1749 pw->flags |= F_PW_STATIC_NBR_ADDR;
1750 else
1751 pw->flags &= ~F_PW_STATIC_NBR_ADDR;
8429abe0
RW
1752 if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr)
1753 ldpe_l2vpn_pw_init(pw);
1754 if (ldpd_process == PROC_LDE_ENGINE &&
1755 !reset_nbr && reinstall_pwfec) {
1756 l2vpn->pw_type = xl->pw_type;
1757 l2vpn->mtu = xl->mtu;
1758 l2vpn_pw_init(pw);
1759 l2vpn->pw_type = previous_pw_type;
1760 l2vpn->mtu = previous_mtu;
1761 }
1762
20bacaeb 1763 RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
8429abe0
RW
1764 free(xp);
1765 }
1766
eac6e3f0 1767 /* merge inactive pseudowires */
20bacaeb 1768 RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) {
eac6e3f0
RW
1769 /* find deleted inactive pseudowires */
1770 if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) {
20bacaeb 1771 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
4af8997d
RW
1772 if (ldpd_process == PROC_MAIN)
1773 QOBJ_UNREG (pw);
eac6e3f0
RW
1774 free(pw);
1775 }
1776 }
20bacaeb 1777 RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
eac6e3f0
RW
1778 /* find new inactive pseudowires */
1779 if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
20bacaeb
RW
1780 RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
1781 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
eac6e3f0 1782 xp->l2vpn = l2vpn;
4af8997d
RW
1783 if (ldpd_process == PROC_MAIN)
1784 QOBJ_REG (xp, l2vpn_pw);
eac6e3f0
RW
1785 continue;
1786 }
1787
1788 /* update existing inactive pseudowire */
1789 pw->lsr_id.s_addr = xp->lsr_id.s_addr;
1790 pw->af = xp->af;
1791 pw->addr = xp->addr;
1792 pw->pwid = xp->pwid;
1793 strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
1794 pw->ifindex = xp->ifindex;
1795 pw->flags = xp->flags;
1796
1797 /* check if the pseudowire should be activated */
1798 if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) {
1799 /* remove from inactive list */
20bacaeb
RW
1800 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
1801 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
eac6e3f0
RW
1802
1803 switch (ldpd_process) {
1804 case PROC_LDE_ENGINE:
1805 l2vpn_pw_init(pw);
1806 break;
1807 case PROC_LDP_ENGINE:
1808 ldpe_l2vpn_pw_init(pw);
1809 break;
1810 case PROC_MAIN:
1811 break;
1812 }
1813 }
1814
20bacaeb 1815 RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
eac6e3f0
RW
1816 free(xp);
1817 }
1818
1819 /* insert pseudowires that were disabled in the inactive list */
20bacaeb
RW
1820 RB_FOREACH_SAFE(pw, l2vpn_pw_head, &pw_aux_list, ptmp) {
1821 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
1822 RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
eac6e3f0
RW
1823 }
1824
8429abe0
RW
1825 l2vpn->pw_type = xl->pw_type;
1826 l2vpn->mtu = xl->mtu;
1827 strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname));
1828 l2vpn->br_ifindex = xl->br_ifindex;
1829}
1830
1831struct ldpd_conf *
1832config_new_empty(void)
1833{
1834 struct ldpd_conf *xconf;
1835
1836 xconf = calloc(1, sizeof(*xconf));
1837 if (xconf == NULL)
1838 fatal(NULL);
1839
7d3d7491 1840 RB_INIT(&xconf->iface_tree);
7989cdba 1841 RB_INIT(&xconf->tnbr_tree);
76c4abd1 1842 RB_INIT(&xconf->nbrp_tree);
90d7e7bd 1843 RB_INIT(&xconf->l2vpn_tree);
8429abe0
RW
1844
1845 return (xconf);
1846}
1847
1848void
1849config_clear(struct ldpd_conf *conf)
1850{
1851 struct ldpd_conf *xconf;
1852
1853 /*
1854 * Merge current config with an empty config, this will deactivate
1855 * and deallocate all the interfaces, pseudowires and so on. Before
1856 * merging, copy the router-id and other variables to avoid some
1857 * unnecessary operations, like trying to reset the neighborships.
1858 */
1859 xconf = config_new_empty();
1860 xconf->ipv4 = conf->ipv4;
1861 xconf->ipv6 = conf->ipv6;
1862 xconf->rtr_id = conf->rtr_id;
1863 xconf->trans_pref = conf->trans_pref;
1864 xconf->flags = conf->flags;
1865 merge_config(conf, xconf);
1866 free(conf);
1867}