Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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