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