Bug Summary

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

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 ospfd.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/ospfd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ospfd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ospfd/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/ospfd/ospfd.c
1/* $OpenBSD: ospfd.c,v 1.116 2021/09/06 13:32:18 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <sys/types.h>
22#include <sys/socket.h>
23#include <sys/queue.h>
24#include <sys/time.h>
25#include <sys/stat.h>
26#include <sys/wait.h>
27#include <sys/sysctl.h>
28#include <syslog.h>
29
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <net/if_types.h>
33
34#include <event.h>
35#include <err.h>
36#include <errno(*__errno()).h>
37#include <pwd.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <signal.h>
42#include <unistd.h>
43
44#include "ospfd.h"
45#include "ospf.h"
46#include "ospfe.h"
47#include "control.h"
48#include "log.h"
49#include "rde.h"
50
51void main_sig_handler(int, short, void *);
52__dead__attribute__((__noreturn__)) void usage(void);
53__dead__attribute__((__noreturn__)) void ospfd_shutdown(void);
54
55void main_dispatch_ospfe(int, short, void *);
56void main_dispatch_rde(int, short, void *);
57
58int ospf_reload(void);
59int ospf_sendboth(enum imsg_type, void *, u_int16_t);
60int merge_interfaces(struct area *, struct area *);
61struct iface *iface_lookup(struct area *, struct iface *);
62
63int pipe_parent2ospfe[2];
64int pipe_parent2rde[2];
65int pipe_ospfe2rde[2];
66
67enum ospfd_process ospfd_process;
68struct ospfd_conf *ospfd_conf = NULL((void*)0);
69static struct imsgev *iev_ospfe;
70static struct imsgev *iev_rde;
71char *conffile;
72
73pid_t ospfe_pid = 0;
74pid_t rde_pid = 0;
75
76/* ARGSUSED */
77void
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 ospfd_shutdown();
85 /* NOTREACHED */
86 case SIGHUP1:
87 if (ospf_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
98__dead__attribute__((__noreturn__)) void
99usage(void)
100{
101 extern char *__progname;
102
103 fprintf(stderr(&__sF[2]), "usage: %s [-cdnv] [-D macro=value]"
104 " [-f file] [-s socket]\n",
105 __progname);
106 exit(1);
107}
108
109int
110main(int argc, char *argv[])
111{
112 struct event ev_sigint, ev_sigterm, ev_sighup;
113 struct area *a;
114 int ch, opts = 0;
115 int debug = 0;
116 int ipforwarding;
117 int mib[4];
118 size_t len;
119 char *sockname = NULL((void*)0);
120 int control_fd;
121
122 conffile = CONF_FILE"/etc/ospfd.conf";
123 ospfd_process = PROC_MAIN;
124
125 log_init(1, LOG_DAEMON(3<<3)); /* log to stderr until daemonized */
126 log_procinit(log_procnames[ospfd_process]);
127
128 while ((ch = getopt(argc, argv, "cdD:f:ns:v")) != -1) {
129 switch (ch) {
130 case 'c':
131 opts |= OSPFD_OPT_FORCE_DEMOTE0x00000010;
132 break;
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 opts |= OSPFD_OPT_NOACTION0x00000004;
146 break;
147 case 's':
148 sockname = optarg;
149 break;
150 case 'v':
151 if (opts & OSPFD_OPT_VERBOSE0x00000001)
152 opts |= OSPFD_OPT_VERBOSE20x00000002;
153 opts |= OSPFD_OPT_VERBOSE0x00000001;
154 log_setverbose(1);
155 break;
156 default:
157 usage();
158 /* NOTREACHED */
159 }
160 }
161
162 argc -= optind;
163 argv += optind;
164 if (argc > 0)
165 usage();
166
167 mib[0] = CTL_NET4;
168 mib[1] = PF_INET2;
169 mib[2] = IPPROTO_IP0;
170 mib[3] = IPCTL_FORWARDING1;
171 len = sizeof(ipforwarding);
172 if (sysctl(mib, 4, &ipforwarding, &len, NULL((void*)0), 0) == -1)
173 err(1, "sysctl");
174
175 if (ipforwarding != 1) {
176 log_warnx("WARNING: IP forwarding NOT enabled, "
177 "running as stub router");
178 opts |= OSPFD_OPT_STUB_ROUTER0x00000008;
179 }
180
181 /* fetch interfaces early */
182 kif_init();
183
184 /* parse config file */
185 if ((ospfd_conf = parse_config(conffile, opts)) == NULL((void*)0)) {
186 kif_clear();
187 exit(1);
188 }
189 if (ospfd_conf->rtr_id.s_addr == 0)
190 ospfd_conf->rtr_id.s_addr = get_rtr_id();
191
192 if (sockname == NULL((void*)0)) {
193 if (asprintf(&sockname, "%s.%d", OSPFD_SOCKET"/var/run/ospfd.sock",
194 ospfd_conf->rdomain) == -1)
195 err(1, "asprintf");
196 }
197
198 ospfd_conf->csock = sockname;
199
200 if (ospfd_conf->opts & OSPFD_OPT_NOACTION0x00000004) {
201 if (ospfd_conf->opts & OSPFD_OPT_VERBOSE0x00000001)
202 print_config(ospfd_conf);
203 else
204 fprintf(stderr(&__sF[2]), "configuration OK\n");
205 kif_clear();
206 exit(0);
207 }
208
209 /* check for root privileges */
210 if (geteuid())
211 errx(1, "need root privileges");
212
213 /* check for ospfd user */
214 if (getpwnam(OSPFD_USER"_ospfd") == NULL((void*)0))
215 errx(1, "unknown user %s", OSPFD_USER"_ospfd");
216
217 log_init(debug, LOG_DAEMON(3<<3));
218 log_setverbose(ospfd_conf->opts & OSPFD_OPT_VERBOSE0x00000001);
219
220 if ((control_check(ospfd_conf->csock)) == -1)
221 fatalx("ospfd already running");
222
223 if (!debug)
224 daemon(1, 0);
225
226 log_info("startup");
227
228 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
229 PF_UNSPEC0, pipe_parent2ospfe) == -1)
230 fatal("socketpair");
231 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
232 PF_UNSPEC0, pipe_parent2rde) == -1)
233 fatal("socketpair");
234 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
235 PF_UNSPEC0, pipe_ospfe2rde) == -1)
236 fatal("socketpair");
237
238 /* start children */
239 rde_pid = rde(ospfd_conf, pipe_parent2rde, pipe_ospfe2rde,
240 pipe_parent2ospfe);
241 ospfe_pid = ospfe(ospfd_conf, pipe_parent2ospfe, pipe_ospfe2rde,
242 pipe_parent2rde);
243
244 event_init();
245
246 /* setup signal handler */
247 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void
*)0))
;
248 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, (
(void*)0))
;
249 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void
*)0))
;
250 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0));
251 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0));
252 signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void*)0));
253 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
254
255 /* setup pipes to children */
256 close(pipe_parent2ospfe[1]);
257 close(pipe_parent2rde[1]);
258 close(pipe_ospfe2rde[0]);
259 close(pipe_ospfe2rde[1]);
260
261 if ((iev_ospfe = malloc(sizeof(struct imsgev))) == NULL((void*)0) ||
262 (iev_rde = malloc(sizeof(struct imsgev))) == NULL((void*)0))
263 fatal(NULL((void*)0));
264 imsg_init(&iev_ospfe->ibuf, pipe_parent2ospfe[0]);
265 iev_ospfe->handler = main_dispatch_ospfe;
266 imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]);
267 iev_rde->handler = main_dispatch_rde;
268
269 /* setup event handler */
270 iev_ospfe->events = EV_READ0x02;
271 event_set(&iev_ospfe->ev, iev_ospfe->ibuf.fd, iev_ospfe->events,
272 iev_ospfe->handler, iev_ospfe);
273 event_add(&iev_ospfe->ev, NULL((void*)0));
274
275 iev_rde->events = EV_READ0x02;
276 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
277 iev_rde->handler, iev_rde);
278 event_add(&iev_rde->ev, NULL((void*)0));
279
280 if ((control_fd = control_init(ospfd_conf->csock)) == -1)
281 fatalx("control socket setup failed");
282 main_imsg_compose_ospfe_fd(IMSG_CONTROLFD, 0, control_fd);
283
284 if (unveil("/", "r") == -1)
285 fatal("unveil /");
286 if (unveil(NULL((void*)0), NULL((void*)0)) == -1)
287 fatal("unveil");
288
289 if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE0x0001),
290 ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix,
291 ospfd_conf->fib_priority) == -1)
292 fatalx("kr_init failed");
293
294 /* remove unneeded stuff from config */
295 while ((a = LIST_FIRST(&ospfd_conf->area_list)((&ospfd_conf->area_list)->lh_first)) != NULL((void*)0)) {
296 LIST_REMOVE(a, entry)do { if ((a)->entry.le_next != ((void*)0)) (a)->entry.le_next
->entry.le_prev = (a)->entry.le_prev; *(a)->entry.le_prev
= (a)->entry.le_next; ; ; } while (0)
;
297 area_del(a);
298 }
299
300 event_dispatch();
301
302 ospfd_shutdown();
303 /* NOTREACHED */
304 return (0);
305}
306
307__dead__attribute__((__noreturn__)) void
308ospfd_shutdown(void)
309{
310 pid_t pid;
311 int status;
312 struct redistribute *r;
313
314 /* close pipes */
315 msgbuf_clear(&iev_ospfe->ibuf.w);
316 close(iev_ospfe->ibuf.fd);
317 msgbuf_clear(&iev_rde->ibuf.w);
318 close(iev_rde->ibuf.fd);
319
320 control_cleanup();
321 while ((r = SIMPLEQ_FIRST(&ospfd_conf->redist_list)((&ospfd_conf->redist_list)->sqh_first)) != NULL((void*)0)) {
322 SIMPLEQ_REMOVE_HEAD(&ospfd_conf->redist_list, entry)do { if (((&ospfd_conf->redist_list)->sqh_first = (
&ospfd_conf->redist_list)->sqh_first->entry.sqe_next
) == ((void*)0)) (&ospfd_conf->redist_list)->sqh_last
= &(&ospfd_conf->redist_list)->sqh_first; } while
(0)
;
323 free(r);
324 }
325 kr_shutdown();
326 carp_demote_shutdown();
327
328 log_debug("waiting for children to terminate");
329 do {
330 pid = wait(&status);
331 if (pid == -1) {
332 if (errno(*__errno()) != EINTR4 && errno(*__errno()) != ECHILD10)
333 fatal("wait");
334 } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
)
335 log_warnx("%s terminated; signal %d",
336 (pid == rde_pid) ? "route decision engine" :
337 "ospf engine", WTERMSIG(status)(((status) & 0177)));
338 } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4));
339
340 free(iev_ospfe);
341 free(iev_rde);
342 free(ospfd_conf);
343
344 log_info("terminating");
345 exit(0);
346}
347
348/* imsg handling */
349/* ARGSUSED */
350void
351main_dispatch_ospfe(int fd, short event, void *bula)
352{
353 struct imsgev *iev = bula;
354 struct imsgbuf *ibuf;
355 struct imsg imsg;
356 struct demote_msg dmsg;
357 ssize_t n;
358 int shut = 0, verbose;
359
360 ibuf = &iev->ibuf;
361
362 if (event & EV_READ0x02) {
363 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
364 fatal("imsg_read error");
365 if (n == 0) /* connection closed */
366 shut = 1;
367 }
368 if (event & EV_WRITE0x04) {
369 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
370 fatal("msgbuf_write");
371 if (n == 0) /* connection closed */
372 shut = 1;
373 }
374
375 for (;;) {
376 if ((n = imsg_get(ibuf, &imsg)) == -1)
377 fatal("imsg_get");
378
379 if (n == 0)
380 break;
381
382 switch (imsg.hdr.type) {
383 case IMSG_CTL_RELOAD:
384 if (ospf_reload() == -1)
385 log_warnx("configuration reload failed");
386 else
387 log_debug("configuration reloaded");
388 break;
389 case IMSG_CTL_FIB_COUPLE:
390 kr_fib_couple();
391 break;
392 case IMSG_CTL_FIB_DECOUPLE:
393 kr_fib_decouple();
394 break;
395 case IMSG_CTL_FIB_RELOAD:
396 kr_fib_reload();
397 break;
398 case IMSG_CTL_KROUTE:
399 case IMSG_CTL_KROUTE_ADDR:
400 kr_show_route(&imsg);
401 break;
402 case IMSG_CTL_IFINFO:
403 if (imsg.hdr.len == IMSG_HEADER_SIZEsizeof(struct imsg_hdr))
404 kr_ifinfo(NULL((void*)0), imsg.hdr.pid);
405 else if (imsg.hdr.len == IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + IFNAMSIZ16)
406 kr_ifinfo(imsg.data, imsg.hdr.pid);
407 else
408 log_warnx("IFINFO request with wrong len");
409 break;
410 case IMSG_DEMOTE:
411 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(dmsg))
412 fatalx("invalid size of OE request");
413 memcpy(&dmsg, imsg.data, sizeof(dmsg));
414 carp_demote_set(dmsg.demote_group, dmsg.level);
415 break;
416 case IMSG_CTL_LOG_VERBOSE:
417 /* already checked by ospfe */
418 memcpy(&verbose, imsg.data, sizeof(verbose));
419 log_setverbose(verbose);
420 break;
421 default:
422 log_debug("main_dispatch_ospfe: error handling imsg %d",
423 imsg.hdr.type);
424 break;
425 }
426 imsg_free(&imsg);
427 }
428 if (!shut)
429 imsg_event_add(iev);
430 else {
431 /* this pipe is dead, so remove the event handler */
432 event_del(&iev->ev);
433 event_loopexit(NULL((void*)0));
434 }
435}
436
437/* ARGSUSED */
438void
439main_dispatch_rde(int fd, short event, void *bula)
440{
441 struct imsgev *iev = bula;
442 struct imsgbuf *ibuf;
443 struct imsg imsg;
444 ssize_t n;
445 int count, shut = 0;
446
447 ibuf = &iev->ibuf;
448
449 if (event & EV_READ0x02) {
450 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
451 fatal("imsg_read error");
452 if (n == 0) /* connection closed */
453 shut = 1;
454 }
455 if (event & EV_WRITE0x04) {
456 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
457 fatal("msgbuf_write");
458 if (n == 0) /* connection closed */
459 shut = 1;
460 }
461
462 for (;;) {
463 if ((n = imsg_get(ibuf, &imsg)) == -1)
464 fatal("imsg_get");
465
466 if (n == 0)
467 break;
468
469 switch (imsg.hdr.type) {
470 case IMSG_KROUTE_CHANGE:
471 count = (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)) /
472 sizeof(struct kroute);
473 if (kr_change(imsg.data, count))
474 log_warn("main_dispatch_rde: error changing "
475 "route");
476 break;
477 case IMSG_KROUTE_DELETE:
478 if (kr_delete(imsg.data))
479 log_warn("main_dispatch_rde: error deleting "
480 "route");
481 break;
482 default:
483 log_debug("main_dispatch_rde: error handling imsg %d",
484 imsg.hdr.type);
485 break;
486 }
487 imsg_free(&imsg);
488 }
489 if (!shut)
490 imsg_event_add(iev);
491 else {
492 /* this pipe is dead, so remove the event handler */
493 event_del(&iev->ev);
494 event_loopexit(NULL((void*)0));
495 }
496}
497
498void
499main_imsg_compose_ospfe(int type, pid_t pid, void *data, u_int16_t datalen)
500{
501 if (iev_ospfe)
502 imsg_compose_event(iev_ospfe, type, 0, pid, -1, data, datalen);
503}
504
505void
506main_imsg_compose_ospfe_fd(int type, pid_t pid, int fd)
507{
508 if (iev_ospfe)
509 imsg_compose_event(iev_ospfe, type, 0, pid, fd, NULL((void*)0), 0);
510}
511
512void
513main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen)
514{
515 if (iev_rde)
516 imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen);
517}
518
519void
520imsg_event_add(struct imsgev *iev)
521{
522 iev->events = EV_READ0x02;
523 if (iev->ibuf.w.queued)
524 iev->events |= EV_WRITE0x04;
525
526 event_del(&iev->ev);
527 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
528 event_add(&iev->ev, NULL((void*)0));
529}
530
531int
532imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
533 pid_t pid, int fd, void *data, u_int16_t datalen)
534{
535 int ret;
536
537 if ((ret = imsg_compose(&iev->ibuf, type, peerid,
538 pid, fd, data, datalen)) != -1)
539 imsg_event_add(iev);
540 return (ret);
541}
542
543int
544ospf_redistribute(struct kroute *kr, u_int32_t *metric)
545{
546 struct in_addr addr;
547 struct kif *kif;
548 struct redistribute *r;
549 int is_default, depend_ok;
550
551 bzero(&addr, sizeof(addr));
552
553 /* only allow 0.0.0.0/0 via REDIST_DEFAULT */
554 is_default = (kr->prefix.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) && kr->prefixlen == 0);
555
556 SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry)for((r) = ((&ospfd_conf->redist_list)->sqh_first); (
r) != ((void*)0); (r) = ((r)->entry.sqe_next))
{
557 if (r->dependon[0] != '\0') {
558 if ((kif = kif_findname(r->dependon, addr, NULL((void*)0))))
559 depend_ok = ifstate_is_up(kif);
560 else
561 depend_ok = 0;
562 } else
563 depend_ok = 1;
564
565 switch (r->type & ~REDIST_NO0x10) {
566 case REDIST_LABEL0x04:
567 if (kr->rtlabel == r->label) {
568 *metric = depend_ok ? r->metric :
569 r->metric | MAX_METRIC65535;
570 return (r->type & REDIST_NO0x10 ? 0 : 1);
571 }
572 break;
573 case REDIST_STATIC0x02:
574 /*
575 * Dynamic routes are not redistributable. Placed here
576 * so that link local addresses can be redistributed
577 * via a rtlabel.
578 */
579 if (is_default)
580 continue;
581 if (kr->flags & F_DYNAMIC0x0010)
582 continue;
583 if (kr->flags & F_STATIC0x0008) {
584 *metric = depend_ok ? r->metric :
585 r->metric | MAX_METRIC65535;
586 return (r->type & REDIST_NO0x10 ? 0 : 1);
587 }
588 break;
589 case REDIST_CONNECTED0x01:
590 if (is_default)
591 continue;
592 if (kr->flags & F_DYNAMIC0x0010)
593 continue;
594 if (kr->flags & F_CONNECTED0x0004) {
595 *metric = depend_ok ? r->metric :
596 r->metric | MAX_METRIC65535;
597 return (r->type & REDIST_NO0x10 ? 0 : 1);
598 }
599 break;
600 case REDIST_ADDR0x08:
601 if (kr->flags & F_DYNAMIC0x0010)
602 continue;
603
604 if (r->addr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) &&
605 r->mask.s_addr == INADDR_ANY((u_int32_t)(0x00000000))) {
606 if (is_default) {
607 *metric = depend_ok ? r->metric :
608 r->metric | MAX_METRIC65535;
609 return (r->type & REDIST_NO0x10 ? 0 : 1);
610 } else
611 return (0);
612 }
613
614 if ((kr->prefix.s_addr & r->mask.s_addr) ==
615 (r->addr.s_addr & r->mask.s_addr) &&
616 kr->prefixlen >= mask2prefixlen(r->mask.s_addr)) {
617 *metric = depend_ok ? r->metric :
618 r->metric | MAX_METRIC65535;
619 return (r->type & REDIST_NO0x10 ? 0 : 1);
620 }
621 break;
622 case REDIST_DEFAULT0x20:
623 if (is_default) {
624 *metric = depend_ok ? r->metric :
625 r->metric | MAX_METRIC65535;
626 return (r->type & REDIST_NO0x10 ? 0 : 1);
627 }
628 break;
629 }
630 }
631
632 return (0);
633}
634
635int
636ospf_reload(void)
637{
638 struct area *area;
639 struct iface *iface;
640 struct ospfd_conf *xconf;
641 struct redistribute *r;
642
643 if ((xconf = parse_config(conffile, ospfd_conf->opts)) == NULL((void*)0))
644 return (-1);
645
646 /* No router-id was specified, keep existing value */
647 if (xconf->rtr_id.s_addr == 0)
648 xconf->rtr_id.s_addr = ospfd_conf->rtr_id.s_addr;
649
650 /* Abort the reload if rtr_id changed */
651 if (ospfd_conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
652 log_warnx("router-id changed: restart required");
653 return (-1);
654 }
655
656 /* send config to childs */
657 if (ospf_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
658 return (-1);
659
660 /* send interfaces */
661 LIST_FOREACH(area, &xconf->area_list, entry)for((area) = ((&xconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
{
662 if (ospf_sendboth(IMSG_RECONF_AREA, area, sizeof(*area)) == -1)
663 return (-1);
664
665 SIMPLEQ_FOREACH(r, &area->redist_list, entry)for((r) = ((&area->redist_list)->sqh_first); (r) !=
((void*)0); (r) = ((r)->entry.sqe_next))
{
666 main_imsg_compose_rde(IMSG_RECONF_REDIST, 0, r,
667 sizeof(*r));
668 }
669 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
670 if (ospf_sendboth(IMSG_RECONF_IFACE, iface,
671 sizeof(*iface)) == -1)
672 return (-1);
673 if (iface->auth_type == AUTH_CRYPT)
674 if (md_list_send(&iface->auth_md_list,
675 iev_ospfe) == -1)
676 return (-1);
677 }
678 }
679
680 if (ospf_sendboth(IMSG_RECONF_END, NULL((void*)0), 0) == -1)
681 return (-1);
682
683 merge_config(ospfd_conf, xconf);
684 /* update redistribute lists */
685 kr_reload(ospfd_conf->redist_label_or_prefix);
686 return (0);
687}
688
689int
690ospf_sendboth(enum imsg_type type, void *buf, u_int16_t len)
691{
692 if (imsg_compose_event(iev_ospfe, type, 0, 0, -1, buf, len) == -1)
693 return (-1);
694 if (imsg_compose_event(iev_rde, type, 0, 0, -1, buf, len) == -1)
695 return (-1);
696 return (0);
697}
698
699void
700merge_config(struct ospfd_conf *conf, struct ospfd_conf *xconf)
701{
702 struct area *a, *xa, *na;
703 struct iface *iface;
704 struct redistribute *r;
705 int rchange = 0;
706
707 conf->flags = xconf->flags;
708 conf->spf_delay = xconf->spf_delay;
709 conf->spf_hold_time = xconf->spf_hold_time;
710 if (SIMPLEQ_EMPTY(&conf->redist_list)(((&conf->redist_list)->sqh_first) == ((void*)0)) !=
711 SIMPLEQ_EMPTY(&xconf->redist_list)(((&xconf->redist_list)->sqh_first) == ((void*)0)))
712 rchange = 1;
713 conf->rfc1583compat = xconf->rfc1583compat;
714 conf->redist_label_or_prefix = xconf->redist_label_or_prefix;
715
716 if (ospfd_process == PROC_MAIN) {
717 /* main process does neither use areas nor interfaces */
718 while ((r = SIMPLEQ_FIRST(&conf->redist_list)((&conf->redist_list)->sqh_first)) != NULL((void*)0)) {
719 SIMPLEQ_REMOVE_HEAD(&conf->redist_list, entry)do { if (((&conf->redist_list)->sqh_first = (&conf
->redist_list)->sqh_first->entry.sqe_next) == ((void
*)0)) (&conf->redist_list)->sqh_last = &(&conf
->redist_list)->sqh_first; } while (0)
;
720 free(r);
721 }
722 SIMPLEQ_CONCAT(&conf->redist_list, &xconf->redist_list)do { if (!((((&xconf->redist_list))->sqh_first) == (
(void*)0))) { *(&conf->redist_list)->sqh_last = (&
xconf->redist_list)->sqh_first; (&conf->redist_list
)->sqh_last = (&xconf->redist_list)->sqh_last; do
{ ((&xconf->redist_list))->sqh_first = ((void*)0);
((&xconf->redist_list))->sqh_last = &((&xconf
->redist_list))->sqh_first; } while (0); } } while (0)
;
723
724 /* adjust FIB priority if changed */
725 if (conf->fib_priority != xconf->fib_priority) {
726 kr_fib_decouple();
727 kr_fib_update_prio(xconf->fib_priority);
728 conf->fib_priority = xconf->fib_priority;
729 kr_fib_couple();
730 }
731
732 goto done;
733 }
734
735 /* merge areas and interfaces */
736 for (a = LIST_FIRST(&conf->area_list)((&conf->area_list)->lh_first); a != NULL((void*)0); a = na) {
737 na = LIST_NEXT(a, entry)((a)->entry.le_next);
738 /* find deleted areas */
739 if ((xa = area_find(xconf, a->id)) == NULL((void*)0)) {
Although the value stored to 'xa' is used in the enclosing expression, the value is never actually read from 'xa'
740 if (ospfd_process == PROC_OSPF_ENGINE) {
741 LIST_FOREACH(iface, &a->iface_list, entry)for((iface) = ((&a->iface_list)->lh_first); (iface)
!= ((void*)0); (iface) = ((iface)->entry.le_next))
742 if_fsm(iface, IF_EVT_DOWN);
743 }
744 LIST_REMOVE(a, entry)do { if ((a)->entry.le_next != ((void*)0)) (a)->entry.le_next
->entry.le_prev = (a)->entry.le_prev; *(a)->entry.le_prev
= (a)->entry.le_next; ; ; } while (0)
;
745 area_del(a);
746 }
747 }
748
749 for (xa = LIST_FIRST(&xconf->area_list)((&xconf->area_list)->lh_first); xa != NULL((void*)0); xa = na) {
750 na = LIST_NEXT(xa, entry)((xa)->entry.le_next);
751 if ((a = area_find(conf, xa->id)) == NULL((void*)0)) {
752 LIST_REMOVE(xa, entry)do { if ((xa)->entry.le_next != ((void*)0)) (xa)->entry
.le_next->entry.le_prev = (xa)->entry.le_prev; *(xa)->
entry.le_prev = (xa)->entry.le_next; ; ; } while (0)
;
753 LIST_INSERT_HEAD(&conf->area_list, xa, entry)do { if (((xa)->entry.le_next = (&conf->area_list)->
lh_first) != ((void*)0)) (&conf->area_list)->lh_first
->entry.le_prev = &(xa)->entry.le_next; (&conf->
area_list)->lh_first = (xa); (xa)->entry.le_prev = &
(&conf->area_list)->lh_first; } while (0)
;
754 if (ospfd_process == PROC_OSPF_ENGINE) {
755 /* start interfaces */
756 ospfe_demote_area(xa, 0);
757 LIST_FOREACH(iface, &xa->iface_list, entry)for((iface) = ((&xa->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
758 if_init(conf, iface);
759 if (if_fsm(iface, IF_EVT_UP)) {
760 log_debug("error starting "
761 "interface %s",
762 iface->name);
763 }
764 }
765 }
766 /* no need to merge interfaces */
767 continue;
768 }
769 /*
770 * stub is not yet used but switching between stub and normal
771 * will be another painful job.
772 */
773 if (a->stub != xa->stub && ospfd_process == PROC_OSPF_ENGINE)
774 a->dirty = 1; /* force rtr LSA update */
775 if (xa->stub && ospfd_process == PROC_RDE_ENGINE) {
776 while ((r = SIMPLEQ_FIRST(&a->redist_list)((&a->redist_list)->sqh_first)) != NULL((void*)0)) {
777 SIMPLEQ_REMOVE_HEAD(&a->redist_list, entry)do { if (((&a->redist_list)->sqh_first = (&a->
redist_list)->sqh_first->entry.sqe_next) == ((void*)0))
(&a->redist_list)->sqh_last = &(&a->redist_list
)->sqh_first; } while (0)
;
778 free(r);
779 }
780
781 SIMPLEQ_CONCAT(&a->redist_list, &xa->redist_list)do { if (!((((&xa->redist_list))->sqh_first) == ((void
*)0))) { *(&a->redist_list)->sqh_last = (&xa->
redist_list)->sqh_first; (&a->redist_list)->sqh_last
= (&xa->redist_list)->sqh_last; do { ((&xa->
redist_list))->sqh_first = ((void*)0); ((&xa->redist_list
))->sqh_last = &((&xa->redist_list))->sqh_first
; } while (0); } } while (0)
;
782 }
783
784 a->stub = xa->stub;
785 a->stub_default_cost = xa->stub_default_cost;
786 if (ospfd_process == PROC_RDE_ENGINE)
787 a->dirty = 1; /* force SPF tree recalculation */
788
789 /* merge interfaces */
790 if (merge_interfaces(a, xa) &&
791 ospfd_process == PROC_OSPF_ENGINE)
792 a->dirty = 1; /* force rtr LSA update */
793 }
794
795 if (ospfd_process == PROC_OSPF_ENGINE) {
796 LIST_FOREACH(a, &conf->area_list, entry)for((a) = ((&conf->area_list)->lh_first); (a)!= ((void
*)0); (a) = ((a)->entry.le_next))
{
797 LIST_FOREACH(iface, &a->iface_list, entry)for((iface) = ((&a->iface_list)->lh_first); (iface)
!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
798 if (iface->state == IF_STA_NEW0x00) {
799 iface->state = IF_STA_DOWN0x01;
800 if_init(conf, iface);
801 if (if_fsm(iface, IF_EVT_UP)) {
802 log_debug("error starting "
803 "interface %s",
804 iface->name);
805 }
806 }
807 }
808 if (a->dirty || rchange) {
809 a->dirty = 0;
810 orig_rtr_lsa(a);
811 }
812 }
813 }
814 if (ospfd_process == PROC_RDE_ENGINE) {
815 LIST_FOREACH(a, &conf->area_list, entry)for((a) = ((&conf->area_list)->lh_first); (a)!= ((void
*)0); (a) = ((a)->entry.le_next))
{
816 if (a->dirty) {
817 start_spf_timer();
818 break;
819 }
820 }
821 }
822
823done:
824 while ((a = LIST_FIRST(&xconf->area_list)((&xconf->area_list)->lh_first)) != NULL((void*)0)) {
825 LIST_REMOVE(a, entry)do { if ((a)->entry.le_next != ((void*)0)) (a)->entry.le_next
->entry.le_prev = (a)->entry.le_prev; *(a)->entry.le_prev
= (a)->entry.le_next; ; ; } while (0)
;
826 area_del(a);
827 }
828 free(xconf);
829}
830
831int
832merge_interfaces(struct area *a, struct area *xa)
833{
834 struct iface *i, *xi, *ni;
835 int dirty = 0;
836
837 /* problems:
838 * - new interfaces (easy)
839 * - deleted interfaces
840 * - changing passive (painful?)
841 */
842 for (i = LIST_FIRST(&a->iface_list)((&a->iface_list)->lh_first); i != NULL((void*)0); i = ni) {
843 ni = LIST_NEXT(i, entry)((i)->entry.le_next);
844 if (iface_lookup(xa, i) == NULL((void*)0)) {
845 log_debug("merge_interfaces: proc %d area %s removing "
846 "interface %s", ospfd_process, inet_ntoa(a->id),
847 i->name);
848 if (ospfd_process == PROC_OSPF_ENGINE)
849 if_fsm(i, IF_EVT_DOWN);
850 else if (ospfd_process == PROC_RDE_ENGINE)
851 rde_nbr_iface_del(i);
852 LIST_REMOVE(i, entry)do { if ((i)->entry.le_next != ((void*)0)) (i)->entry.le_next
->entry.le_prev = (i)->entry.le_prev; *(i)->entry.le_prev
= (i)->entry.le_next; ; ; } while (0)
;
853 if_del(i);
854 dirty = 1; /* force rtr LSA update */
855 }
856 }
857
858 for (xi = LIST_FIRST(&xa->iface_list)((&xa->iface_list)->lh_first); xi != NULL((void*)0); xi = ni) {
859 ni = LIST_NEXT(xi, entry)((xi)->entry.le_next);
860 if ((i = iface_lookup(a, xi)) == NULL((void*)0)) {
861 /* new interface but delay initialisation */
862 log_debug("merge_interfaces: proc %d area %s adding "
863 "interface %s", ospfd_process, inet_ntoa(a->id),
864 xi->name);
865 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)
;
866 LIST_INSERT_HEAD(&a->iface_list, xi, entry)do { if (((xi)->entry.le_next = (&a->iface_list)->
lh_first) != ((void*)0)) (&a->iface_list)->lh_first
->entry.le_prev = &(xi)->entry.le_next; (&a->
iface_list)->lh_first = (xi); (xi)->entry.le_prev = &
(&a->iface_list)->lh_first; } while (0)
;
867 xi->area = a;
868 if (ospfd_process == PROC_OSPF_ENGINE)
869 xi->state = IF_STA_NEW0x00;
870 continue;
871 }
872 log_debug("merge_interfaces: proc %d area %s merging "
873 "interface %s", ospfd_process, inet_ntoa(a->id), i->name);
874 i->dst = xi->dst;
875 i->abr_id = xi->abr_id;
876 i->baudrate = xi->baudrate;
877 i->dead_interval = xi->dead_interval;
878 i->mtu = xi->mtu;
879 i->transmit_delay = xi->transmit_delay;
880 i->hello_interval = xi->hello_interval;
881 i->rxmt_interval = xi->rxmt_interval;
882 if (i->metric != xi->metric)
883 dirty = 1;
884 i->metric = xi->metric;
885 i->priority = xi->priority;
886 if (i->self)
887 i->self->priority = i->priority;
888 i->flags = xi->flags; /* needed? */
889 i->if_type = xi->if_type; /* needed? */
890 i->linkstate = xi->linkstate; /* needed? */
891
892 i->auth_type = xi->auth_type;
893 strncpy(i->auth_key, xi->auth_key, MAX_SIMPLE_AUTH_LEN8);
894 md_list_clr(&i->auth_md_list);
895 md_list_copy(&i->auth_md_list, &xi->auth_md_list);
896
897 strlcpy(i->dependon, xi->dependon,
898 sizeof(i->dependon));
899 i->depend_ok = xi->depend_ok;
900
901 if (i->passive != xi->passive) {
902 /* need to restart interface to cope with this change */
903 if (ospfd_process == PROC_OSPF_ENGINE)
904 if_fsm(i, IF_EVT_DOWN);
905 i->passive = xi->passive;
906 if (ospfd_process == PROC_OSPF_ENGINE)
907 if_fsm(i, IF_EVT_UP);
908 }
909
910 if (i->type != xi->type) {
911 /* restart interface to enable or disable DR election */
912 if (ospfd_process == PROC_OSPF_ENGINE)
913 if_fsm(i, IF_EVT_DOWN);
914 i->type = xi->type;
915 if (ospfd_process == PROC_OSPF_ENGINE)
916 if_fsm(i, IF_EVT_UP);
917 }
918 }
919 return (dirty);
920}
921
922struct iface *
923iface_lookup(struct area *area, struct iface *iface)
924{
925 struct iface *i;
926
927 LIST_FOREACH(i, &area->iface_list, entry)for((i) = ((&area->iface_list)->lh_first); (i)!= ((
void*)0); (i) = ((i)->entry.le_next))
928 if (i->ifindex == iface->ifindex &&
929 i->addr.s_addr == iface->addr.s_addr &&
930 i->mask.s_addr == iface->mask.s_addr)
931 return (i);
932 return (NULL((void*)0));
933}
934
935int
936ifstate_is_up(struct kif *kif)
937{
938 if (!(kif->flags & IFF_UP0x1))
939 return (0);
940 if (kif->if_type == IFT_CARP0xf7 &&
941 kif->link_state == LINK_STATE_UNKNOWN0)
942 return (0);
943 return LINK_STATE_IS_UP(kif->link_state)((kif->link_state) >= 4 || (kif->link_state) == 0);
944}