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