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