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