Bug Summary

File:src/usr.sbin/ldpd/ldpd.c
Warning:line 1096, column 8
Although the value stored to 'xf' is used in the enclosing expression, the value is never actually read from 'xf'

Annotated Source Code

Press '?' to see keyboard shortcuts

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