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