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