1 /* $OpenBSD: ldpd.c,v 1.79 2024/11/21 13:38:14 claudio Exp $ */
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
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <err.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <pwd.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <unistd.h>
33
34 #include "ldpd.h"
35 #include "ldpe.h"
36 #include "lde.h"
37 #include "log.h"
38
39 static void main_sig_handler(int, short, void *);
40 static __dead void usage(void);
41 static __dead void ldpd_shutdown(void);
42 static pid_t start_child(enum ldpd_process, char *, int, int, int,
43 char *);
44 static void main_dispatch_ldpe(int, short, void *);
45 static void main_dispatch_lde(int, short, void *);
46 static int main_imsg_compose_both(enum imsg_type, void *,
47 uint16_t);
48 static int main_imsg_send_ipc_sockets(struct imsgbuf *,
49 struct imsgbuf *);
50 static void main_imsg_send_net_sockets(int);
51 static void main_imsg_send_net_socket(int, enum socket_type);
52 static int main_imsg_send_config(struct ldpd_conf *);
53 static int ldp_reload(void);
54 static void merge_global(struct ldpd_conf *, struct ldpd_conf *);
55 static void merge_af(int, struct ldpd_af_conf *,
56 struct ldpd_af_conf *);
57 static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *);
58 static void merge_iface_af(struct iface_af *, struct iface_af *);
59 static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *);
60 static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *);
61 static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *);
62 static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *,
63 struct l2vpn *);
64 static void merge_auths(struct ldpd_conf *, struct ldpd_conf *);
65
66 enum ldpd_process ldpd_process;
67 struct ldpd_global global;
68 struct ldpd_conf *ldpd_conf;
69
70 static char *conffile;
71 static struct imsgev *iev_ldpe;
72 static struct imsgev *iev_lde;
73 static pid_t ldpe_pid;
74 static pid_t lde_pid;
75
76 static void
main_sig_handler(int sig,short event,void * arg)77 main_sig_handler(int sig, short event, void *arg)
78 {
79 /* signal handler rules don't apply, libevent decouples for us */
80 switch (sig) {
81 case SIGTERM:
82 case SIGINT:
83 ldpd_shutdown();
84 /* NOTREACHED */
85 case SIGHUP:
86 if (ldp_reload() == -1)
87 log_warnx("configuration reload failed");
88 else
89 log_debug("configuration reloaded");
90 break;
91 default:
92 fatalx("unexpected signal");
93 /* NOTREACHED */
94 }
95 }
96
97 static __dead void
usage(void)98 usage(void)
99 {
100 extern char *__progname;
101
102 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]"
103 " [-s socket]\n", __progname);
104 exit(1);
105 }
106
107 int
main(int argc,char * argv[])108 main(int argc, char *argv[])
109 {
110 struct event ev_sigint, ev_sigterm, ev_sighup;
111 char *saved_argv0;
112 int ch;
113 int debug = 0, lflag = 0, eflag = 0;
114 char *sockname;
115 int pipe_parent2ldpe[2];
116 int pipe_parent2lde[2];
117
118 conffile = CONF_FILE;
119 ldpd_process = PROC_MAIN;
120 log_procname = "parent";
121 sockname = LDPD_SOCKET;
122
123 log_init(1); /* log to stderr until daemonized */
124 log_verbose(1);
125
126 saved_argv0 = argv[0];
127 if (saved_argv0 == NULL)
128 saved_argv0 = "ldpd";
129
130 while ((ch = getopt(argc, argv, "dD:f:ns:vLE")) != -1) {
131 switch (ch) {
132 case 'd':
133 debug = 1;
134 break;
135 case 'D':
136 if (cmdline_symset(optarg) < 0)
137 log_warnx("could not parse macro definition %s",
138 optarg);
139 break;
140 case 'f':
141 conffile = optarg;
142 break;
143 case 'n':
144 global.cmd_opts |= LDPD_OPT_NOACTION;
145 break;
146 case 's':
147 sockname = optarg;
148 break;
149 case 'v':
150 if (global.cmd_opts & LDPD_OPT_VERBOSE)
151 global.cmd_opts |= LDPD_OPT_VERBOSE2;
152 global.cmd_opts |= LDPD_OPT_VERBOSE;
153 break;
154 case 'L':
155 lflag = 1;
156 break;
157 case 'E':
158 eflag = 1;
159 break;
160 default:
161 usage();
162 /* NOTREACHED */
163 }
164 }
165
166 argc -= optind;
167 argv += optind;
168 if (argc > 0 || (lflag && eflag))
169 usage();
170
171 if (lflag)
172 lde(debug, global.cmd_opts & LDPD_OPT_VERBOSE);
173 else if (eflag)
174 ldpe(debug, global.cmd_opts & LDPD_OPT_VERBOSE, sockname);
175
176 /* fetch interfaces early */
177 kif_init();
178
179 /* parse config file */
180 if ((ldpd_conf = parse_config(conffile)) == NULL ) {
181 kif_clear();
182 exit(1);
183 }
184
185 if (global.cmd_opts & LDPD_OPT_NOACTION) {
186 if (global.cmd_opts & LDPD_OPT_VERBOSE)
187 print_config(ldpd_conf);
188 else
189 fprintf(stderr, "configuration OK\n");
190 kif_clear();
191 exit(0);
192 }
193
194 /* check for root privileges */
195 if (geteuid())
196 errx(1, "need root privileges");
197
198 /* check for ldpd user */
199 if (getpwnam(LDPD_USER) == NULL)
200 errx(1, "unknown user %s", LDPD_USER);
201
202 log_init(debug);
203 log_verbose(global.cmd_opts & (LDPD_OPT_VERBOSE | LDPD_OPT_VERBOSE2));
204
205 if (!debug)
206 daemon(1, 0);
207
208 log_info("startup");
209
210 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
211 PF_UNSPEC, pipe_parent2ldpe) == -1)
212 fatal("socketpair");
213 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
214 PF_UNSPEC, pipe_parent2lde) == -1)
215 fatal("socketpair");
216
217 /* start children */
218 lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
219 pipe_parent2lde[1], debug, global.cmd_opts & LDPD_OPT_VERBOSE,
220 NULL);
221 ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
222 pipe_parent2ldpe[1], debug, global.cmd_opts & LDPD_OPT_VERBOSE,
223 sockname);
224
225 if (unveil("/", "r") == -1)
226 fatal("unveil /");
227 if (unveil(NULL, NULL) == -1)
228 fatal("unveil");
229
230 event_init();
231
232 /* setup signal handler */
233 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
234 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
235 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
236 signal_add(&ev_sigint, NULL);
237 signal_add(&ev_sigterm, NULL);
238 signal_add(&ev_sighup, NULL);
239 signal(SIGPIPE, SIG_IGN);
240
241 /* setup pipes to children */
242 if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL ||
243 (iev_lde = malloc(sizeof(struct imsgev))) == NULL)
244 fatal(NULL);
245 if (imsgbuf_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]) == -1)
246 fatal(NULL);
247 imsgbuf_allow_fdpass(&iev_ldpe->ibuf);
248 iev_ldpe->handler = main_dispatch_ldpe;
249 if (imsgbuf_init(&iev_lde->ibuf, pipe_parent2lde[0]) == -1)
250 fatal(NULL);
251 imsgbuf_allow_fdpass(&iev_lde->ibuf);
252 iev_lde->handler = main_dispatch_lde;
253
254 /* setup event handler */
255 iev_ldpe->events = EV_READ;
256 event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events,
257 iev_ldpe->handler, iev_ldpe);
258 event_add(&iev_ldpe->ev, NULL);
259
260 iev_lde->events = EV_READ;
261 event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events,
262 iev_lde->handler, iev_lde);
263 event_add(&iev_lde->ev, NULL);
264
265 if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
266 fatal("could not establish imsg links");
267 main_imsg_send_config(ldpd_conf);
268
269 if (kr_init(!(ldpd_conf->flags & F_LDPD_NO_FIB_UPDATE),
270 ldpd_conf->rdomain) == -1)
271 fatalx("kr_init failed");
272
273 /* notify ldpe about existing interfaces and addresses */
274 kif_redistribute(NULL);
275
276 if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED)
277 main_imsg_send_net_sockets(AF_INET);
278 if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED)
279 main_imsg_send_net_sockets(AF_INET6);
280
281 /* remove unneeded stuff from config */
282 /* ... */
283
284 event_dispatch();
285
286 ldpd_shutdown();
287 /* NOTREACHED */
288 return (0);
289 }
290
291 static __dead void
ldpd_shutdown(void)292 ldpd_shutdown(void)
293 {
294 pid_t pid;
295 int status;
296
297 /* close pipes */
298 imsgbuf_clear(&iev_ldpe->ibuf);
299 close(iev_ldpe->ibuf.fd);
300 imsgbuf_clear(&iev_lde->ibuf);
301 close(iev_lde->ibuf.fd);
302
303 kr_shutdown();
304 config_clear(ldpd_conf);
305
306 log_debug("waiting for children to terminate");
307 do {
308 pid = wait(&status);
309 if (pid == -1) {
310 if (errno != EINTR && errno != ECHILD)
311 fatal("wait");
312 } else if (WIFSIGNALED(status))
313 log_warnx("%s terminated; signal %d",
314 (pid == lde_pid) ? "label decision engine" :
315 "ldp engine", WTERMSIG(status));
316 } while (pid != -1 || (pid == -1 && errno == EINTR));
317
318 free(iev_ldpe);
319 free(iev_lde);
320
321 log_info("terminating");
322 exit(0);
323 }
324
325 static pid_t
start_child(enum ldpd_process p,char * argv0,int fd,int debug,int verbose,char * sockname)326 start_child(enum ldpd_process p, char *argv0, int fd, int debug, int verbose,
327 char *sockname)
328 {
329 char *argv[7];
330 int argc = 0;
331 pid_t pid;
332
333 switch (pid = fork()) {
334 case -1:
335 fatal("cannot fork");
336 case 0:
337 break;
338 default:
339 close(fd);
340 return (pid);
341 }
342
343 if (fd != 3) {
344 if (dup2(fd, 3) == -1)
345 fatal("cannot setup imsg fd");
346 } else if (fcntl(fd, F_SETFD, 0) == -1)
347 fatal("cannot setup imsg fd");
348
349 argv[argc++] = argv0;
350 switch (p) {
351 case PROC_MAIN:
352 fatalx("Can not start main process");
353 case PROC_LDE_ENGINE:
354 argv[argc++] = "-L";
355 break;
356 case PROC_LDP_ENGINE:
357 argv[argc++] = "-E";
358 break;
359 }
360 if (debug)
361 argv[argc++] = "-d";
362 if (verbose)
363 argv[argc++] = "-v";
364 if (sockname) {
365 argv[argc++] = "-s";
366 argv[argc++] = sockname;
367 }
368 argv[argc++] = NULL;
369
370 execvp(argv0, argv);
371 fatal("execvp");
372 }
373
374 /* imsg handling */
375 static void
main_dispatch_ldpe(int fd,short event,void * bula)376 main_dispatch_ldpe(int fd, short event, void *bula)
377 {
378 struct imsgev *iev = bula;
379 struct imsgbuf *ibuf = &iev->ibuf;
380 struct imsg imsg;
381 int af;
382 ssize_t n;
383 int shut = 0, verbose;
384
385 if (event & EV_READ) {
386 if ((n = imsgbuf_read(ibuf)) == -1)
387 fatal("imsgbuf_read error");
388 if (n == 0) /* connection closed */
389 shut = 1;
390 }
391 if (event & EV_WRITE) {
392 if (imsgbuf_write(ibuf) == -1) {
393 if (errno == EPIPE) /* connection closed */
394 shut = 1;
395 else
396 fatal("imsgbuf_write");
397 }
398 }
399
400 for (;;) {
401 if ((n = imsg_get(ibuf, &imsg)) == -1)
402 fatal("imsg_get");
403
404 if (n == 0)
405 break;
406
407 switch (imsg.hdr.type) {
408 case IMSG_REQUEST_SOCKETS:
409 af = imsg.hdr.pid;
410 main_imsg_send_net_sockets(af);
411 break;
412 case IMSG_CTL_RELOAD:
413 if (ldp_reload() == -1)
414 log_warnx("configuration reload failed");
415 else
416 log_debug("configuration reloaded");
417 break;
418 case IMSG_CTL_FIB_COUPLE:
419 kr_fib_couple();
420 break;
421 case IMSG_CTL_FIB_DECOUPLE:
422 kr_fib_decouple();
423 break;
424 case IMSG_CTL_KROUTE:
425 case IMSG_CTL_KROUTE_ADDR:
426 kr_show_route(&imsg);
427 break;
428 case IMSG_CTL_IFINFO:
429 if (imsg.hdr.len == IMSG_HEADER_SIZE)
430 kr_ifinfo(NULL, imsg.hdr.pid);
431 else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ)
432 kr_ifinfo(imsg.data, imsg.hdr.pid);
433 else
434 log_warnx("IFINFO request with wrong len");
435 break;
436 case IMSG_CTL_LOG_VERBOSE:
437 /* already checked by ldpe */
438 memcpy(&verbose, imsg.data, sizeof(verbose));
439 log_verbose(verbose);
440 break;
441 default:
442 log_debug("%s: error handling imsg %d", __func__,
443 imsg.hdr.type);
444 break;
445 }
446 imsg_free(&imsg);
447 }
448 if (!shut)
449 imsg_event_add(iev);
450 else {
451 /* this pipe is dead, so remove the event handler */
452 event_del(&iev->ev);
453 event_loopexit(NULL);
454 }
455 }
456
457 static void
main_dispatch_lde(int fd,short event,void * bula)458 main_dispatch_lde(int fd, short event, void *bula)
459 {
460 struct imsgev *iev = bula;
461 struct imsgbuf *ibuf = &iev->ibuf;
462 struct imsg imsg;
463 ssize_t n;
464 int shut = 0;
465
466 if (event & EV_READ) {
467 if ((n = imsgbuf_read(ibuf)) == -1)
468 fatal("imsgbuf_read error");
469 if (n == 0) /* connection closed */
470 shut = 1;
471 }
472 if (event & EV_WRITE) {
473 if (imsgbuf_write(ibuf) == -1) {
474 if (errno == EPIPE) /* connection closed */
475 shut = 1;
476 else
477 fatal("imsgbuf_write");
478 }
479 }
480
481 for (;;) {
482 if ((n = imsg_get(ibuf, &imsg)) == -1)
483 fatal("imsg_get");
484
485 if (n == 0)
486 break;
487
488 switch (imsg.hdr.type) {
489 case IMSG_KLABEL_CHANGE:
490 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
491 sizeof(struct kroute))
492 fatalx("invalid size of IMSG_KLABEL_CHANGE");
493 if (kr_change(imsg.data))
494 log_warnx("%s: error changing route", __func__);
495 break;
496 case IMSG_KLABEL_DELETE:
497 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
498 sizeof(struct kroute))
499 fatalx("invalid size of IMSG_KLABEL_DELETE");
500 if (kr_delete(imsg.data))
501 log_warnx("%s: error deleting route", __func__);
502 break;
503 case IMSG_KPWLABEL_CHANGE:
504 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
505 sizeof(struct kpw))
506 fatalx("invalid size of IMSG_KPWLABEL_CHANGE");
507 if (kmpw_set(imsg.data))
508 log_warnx("%s: error changing pseudowire",
509 __func__);
510 break;
511 case IMSG_KPWLABEL_DELETE:
512 if (imsg.hdr.len - IMSG_HEADER_SIZE !=
513 sizeof(struct kpw))
514 fatalx("invalid size of IMSG_KPWLABEL_DELETE");
515 if (kmpw_unset(imsg.data))
516 log_warnx("%s: error unsetting pseudowire",
517 __func__);
518 break;
519 default:
520 log_debug("%s: error handling imsg %d", __func__,
521 imsg.hdr.type);
522 break;
523 }
524 imsg_free(&imsg);
525 }
526 if (!shut)
527 imsg_event_add(iev);
528 else {
529 /* this pipe is dead, so remove the event handler */
530 event_del(&iev->ev);
531 event_loopexit(NULL);
532 }
533 }
534
535 void
main_imsg_compose_ldpe(int type,pid_t pid,void * data,uint16_t datalen)536 main_imsg_compose_ldpe(int type, pid_t pid, void *data, uint16_t datalen)
537 {
538 if (iev_ldpe == NULL)
539 return;
540 imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen);
541 }
542
543 void
main_imsg_compose_lde(int type,pid_t pid,void * data,uint16_t datalen)544 main_imsg_compose_lde(int type, pid_t pid, void *data, uint16_t datalen)
545 {
546 imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen);
547 }
548
549 static int
main_imsg_compose_both(enum imsg_type type,void * buf,uint16_t len)550 main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len)
551 {
552 if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1)
553 return (-1);
554 if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1)
555 return (-1);
556 return (0);
557 }
558
559 void
imsg_event_add(struct imsgev * iev)560 imsg_event_add(struct imsgev *iev)
561 {
562 iev->events = EV_READ;
563 if (imsgbuf_queuelen(&iev->ibuf) > 0)
564 iev->events |= EV_WRITE;
565
566 event_del(&iev->ev);
567 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
568 event_add(&iev->ev, NULL);
569 }
570
571 int
imsg_compose_event(struct imsgev * iev,uint16_t type,uint32_t peerid,pid_t pid,int fd,void * data,uint16_t datalen)572 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
573 pid_t pid, int fd, void *data, uint16_t datalen)
574 {
575 int ret;
576
577 if ((ret = imsg_compose(&iev->ibuf, type, peerid,
578 pid, fd, data, datalen)) != -1)
579 imsg_event_add(iev);
580 return (ret);
581 }
582
583 void
evbuf_enqueue(struct evbuf * eb,struct ibuf * buf)584 evbuf_enqueue(struct evbuf *eb, struct ibuf *buf)
585 {
586 ibuf_close(eb->wbuf, buf);
587 evbuf_event_add(eb);
588 }
589
590 void
evbuf_event_add(struct evbuf * eb)591 evbuf_event_add(struct evbuf *eb)
592 {
593 if (msgbuf_queuelen(eb->wbuf) > 0)
594 event_add(&eb->ev, NULL);
595 }
596
597 void
evbuf_init(struct evbuf * eb,int fd,void (* handler)(int,short,void *),void * arg)598 evbuf_init(struct evbuf *eb, int fd, void (*handler)(int, short, void *),
599 void *arg)
600 {
601 if (eb->wbuf != NULL)
602 fatalx("evbuf_init: msgbuf already set");
603 if ((eb->wbuf = msgbuf_new()) == NULL)
604 fatal(__func__);
605 event_set(&eb->ev, fd, EV_WRITE, handler, arg);
606 }
607
608 void
evbuf_clear(struct evbuf * eb)609 evbuf_clear(struct evbuf *eb)
610 {
611 event_del(&eb->ev);
612 msgbuf_free(eb->wbuf);
613 eb->wbuf = NULL;
614 }
615
616 static int
main_imsg_send_ipc_sockets(struct imsgbuf * ldpe_buf,struct imsgbuf * lde_buf)617 main_imsg_send_ipc_sockets(struct imsgbuf *ldpe_buf, struct imsgbuf *lde_buf)
618 {
619 int pipe_ldpe2lde[2];
620
621 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
622 PF_UNSPEC, pipe_ldpe2lde) == -1)
623 return (-1);
624
625 if (imsg_compose(ldpe_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[0],
626 NULL, 0) == -1)
627 return (-1);
628 if (imsg_compose(lde_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[1],
629 NULL, 0) == -1)
630 return (-1);
631
632 return (0);
633 }
634
635 static void
main_imsg_send_net_sockets(int af)636 main_imsg_send_net_sockets(int af)
637 {
638 main_imsg_send_net_socket(af, LDP_SOCKET_DISC);
639 main_imsg_send_net_socket(af, LDP_SOCKET_EDISC);
640 main_imsg_send_net_socket(af, LDP_SOCKET_SESSION);
641 imsg_compose_event(iev_ldpe, IMSG_SETUP_SOCKETS, af, 0, -1, NULL, 0);
642 }
643
644 static void
main_imsg_send_net_socket(int af,enum socket_type type)645 main_imsg_send_net_socket(int af, enum socket_type type)
646 {
647 int fd;
648
649 fd = ldp_create_socket(af, type);
650 if (fd == -1) {
651 log_warnx("%s: failed to create %s socket for address-family "
652 "%s", __func__, socket_name(type), af_name(af));
653 return;
654 }
655
656 imsg_compose_event(iev_ldpe, IMSG_SOCKET_NET, af, 0, fd, &type,
657 sizeof(type));
658 }
659
660 struct ldpd_af_conf *
ldp_af_conf_get(struct ldpd_conf * xconf,int af)661 ldp_af_conf_get(struct ldpd_conf *xconf, int af)
662 {
663 switch (af) {
664 case AF_INET:
665 return (&xconf->ipv4);
666 case AF_INET6:
667 return (&xconf->ipv6);
668 default:
669 fatalx("ldp_af_conf_get: unknown af");
670 }
671 }
672
673 struct ldpd_af_global *
ldp_af_global_get(struct ldpd_global * xglobal,int af)674 ldp_af_global_get(struct ldpd_global *xglobal, int af)
675 {
676 switch (af) {
677 case AF_INET:
678 return (&xglobal->ipv4);
679 case AF_INET6:
680 return (&xglobal->ipv6);
681 default:
682 fatalx("ldp_af_global_get: unknown af");
683 }
684 }
685
686 int
ldp_is_dual_stack(struct ldpd_conf * xconf)687 ldp_is_dual_stack(struct ldpd_conf *xconf)
688 {
689 return ((xconf->ipv4.flags & F_LDPD_AF_ENABLED) &&
690 (xconf->ipv6.flags & F_LDPD_AF_ENABLED));
691 }
692
693 static int
main_imsg_send_config(struct ldpd_conf * xconf)694 main_imsg_send_config(struct ldpd_conf *xconf)
695 {
696 struct iface *iface;
697 struct tnbr *tnbr;
698 struct nbr_params *nbrp;
699 struct l2vpn *l2vpn;
700 struct l2vpn_if *lif;
701 struct l2vpn_pw *pw;
702 struct ldp_auth *auth;
703
704 if (main_imsg_compose_both(IMSG_RECONF_CONF, xconf,
705 sizeof(*xconf)) == -1)
706 return (-1);
707
708 LIST_FOREACH(auth, &xconf->auth_list, entry) {
709 if (main_imsg_compose_both(IMSG_RECONF_CONF_AUTH,
710 auth, sizeof(*auth)) == -1)
711 return (-1);
712 }
713
714 LIST_FOREACH(iface, &xconf->iface_list, entry) {
715 if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface,
716 sizeof(*iface)) == -1)
717 return (-1);
718 }
719
720 LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) {
721 if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr,
722 sizeof(*tnbr)) == -1)
723 return (-1);
724 }
725
726 LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) {
727 if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp,
728 sizeof(*nbrp)) == -1)
729 return (-1);
730 }
731
732 LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
733 if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn,
734 sizeof(*l2vpn)) == -1)
735 return (-1);
736
737 LIST_FOREACH(lif, &l2vpn->if_list, entry) {
738 if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif,
739 sizeof(*lif)) == -1)
740 return (-1);
741 }
742 LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
743 if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw,
744 sizeof(*pw)) == -1)
745 return (-1);
746 }
747 }
748
749 if (main_imsg_compose_both(IMSG_RECONF_END, NULL, 0) == -1)
750 return (-1);
751
752 return (0);
753 }
754
755 static int
ldp_reload(void)756 ldp_reload(void)
757 {
758 struct ldpd_conf *xconf;
759
760 if ((xconf = parse_config(conffile)) == NULL)
761 return (-1);
762
763 if (main_imsg_send_config(xconf) == -1)
764 return (-1);
765
766 merge_config(ldpd_conf, xconf);
767
768 return (0);
769 }
770
771 void
merge_config(struct ldpd_conf * conf,struct ldpd_conf * xconf)772 merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
773 {
774 merge_global(conf, xconf);
775 merge_auths(conf, xconf);
776 merge_af(AF_INET, &conf->ipv4, &xconf->ipv4);
777 merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6);
778 merge_ifaces(conf, xconf);
779 merge_tnbrs(conf, xconf);
780 merge_nbrps(conf, xconf);
781 merge_l2vpns(conf, xconf);
782 free(xconf);
783 }
784
785 static void
merge_global(struct ldpd_conf * conf,struct ldpd_conf * xconf)786 merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
787 {
788 /* change of router-id requires resetting all neighborships */
789 if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
790 if (ldpd_process == PROC_LDP_ENGINE) {
791 ldpe_reset_nbrs(AF_INET);
792 ldpe_reset_nbrs(AF_INET6);
793 if (conf->rtr_id.s_addr == INADDR_ANY ||
794 xconf->rtr_id.s_addr == INADDR_ANY) {
795 if_update_all(AF_UNSPEC);
796 tnbr_update_all(AF_UNSPEC);
797 }
798 }
799 conf->rtr_id = xconf->rtr_id;
800 }
801
802 conf->rdomain= xconf->rdomain;
803
804 if (conf->trans_pref != xconf->trans_pref) {
805 if (ldpd_process == PROC_LDP_ENGINE)
806 ldpe_reset_ds_nbrs();
807 conf->trans_pref = xconf->trans_pref;
808 }
809
810 if ((conf->flags & F_LDPD_DS_CISCO_INTEROP) !=
811 (xconf->flags & F_LDPD_DS_CISCO_INTEROP)) {
812 if (ldpd_process == PROC_LDP_ENGINE)
813 ldpe_reset_ds_nbrs();
814 }
815
816 conf->flags = xconf->flags;
817 }
818
819 static void
merge_af(int af,struct ldpd_af_conf * af_conf,struct ldpd_af_conf * xa)820 merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
821 {
822 int egress_label_changed = 0;
823 int update_sockets = 0;
824
825 if (af_conf->keepalive != xa->keepalive) {
826 af_conf->keepalive = xa->keepalive;
827 if (ldpd_process == PROC_LDP_ENGINE)
828 ldpe_stop_init_backoff(af);
829 }
830 af_conf->thello_holdtime = xa->thello_holdtime;
831 af_conf->thello_interval = xa->thello_interval;
832
833 /* update flags */
834 if (ldpd_process == PROC_LDP_ENGINE &&
835 (af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) &&
836 !(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
837 ldpe_remove_dynamic_tnbrs(af);
838
839 if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
840 (xa->flags & F_LDPD_AF_NO_GTSM)) {
841 if (af == AF_INET6)
842 /* need to set/unset IPV6_MINHOPCOUNT */
843 update_sockets = 1;
844 else if (ldpd_process == PROC_LDP_ENGINE)
845 /* for LDPv4 just resetting the neighbors is enough */
846 ldpe_reset_nbrs(af);
847 }
848
849 if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
850 (xa->flags & F_LDPD_AF_EXPNULL))
851 egress_label_changed = 1;
852
853 af_conf->flags = xa->flags;
854
855 if (egress_label_changed) {
856 switch (ldpd_process) {
857 case PROC_LDE_ENGINE:
858 lde_change_egress_label(af, af_conf->flags &
859 F_LDPD_AF_EXPNULL);
860 break;
861 case PROC_MAIN:
862 kr_change_egress_label(af, af_conf->flags &
863 F_LDPD_AF_EXPNULL);
864 break;
865 default:
866 break;
867 }
868 }
869
870 if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
871 af_conf->trans_addr = xa->trans_addr;
872 update_sockets = 1;
873 }
874
875 if (ldpd_process == PROC_MAIN && update_sockets)
876 imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af, 0, -1,
877 NULL, 0);
878 }
879
880 static void
merge_ifaces(struct ldpd_conf * conf,struct ldpd_conf * xconf)881 merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
882 {
883 struct iface *iface, *itmp, *xi;
884
885 LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) {
886 /* find deleted interfaces */
887 if ((xi = if_lookup(xconf, iface->ifindex)) == NULL) {
888 LIST_REMOVE(iface, entry);
889 if (ldpd_process == PROC_LDP_ENGINE)
890 if_exit(iface);
891 free(iface);
892 }
893 }
894 LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) {
895 /* find new interfaces */
896 if ((iface = if_lookup(conf, xi->ifindex)) == NULL) {
897 LIST_REMOVE(xi, entry);
898 LIST_INSERT_HEAD(&conf->iface_list, xi, entry);
899
900 /* resend addresses to activate new interfaces */
901 if (ldpd_process == PROC_MAIN)
902 kif_redistribute(xi->name);
903 continue;
904 }
905
906 /* update existing interfaces */
907 merge_iface_af(&iface->ipv4, &xi->ipv4);
908 merge_iface_af(&iface->ipv6, &xi->ipv6);
909 LIST_REMOVE(xi, entry);
910 free(xi);
911 }
912 }
913
914 static void
merge_iface_af(struct iface_af * ia,struct iface_af * xi)915 merge_iface_af(struct iface_af *ia, struct iface_af *xi)
916 {
917 if (ia->enabled != xi->enabled) {
918 ia->enabled = xi->enabled;
919 if (ldpd_process == PROC_LDP_ENGINE)
920 if_update(ia->iface, ia->af);
921 }
922 ia->hello_holdtime = xi->hello_holdtime;
923 ia->hello_interval = xi->hello_interval;
924 }
925
926 static void
merge_tnbrs(struct ldpd_conf * conf,struct ldpd_conf * xconf)927 merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
928 {
929 struct tnbr *tnbr, *ttmp, *xt;
930
931 LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) {
932 if (!(tnbr->flags & F_TNBR_CONFIGURED))
933 continue;
934
935 /* find deleted tnbrs */
936 if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) {
937 if (ldpd_process == PROC_LDP_ENGINE) {
938 tnbr->flags &= ~F_TNBR_CONFIGURED;
939 tnbr_check(tnbr);
940 } else {
941 LIST_REMOVE(tnbr, entry);
942 free(tnbr);
943 }
944 }
945 }
946 LIST_FOREACH_SAFE(xt, &xconf->tnbr_list, entry, ttmp) {
947 /* find new tnbrs */
948 if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
949 LIST_REMOVE(xt, entry);
950 LIST_INSERT_HEAD(&conf->tnbr_list, xt, entry);
951
952 if (ldpd_process == PROC_LDP_ENGINE)
953 tnbr_update(xt);
954 continue;
955 }
956
957 /* update existing tnbrs */
958 if (!(tnbr->flags & F_TNBR_CONFIGURED))
959 tnbr->flags |= F_TNBR_CONFIGURED;
960 tnbr->hello_holdtime = xt->hello_holdtime;
961 tnbr->hello_interval = xt->hello_interval;
962 LIST_REMOVE(xt, entry);
963 free(xt);
964 }
965 }
966
967 static void
merge_nbrps(struct ldpd_conf * conf,struct ldpd_conf * xconf)968 merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
969 {
970 struct nbr_params *nbrp, *ntmp, *xn;
971 struct nbr *nbr;
972 int nbrp_changed;
973
974 LIST_FOREACH_SAFE(nbrp, &conf->nbrp_list, entry, ntmp) {
975 /* find deleted nbrps */
976 if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
977 if (ldpd_process == PROC_LDP_ENGINE) {
978 nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
979 if (nbr) {
980 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
981 pfkey_remove(nbr);
982 if (nbr_session_active_role(nbr))
983 nbr_establish_connection(nbr);
984 }
985 }
986 LIST_REMOVE(nbrp, entry);
987 free(nbrp);
988 }
989 }
990 LIST_FOREACH_SAFE(xn, &xconf->nbrp_list, entry, ntmp) {
991 /* find new nbrps */
992 if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
993 LIST_REMOVE(xn, entry);
994 LIST_INSERT_HEAD(&conf->nbrp_list, xn, entry);
995
996 if (ldpd_process == PROC_LDP_ENGINE) {
997 nbr = nbr_find_ldpid(xn->lsr_id.s_addr);
998 if (nbr) {
999 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
1000 if (pfkey_establish(conf, nbr) == -1)
1001 fatalx("pfkey setup failed");
1002 if (nbr_session_active_role(nbr))
1003 nbr_establish_connection(nbr);
1004 }
1005 }
1006 continue;
1007 }
1008
1009 /* update existing nbrps */
1010 if (nbrp->flags != xn->flags ||
1011 nbrp->keepalive != xn->keepalive ||
1012 nbrp->gtsm_enabled != xn->gtsm_enabled ||
1013 nbrp->gtsm_hops != xn->gtsm_hops)
1014 nbrp_changed = 1;
1015 else
1016 nbrp_changed = 0;
1017
1018 nbrp->keepalive = xn->keepalive;
1019 nbrp->gtsm_enabled = xn->gtsm_enabled;
1020 nbrp->gtsm_hops = xn->gtsm_hops;
1021 nbrp->flags = xn->flags;
1022
1023 if (ldpd_process == PROC_LDP_ENGINE) {
1024 nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
1025 if (nbr && nbrp_changed) {
1026 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
1027 pfkey_remove(nbr);
1028 if (pfkey_establish(conf, nbr) == -1)
1029 fatalx("pfkey setup failed");
1030 if (nbr_session_active_role(nbr))
1031 nbr_establish_connection(nbr);
1032 }
1033 }
1034 LIST_REMOVE(xn, entry);
1035 free(xn);
1036 }
1037 }
1038
1039 static void
merge_l2vpns(struct ldpd_conf * conf,struct ldpd_conf * xconf)1040 merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
1041 {
1042 struct l2vpn *l2vpn, *ltmp, *xl;
1043
1044 LIST_FOREACH_SAFE(l2vpn, &conf->l2vpn_list, entry, ltmp) {
1045 /* find deleted l2vpns */
1046 if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
1047 LIST_REMOVE(l2vpn, entry);
1048
1049 switch (ldpd_process) {
1050 case PROC_LDE_ENGINE:
1051 l2vpn_exit(l2vpn);
1052 break;
1053 case PROC_LDP_ENGINE:
1054 ldpe_l2vpn_exit(l2vpn);
1055 break;
1056 case PROC_MAIN:
1057 break;
1058 }
1059 l2vpn_del(l2vpn);
1060 }
1061 }
1062 LIST_FOREACH_SAFE(xl, &xconf->l2vpn_list, entry, ltmp) {
1063 /* find new l2vpns */
1064 if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
1065 LIST_REMOVE(xl, entry);
1066 LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry);
1067
1068 switch (ldpd_process) {
1069 case PROC_LDE_ENGINE:
1070 l2vpn_init(xl);
1071 break;
1072 case PROC_LDP_ENGINE:
1073 ldpe_l2vpn_init(xl);
1074 break;
1075 case PROC_MAIN:
1076 break;
1077 }
1078 continue;
1079 }
1080
1081 /* update existing l2vpns */
1082 merge_l2vpn(conf, l2vpn, xl);
1083 LIST_REMOVE(xl, entry);
1084 free(xl);
1085 }
1086 }
1087
1088 static void
merge_l2vpn(struct ldpd_conf * xconf,struct l2vpn * l2vpn,struct l2vpn * xl)1089 merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
1090 {
1091 struct l2vpn_if *lif, *ftmp, *xf;
1092 struct l2vpn_pw *pw, *ptmp, *xp;
1093 struct nbr *nbr;
1094 int reset_nbr, reinstall_pwfec, reinstall_tnbr;
1095 int previous_pw_type, previous_mtu;
1096
1097 previous_pw_type = l2vpn->pw_type;
1098 previous_mtu = l2vpn->mtu;
1099
1100 /* merge intefaces */
1101 LIST_FOREACH_SAFE(lif, &l2vpn->if_list, entry, ftmp) {
1102 /* find deleted interfaces */
1103 if ((xf = l2vpn_if_find(xl, lif->ifindex)) == NULL) {
1104 LIST_REMOVE(lif, entry);
1105 free(lif);
1106 }
1107 }
1108 LIST_FOREACH_SAFE(xf, &xl->if_list, entry, ftmp) {
1109 /* find new interfaces */
1110 if ((lif = l2vpn_if_find(l2vpn, xf->ifindex)) == NULL) {
1111 LIST_REMOVE(xf, entry);
1112 LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry);
1113 xf->l2vpn = l2vpn;
1114 continue;
1115 }
1116
1117 LIST_REMOVE(xf, entry);
1118 free(xf);
1119 }
1120
1121 /* merge pseudowires */
1122 LIST_FOREACH_SAFE(pw, &l2vpn->pw_list, entry, ptmp) {
1123 /* find deleted pseudowires */
1124 if ((xp = l2vpn_pw_find(xl, pw->ifindex)) == NULL) {
1125 switch (ldpd_process) {
1126 case PROC_LDE_ENGINE:
1127 l2vpn_pw_exit(pw);
1128 break;
1129 case PROC_LDP_ENGINE:
1130 ldpe_l2vpn_pw_exit(pw);
1131 break;
1132 case PROC_MAIN:
1133 break;
1134 }
1135
1136 LIST_REMOVE(pw, entry);
1137 free(pw);
1138 }
1139 }
1140 LIST_FOREACH_SAFE(xp, &xl->pw_list, entry, ptmp) {
1141 /* find new pseudowires */
1142 if ((pw = l2vpn_pw_find(l2vpn, xp->ifindex)) == NULL) {
1143 LIST_REMOVE(xp, entry);
1144 LIST_INSERT_HEAD(&l2vpn->pw_list, xp, entry);
1145 xp->l2vpn = l2vpn;
1146
1147 switch (ldpd_process) {
1148 case PROC_LDE_ENGINE:
1149 l2vpn_pw_init(xp);
1150 break;
1151 case PROC_LDP_ENGINE:
1152 ldpe_l2vpn_pw_init(xp);
1153 break;
1154 case PROC_MAIN:
1155 break;
1156 }
1157 continue;
1158 }
1159
1160 /* update existing pseudowire */
1161 if (pw->af != xp->af ||
1162 ldp_addrcmp(pw->af, &pw->addr, &xp->addr))
1163 reinstall_tnbr = 1;
1164 else
1165 reinstall_tnbr = 0;
1166
1167 /* changes that require a session restart */
1168 if ((pw->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)) !=
1169 (xp->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)))
1170 reset_nbr = 1;
1171 else
1172 reset_nbr = 0;
1173
1174 if (l2vpn->pw_type != xl->pw_type || l2vpn->mtu != xl->mtu ||
1175 pw->pwid != xp->pwid || reinstall_tnbr || reset_nbr ||
1176 pw->lsr_id.s_addr != xp->lsr_id.s_addr)
1177 reinstall_pwfec = 1;
1178 else
1179 reinstall_pwfec = 0;
1180
1181 if (ldpd_process == PROC_LDP_ENGINE) {
1182 if (reinstall_tnbr)
1183 ldpe_l2vpn_pw_exit(pw);
1184 if (reset_nbr) {
1185 nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
1186 if (nbr && nbr->state == NBR_STA_OPER)
1187 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
1188 }
1189 }
1190 if (ldpd_process == PROC_LDE_ENGINE &&
1191 !reset_nbr && reinstall_pwfec)
1192 l2vpn_pw_exit(pw);
1193 pw->lsr_id = xp->lsr_id;
1194 pw->af = xp->af;
1195 pw->addr = xp->addr;
1196 pw->pwid = xp->pwid;
1197 strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
1198 pw->ifindex = xp->ifindex;
1199 if (xp->flags & F_PW_CWORD_CONF)
1200 pw->flags |= F_PW_CWORD_CONF;
1201 else
1202 pw->flags &= ~F_PW_CWORD_CONF;
1203 if (xp->flags & F_PW_STATUSTLV_CONF)
1204 pw->flags |= F_PW_STATUSTLV_CONF;
1205 else
1206 pw->flags &= ~F_PW_STATUSTLV_CONF;
1207 if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr)
1208 ldpe_l2vpn_pw_init(pw);
1209 if (ldpd_process == PROC_LDE_ENGINE &&
1210 !reset_nbr && reinstall_pwfec) {
1211 l2vpn->pw_type = xl->pw_type;
1212 l2vpn->mtu = xl->mtu;
1213 l2vpn_pw_init(pw);
1214 l2vpn->pw_type = previous_pw_type;
1215 l2vpn->mtu = previous_mtu;
1216 }
1217
1218 LIST_REMOVE(xp, entry);
1219 free(xp);
1220 }
1221
1222 l2vpn->pw_type = xl->pw_type;
1223 l2vpn->mtu = xl->mtu;
1224 strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname));
1225 l2vpn->br_ifindex = xl->br_ifindex;
1226 }
1227
1228 static struct ldp_auth *
auth_find(struct ldpd_conf * conf,const struct ldp_auth * needle)1229 auth_find(struct ldpd_conf *conf, const struct ldp_auth *needle)
1230 {
1231 struct ldp_auth *auth;
1232
1233 LIST_FOREACH(auth, &conf->auth_list, entry) {
1234 in_addr_t mask;
1235 if (needle->md5key_len != auth->md5key_len)
1236 continue;
1237 if (needle->idlen != auth->idlen)
1238 continue;
1239
1240 if (memcmp(needle->md5key, auth->md5key,
1241 needle->md5key_len) != 0)
1242 continue;
1243
1244 mask = prefixlen2mask(auth->idlen);
1245 if ((needle->id.s_addr & mask) != (auth->id.s_addr & mask))
1246 continue;
1247
1248 return (auth);
1249 }
1250
1251 return (NULL);
1252 }
1253
1254 static void
merge_auths(struct ldpd_conf * conf,struct ldpd_conf * xconf)1255 merge_auths(struct ldpd_conf *conf, struct ldpd_conf *xconf)
1256 {
1257 struct ldp_auth *auth, *nauth, *xauth;
1258
1259 /* find deleted auths */
1260 LIST_FOREACH_SAFE(auth, &conf->auth_list, entry, nauth) {
1261 xauth = auth_find(xconf, auth);
1262 if (xauth == NULL)
1263 continue;
1264
1265 LIST_REMOVE(auth, entry);
1266
1267 free(auth);
1268 }
1269
1270 /* find new auths */
1271 LIST_FOREACH_SAFE(xauth, &xconf->auth_list, entry, nauth) {
1272 LIST_REMOVE(xauth, entry);
1273
1274 auth = auth_find(conf, xauth);
1275 if (auth == NULL) {
1276 LIST_INSERT_HEAD(&conf->auth_list, xauth, entry);
1277 continue;
1278 }
1279
1280 free(xauth);
1281 }
1282 }
1283
1284 struct ldpd_conf *
config_new_empty(void)1285 config_new_empty(void)
1286 {
1287 struct ldpd_conf *xconf;
1288
1289 xconf = calloc(1, sizeof(*xconf));
1290 if (xconf == NULL)
1291 fatal(NULL);
1292
1293 LIST_INIT(&xconf->iface_list);
1294 LIST_INIT(&xconf->tnbr_list);
1295 LIST_INIT(&xconf->nbrp_list);
1296 LIST_INIT(&xconf->l2vpn_list);
1297 LIST_INIT(&xconf->auth_list);
1298
1299 return (xconf);
1300 }
1301
1302 void
config_clear(struct ldpd_conf * conf)1303 config_clear(struct ldpd_conf *conf)
1304 {
1305 struct ldpd_conf *xconf;
1306
1307 /*
1308 * Merge current config with an empty config, this will deactivate
1309 * and deallocate all the interfaces, pseudowires and so on. Before
1310 * merging, copy the router-id and other variables to avoid some
1311 * unnecessary operations, like trying to reset the neighborships.
1312 */
1313 xconf = config_new_empty();
1314 xconf->ipv4 = conf->ipv4;
1315 xconf->ipv6 = conf->ipv6;
1316 xconf->rtr_id = conf->rtr_id;
1317 xconf->trans_pref = conf->trans_pref;
1318 xconf->flags = conf->flags;
1319 merge_config(conf, xconf);
1320 free(conf);
1321 }
1322