Bug Summary

File:src/usr.sbin/ospf6d/ospf6d.c
Warning:line 694, 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 ospf6d.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/ospf6d/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ospf6d -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ospf6d/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/ospf6d/ospf6d.c
1/* $OpenBSD: ospf6d.c,v 1.51 2021/09/06 13:32:18 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004, 2007 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 "ospf6d.h"
45#include "ospf6.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 [-dnv] [-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 int ch, opts = 0;
114 int debug = 0;
115 int ipforwarding;
116 int mib[4];
117 size_t len;
118 char *sockname = NULL((void*)0);
119 int control_fd;
120
121 conffile = CONF_FILE"/etc/ospf6d.conf";
122 ospfd_process = PROC_MAIN;
123
124 log_init(1, LOG_DAEMON(3<<3)); /* log to stderr until daemonized */
125 log_procinit(log_procnames[ospfd_process]);
126
127 while ((ch = getopt(argc, argv, "cdD:f:s:nv")) != -1) {
128 switch (ch) {
129 case 'c':
130 opts |= OSPFD_OPT_FORCE_DEMOTE0x00000010;
131 break;
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 opts |= OSPFD_OPT_NOACTION0x00000004;
145 break;
146 case 's':
147 sockname = optarg;
148 break;
149 case 'v':
150 if (opts & OSPFD_OPT_VERBOSE0x00000001)
151 opts |= OSPFD_OPT_VERBOSE20x00000002;
152 opts |= OSPFD_OPT_VERBOSE0x00000001;
153 log_setverbose(1);
154 break;
155 default:
156 usage();
157 /* NOTREACHED */
158 }
159 }
160
161 argc -= optind;
162 argv += optind;
163 if (argc > 0)
164 usage();
165
166 mib[0] = CTL_NET4;
167 mib[1] = PF_INET624;
168 mib[2] = IPPROTO_IPV641;
169 mib[3] = IPCTL_FORWARDING1;
170 len = sizeof(ipforwarding);
171 if (sysctl(mib, 4, &ipforwarding, &len, NULL((void*)0), 0) == -1)
172 err(1, "sysctl");
173
174 if (ipforwarding != 1) {
175 log_warnx("WARNING: IPv6 forwarding NOT enabled, "
176 "running as stub router");
177 opts |= OSPFD_OPT_STUB_ROUTER0x00000008;
178 }
179
180 /* prepare and fetch interfaces early */
181 if_init();
182
183 /* parse config file */
184 if ((ospfd_conf = parse_config(conffile, opts)) == NULL((void*)0) )
185 exit(1);
186
187 if (sockname == NULL((void*)0)) {
188 if (asprintf(&sockname, "%s.%d", OSPF6D_SOCKET"/var/run/ospf6d.sock",
189 ospfd_conf->rdomain) == -1)
190 err(1, "asprintf");
191 }
192
193 ospfd_conf->csock = sockname;
194
195 if (ospfd_conf->opts & OSPFD_OPT_NOACTION0x00000004) {
196 if (ospfd_conf->opts & OSPFD_OPT_VERBOSE0x00000001)
197 print_config(ospfd_conf);
198 else
199 fprintf(stderr(&__sF[2]), "configuration OK\n");
200 exit(0);
201 }
202
203 /* check for root privileges */
204 if (geteuid())
205 errx(1, "need root privileges");
206
207 /* check for ospfd user */
208 if (getpwnam(OSPF6D_USER"_ospf6d") == NULL((void*)0))
209 errx(1, "unknown user %s", OSPF6D_USER"_ospf6d");
210
211 log_init(debug, LOG_DAEMON(3<<3));
212 log_setverbose(ospfd_conf->opts & OSPFD_OPT_VERBOSE0x00000001);
213
214 if ((control_check(ospfd_conf->csock)) == -1)
215 fatalx("ospf6d already running");
216
217 if (!debug)
218 daemon(1, 0);
219
220 log_info("startup");
221
222 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
223 PF_UNSPEC0, pipe_parent2ospfe) == -1)
224 fatal("socketpair");
225 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
226 PF_UNSPEC0, pipe_parent2rde) == -1)
227 fatal("socketpair");
228 if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
229 PF_UNSPEC0, pipe_ospfe2rde) == -1)
230 fatal("socketpair");
231
232 /* start children */
233 rde_pid = rde(ospfd_conf, pipe_parent2rde, pipe_ospfe2rde,
234 pipe_parent2ospfe);
235 ospfe_pid = ospfe(ospfd_conf, pipe_parent2ospfe, pipe_ospfe2rde,
236 pipe_parent2rde);
237
238 event_init();
239
240 /* setup signal handler */
241 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void
*)0))
;
242 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, (
(void*)0))
;
243 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void
*)0))
;
244 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0));
245 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0));
246 signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void*)0));
247 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
248
249 /* setup pipes to children */
250 close(pipe_parent2ospfe[1]);
251 close(pipe_parent2rde[1]);
252 close(pipe_ospfe2rde[0]);
253 close(pipe_ospfe2rde[1]);
254
255 if ((iev_ospfe = malloc(sizeof(struct imsgev))) == NULL((void*)0) ||
256 (iev_rde = malloc(sizeof(struct imsgev))) == NULL((void*)0))
257 fatal(NULL((void*)0));
258 imsg_init(&iev_ospfe->ibuf, pipe_parent2ospfe[0]);
259 iev_ospfe->handler = main_dispatch_ospfe;
260 imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]);
261 iev_rde->handler = main_dispatch_rde;
262
263 /* setup event handler */
264 iev_ospfe->events = EV_READ0x02;
265 event_set(&iev_ospfe->ev, iev_ospfe->ibuf.fd, iev_ospfe->events,
266 iev_ospfe->handler, iev_ospfe);
267 event_add(&iev_ospfe->ev, NULL((void*)0));
268
269 iev_rde->events = EV_READ0x02;
270 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
271 iev_rde->handler, iev_rde);
272 event_add(&iev_rde->ev, NULL((void*)0));
273
274 if ((control_fd = control_init(ospfd_conf->csock)) == -1)
275 fatalx("control socket setup failed");
276 main_imsg_compose_ospfe_fd(IMSG_CONTROLFD, 0, control_fd);
277
278 /* no filesystem visibility */
279 if (unveil("/", "") == -1)
280 fatal("unveil /");
281 if (unveil(NULL((void*)0), NULL((void*)0)) == -1)
282 fatal("unveil");
283
284 if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE0x0001),
285 ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix,
286 ospfd_conf->fib_priority) == -1)
287 fatalx("kr_init failed");
288
289 event_dispatch();
290
291 ospfd_shutdown();
292 /* NOTREACHED */
293 return (0);
294}
295
296__dead__attribute__((__noreturn__)) void
297ospfd_shutdown(void)
298{
299 pid_t pid;
300 int status;
301
302 /* close pipes */
303 msgbuf_clear(&iev_ospfe->ibuf.w);
304 close(iev_ospfe->ibuf.fd);
305 msgbuf_clear(&iev_rde->ibuf.w);
306 close(iev_rde->ibuf.fd);
307
308 control_cleanup();
309 kr_shutdown();
310 carp_demote_shutdown();
311
312 log_debug("waiting for children to terminate");
313 do {
314 pid = wait(&status);
315 if (pid == -1) {
316 if (errno(*__errno()) != EINTR4 && errno(*__errno()) != ECHILD10)
317 fatal("wait");
318 } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
)
319 log_warnx("%s terminated; signal %d",
320 (pid == rde_pid) ? "route decision engine" :
321 "ospf engine", WTERMSIG(status)(((status) & 0177)));
322 } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4));
323
324 free(iev_ospfe);
325 free(iev_rde);
326 free(ospfd_conf);
327
328 log_info("terminating");
329 exit(0);
330}
331
332/* imsg handling */
333/* ARGSUSED */
334void
335main_dispatch_ospfe(int fd, short event, void *bula)
336{
337 struct imsgev *iev = bula;
338 struct imsgbuf *ibuf = &iev->ibuf;
339 struct imsg imsg;
340 struct demote_msg dmsg;
341 ssize_t n;
342 int shut = 0, verbose;
343
344 if (event & EV_READ0x02) {
345 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
346 fatal("imsg_read error");
347 if (n == 0) /* connection closed */
348 shut = 1;
349 }
350 if (event & EV_WRITE0x04) {
351 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
352 fatal("msgbuf_write");
353 if (n == 0) /* connection closed */
354 shut = 1;
355 }
356
357 for (;;) {
358 if ((n = imsg_get(ibuf, &imsg)) == -1)
359 fatal("imsg_get");
360
361 if (n == 0)
362 break;
363
364 switch (imsg.hdr.type) {
365 case IMSG_CTL_RELOAD:
366 if (ospf_reload() == -1)
367 log_warnx("configuration reload failed");
368 else
369 log_debug("configuration reloaded");
370 break;
371 case IMSG_CTL_FIB_COUPLE:
372 kr_fib_couple();
373 break;
374 case IMSG_CTL_FIB_DECOUPLE:
375 kr_fib_decouple();
376 break;
377 case IMSG_CTL_KROUTE:
378 case IMSG_CTL_KROUTE_ADDR:
379 kr_show_route(&imsg);
380 break;
381 case IMSG_DEMOTE:
382 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(dmsg))
383 fatalx("invalid size of OE request");
384 memcpy(&dmsg, imsg.data, sizeof(dmsg));
385 carp_demote_set(dmsg.demote_group, dmsg.level);
386 break;
387 case IMSG_CTL_LOG_VERBOSE:
388 /* already checked by ospfe */
389 memcpy(&verbose, imsg.data, sizeof(verbose));
390 log_setverbose(verbose);
391 break;
392 default:
393 log_debug("main_dispatch_ospfe: error handling imsg %d",
394 imsg.hdr.type);
395 break;
396 }
397 imsg_free(&imsg);
398 }
399 if (!shut)
400 imsg_event_add(iev);
401 else {
402 /* this pipe is dead, so remove the event handler */
403 event_del(&iev->ev);
404 event_loopexit(NULL((void*)0));
405 }
406}
407
408/* ARGSUSED */
409void
410main_dispatch_rde(int fd, short event, void *bula)
411{
412 struct imsgev *iev = bula;
413 struct imsgbuf *ibuf = &iev->ibuf;
414 struct imsg imsg;
415 ssize_t n;
416 int count, shut = 0;
417
418 if (event & EV_READ0x02) {
419 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
420 fatal("imsg_read error");
421 if (n == 0) /* connection closed */
422 shut = 1;
423 }
424 if (event & EV_WRITE0x04) {
425 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
426 fatal("msgbuf_write");
427 if (n == 0) /* connection closed */
428 shut = 1;
429 }
430
431 for (;;) {
432 if ((n = imsg_get(ibuf, &imsg)) == -1)
433 fatal("imsg_get");
434
435 if (n == 0)
436 break;
437
438 switch (imsg.hdr.type) {
439 case IMSG_KROUTE_CHANGE:
440 count = (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)) /
441 sizeof(struct kroute);
442 if (kr_change(imsg.data, count))
443 log_warn("main_dispatch_rde: error changing "
444 "route");
445 break;
446 case IMSG_KROUTE_DELETE:
447 if (kr_delete(imsg.data))
448 log_warn("main_dispatch_rde: error deleting "
449 "route");
450 break;
451 default:
452 log_debug("main_dispatch_rde: error handling imsg %d",
453 imsg.hdr.type);
454 break;
455 }
456 imsg_free(&imsg);
457 }
458 if (!shut)
459 imsg_event_add(iev);
460 else {
461 /* this pipe is dead, so remove the event handler */
462 event_del(&iev->ev);
463 event_loopexit(NULL((void*)0));
464 }
465}
466
467void
468main_imsg_compose_ospfe(int type, pid_t pid, void *data, u_int16_t datalen)
469{
470 if (iev_ospfe == NULL((void*)0))
471 return;
472 imsg_compose_event(iev_ospfe, type, 0, pid, -1, data, datalen);
473}
474
475void
476main_imsg_compose_ospfe_fd(int type, pid_t pid, int fd)
477{
478 if (iev_ospfe == NULL((void*)0))
479 return;
480 imsg_compose_event(iev_ospfe, type, 0, pid, fd, NULL((void*)0), 0);
481}
482
483void
484main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen)
485{
486 if (iev_rde == NULL((void*)0))
487 return;
488 imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen);
489}
490
491void
492imsg_event_add(struct imsgev *iev)
493{
494 iev->events = EV_READ0x02;
495 if (iev->ibuf.w.queued)
496 iev->events |= EV_WRITE0x04;
497
498 event_del(&iev->ev);
499 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
500 event_add(&iev->ev, NULL((void*)0));
501}
502
503int
504imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
505 pid_t pid, int fd, void *data, u_int16_t datalen)
506{
507 int ret;
508
509 if ((ret = imsg_compose(&iev->ibuf, type, peerid,
510 pid, fd, data, datalen)) != -1)
511 imsg_event_add(iev);
512 return (ret);
513}
514
515int
516ospf_redistribute(struct kroute *kr, u_int32_t *metric)
517{
518 struct redistribute *r;
519 struct in6_addr ina, inb;
520 struct iface *iface;
521 u_int8_t is_default = 0;
522 int depend_ok;
523
524 /* only allow ::/0 via REDIST_DEFAULT */
525 if (IN6_IS_ADDR_UNSPECIFIED(&kr->prefix)((*(const u_int32_t *)(const void *)(&(&kr->prefix
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&kr->prefix)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&kr->prefix)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&kr->prefix
)->__u6_addr.__u6_addr8[12]) == 0))
&& kr->prefixlen == 0)
526 is_default = 1;
527
528 SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry)for((r) = ((&ospfd_conf->redist_list)->sqh_first); (
r) != ((void*)0); (r) = ((r)->entry.sqe_next))
{
529 if (r->dependon[0] != '\0') {
530 if ((iface = if_findname(r->dependon)))
531 depend_ok = ifstate_is_up(iface);
532 else
533 depend_ok = 0;
534 } else
535 depend_ok = 1;
536
537 switch (r->type & ~REDIST_NO0x10) {
538 case REDIST_LABEL0x04:
539 if (kr->rtlabel == r->label) {
540 *metric = depend_ok ? r->metric :
541 r->metric | MAX_METRIC65535;
542 return (r->type & REDIST_NO0x10 ? 0 : 1);
543 }
544 break;
545 case REDIST_STATIC0x02:
546 /*
547 * Dynamic routes are not redistributable. Placed here
548 * so that link local addresses can be redistributed
549 * via a rtlabel.
550 */
551 if (is_default)
552 continue;
553 if (kr->flags & F_DYNAMIC0x0040)
554 continue;
555 if (kr->flags & F_STATIC0x0020) {
556 *metric = depend_ok ? r->metric :
557 r->metric | MAX_METRIC65535;
558 return (r->type & REDIST_NO0x10 ? 0 : 1);
559 }
560 break;
561 case REDIST_CONNECTED0x01:
562 if (is_default)
563 continue;
564 if (kr->flags & F_DYNAMIC0x0040)
565 continue;
566 if (kr->flags & F_CONNECTED0x0008) {
567 *metric = depend_ok ? r->metric :
568 r->metric | MAX_METRIC65535;
569 return (r->type & REDIST_NO0x10 ? 0 : 1);
570 }
571 break;
572 case REDIST_ADDR0x08:
573 if (kr->flags & F_DYNAMIC0x0040)
574 continue;
575
576 if (IN6_IS_ADDR_UNSPECIFIED(&r->addr)((*(const u_int32_t *)(const void *)(&(&r->addr)->
__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *
)(const void *)(&(&r->addr)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&r->addr)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&r->addr)->
__u6_addr.__u6_addr8[12]) == 0))
&&
577 r->prefixlen == 0) {
578 if (is_default) {
579 *metric = depend_ok ? r->metric :
580 r->metric | MAX_METRIC65535;
581 return (r->type & REDIST_NO0x10 ? 0 : 1);
582 } else
583 return (0);
584 }
585
586 inet6applymask(&ina, &kr->prefix, r->prefixlen);
587 inet6applymask(&inb, &r->addr, r->prefixlen);
588 if (IN6_ARE_ADDR_EQUAL(&ina, &inb)(memcmp(&(&ina)->__u6_addr.__u6_addr8[0], &(&
inb)->__u6_addr.__u6_addr8[0], sizeof(struct in6_addr)) ==
0)
&&
589 kr->prefixlen >= r->prefixlen) {
590 *metric = depend_ok ? r->metric :
591 r->metric | MAX_METRIC65535;
592 return (r->type & REDIST_NO0x10 ? 0 : 1);
593 }
594 break;
595 case REDIST_DEFAULT0x20:
596 if (is_default) {
597 *metric = depend_ok ? r->metric :
598 r->metric | MAX_METRIC65535;
599 return (r->type & REDIST_NO0x10 ? 0 : 1);
600 }
601 break;
602 }
603 }
604
605 return (0);
606}
607
608int
609ospf_reload(void)
610{
611#ifdef notyet
612 struct area *area;
613 struct ospfd_conf *xconf;
614
615 if ((xconf = parse_config(conffile, ospfd_conf->opts)) == NULL((void*)0))
616 return (-1);
617
618 /* XXX bail out if router-id changed */
619
620 /* send config to childs */
621 if (ospf_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
622 return (-1);
623
624 /* send areas, interfaces happen out of band */
625 LIST_FOREACH(area, &xconf->area_list, entry)for((area) = ((&xconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
{
626 if (ospf_sendboth(IMSG_RECONF_AREA, area, sizeof(*area)) == -1)
627 return (-1);
628 }
629
630 if (ospf_sendboth(IMSG_RECONF_END, NULL((void*)0), 0) == -1)
631 return (-1);
632
633 /* XXX send newly available interfaces to the childs */
634
635 merge_config(ospfd_conf, xconf);
636 /* update redistribute lists */
637 kr_reload(ospfd_conf->redist_label_or_prefix);
638 return (0);
639#else
640 return (-1);
641#endif
642}
643
644int
645ospf_sendboth(enum imsg_type type, void *buf, u_int16_t len)
646{
647 if (imsg_compose_event(iev_ospfe, type, 0, 0, -1, buf, len) == -1)
648 return (-1);
649 if (imsg_compose_event(iev_rde, type, 0, 0, -1, buf, len) == -1)
650 return (-1);
651 return (0);
652}
653
654void
655merge_config(struct ospfd_conf *conf, struct ospfd_conf *xconf)
656{
657 struct area *a, *xa, *na;
658 struct iface *iface;
659 struct redistribute *r;
660 int rchange = 0;
661
662 /* change of rtr_id needs a restart */
663 conf->flags = xconf->flags;
664 conf->spf_delay = xconf->spf_delay;
665 conf->spf_hold_time = xconf->spf_hold_time;
666 if (SIMPLEQ_EMPTY(&conf->redist_list)(((&conf->redist_list)->sqh_first) == ((void*)0)) !=
667 SIMPLEQ_EMPTY(&xconf->redist_list)(((&xconf->redist_list)->sqh_first) == ((void*)0)))
668 rchange = 1;
669 conf->redist_label_or_prefix = xconf->redist_label_or_prefix;
670
671 if (ospfd_process == PROC_MAIN) {
672 /* main process does neither use areas nor interfaces */
673 while ((r = SIMPLEQ_FIRST(&conf->redist_list)((&conf->redist_list)->sqh_first)) != NULL((void*)0)) {
674 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)
;
675 free(r);
676 }
677 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)
;
678
679 /* adjust FIB priority if changed */
680 if (conf->fib_priority != xconf->fib_priority) {
681 kr_fib_decouple();
682 kr_fib_update_prio(xconf->fib_priority);
683 conf->fib_priority = xconf->fib_priority;
684 kr_fib_couple();
685 }
686
687 goto done;
688 }
689
690 /* merge areas and interfaces */
691 for (a = LIST_FIRST(&conf->area_list)((&conf->area_list)->lh_first); a != NULL((void*)0); a = na) {
692 na = LIST_NEXT(a, entry)((a)->entry.le_next);
693 /* find deleted areas */
694 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'
695 if (ospfd_process == PROC_OSPF_ENGINE) {
696 LIST_FOREACH(iface, &a->iface_list, entry)for((iface) = ((&a->iface_list)->lh_first); (iface)
!= ((void*)0); (iface) = ((iface)->entry.le_next))
697 if_fsm(iface, IF_EVT_DOWN);
698 }
699 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)
;
700 area_del(a);
701 }
702 }
703
704 for (xa = LIST_FIRST(&xconf->area_list)((&xconf->area_list)->lh_first); xa != NULL((void*)0); xa = na) {
705 na = LIST_NEXT(xa, entry)((xa)->entry.le_next);
706 if ((a = area_find(conf, xa->id)) == NULL((void*)0)) {
707 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)
;
708 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)
;
709 if (ospfd_process == PROC_OSPF_ENGINE) {
710 /* start interfaces */
711 ospfe_demote_area(xa, 0);
712 LIST_FOREACH(iface, &xa->iface_list, entry)for((iface) = ((&xa->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
713 if_start(conf, iface);
714 }
715 /* no need to merge interfaces */
716 continue;
717 }
718 /*
719 * stub is not yet used but switching between stub and normal
720 * will be another painful job.
721 */
722 a->stub = xa->stub;
723 a->stub_default_cost = xa->stub_default_cost;
724 if (ospfd_process == PROC_RDE_ENGINE)
725 a->dirty = 1; /* force SPF tree recalculation */
726
727 /* merge interfaces */
728 if (merge_interfaces(a, xa) &&
729 ospfd_process == PROC_OSPF_ENGINE)
730 a->dirty = 1; /* force rtr LSA update */
731 }
732
733 if (ospfd_process == PROC_OSPF_ENGINE) {
734 LIST_FOREACH(a, &conf->area_list, entry)for((a) = ((&conf->area_list)->lh_first); (a)!= ((void
*)0); (a) = ((a)->entry.le_next))
{
735 LIST_FOREACH(iface, &a->iface_list, entry)for((iface) = ((&a->iface_list)->lh_first); (iface)
!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
736 if (iface->state == IF_STA_NEW0x00) {
737 iface->state = IF_STA_DOWN0x01;
738 if_start(conf, iface);
739 }
740 }
741 if (a->dirty) {
742 a->dirty = 0;
743 orig_rtr_lsa(LIST_FIRST(&a->iface_list)((&a->iface_list)->lh_first)->area);
744 }
745 }
746 }
747
748done:
749 while ((a = LIST_FIRST(&xconf->area_list)((&xconf->area_list)->lh_first)) != NULL((void*)0)) {
750 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)
;
751 area_del(a);
752 }
753 free(xconf);
754}
755
756int
757merge_interfaces(struct area *a, struct area *xa)
758{
759 struct iface *i, *xi, *ni;
760 int dirty = 0;
761
762 /* problems:
763 * - new interfaces (easy)
764 * - deleted interfaces (needs to be done via fsm?)
765 * - changing passive (painful?)
766 */
767 for (i = LIST_FIRST(&a->iface_list)((&a->iface_list)->lh_first); i != NULL((void*)0); i = ni) {
768 ni = LIST_NEXT(i, entry)((i)->entry.le_next);
769 if (iface_lookup(xa, i) == NULL((void*)0)) {
770 log_debug("merge_interfaces: proc %d area %s removing "
771 "interface %s", ospfd_process, inet_ntoa(a->id),
772 i->name);
773 if (ospfd_process == PROC_OSPF_ENGINE)
774 if_fsm(i, IF_EVT_DOWN);
775 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)
;
776 if_del(i);
777 }
778 }
779
780 for (xi = LIST_FIRST(&xa->iface_list)((&xa->iface_list)->lh_first); xi != NULL((void*)0); xi = ni) {
781 ni = LIST_NEXT(xi, entry)((xi)->entry.le_next);
782 if ((i = iface_lookup(a, xi)) == NULL((void*)0)) {
783 /* new interface but delay initialisation */
784 log_debug("merge_interfaces: proc %d area %s adding "
785 "interface %s", ospfd_process, inet_ntoa(a->id),
786 xi->name);
787 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)
;
788 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)
;
789 if (ospfd_process == PROC_OSPF_ENGINE)
790 xi->state = IF_STA_NEW0x00;
791 continue;
792 }
793 log_debug("merge_interfaces: proc %d area %s merging "
794 "interface %s", ospfd_process, inet_ntoa(a->id), i->name);
795 i->addr = xi->addr;
796 i->dst = xi->dst;
797 i->abr_id = xi->abr_id;
798 i->baudrate = xi->baudrate;
799 i->dead_interval = xi->dead_interval;
800 i->mtu = xi->mtu;
801 i->transmit_delay = xi->transmit_delay;
802 i->hello_interval = xi->hello_interval;
803 i->rxmt_interval = xi->rxmt_interval;
804 if (i->metric != xi->metric)
805 dirty = 1;
806 i->metric = xi->metric;
807 i->priority = xi->priority;
808 if (i->self)
809 i->self->priority = i->priority;
810 i->flags = xi->flags; /* needed? */
811 i->type = xi->type; /* needed? */
812 i->if_type = xi->if_type; /* needed? */
813 i->linkstate = xi->linkstate; /* needed? */
814
815#if 0 /* XXX needs some kind of love */
816 if (i->passive != xi->passive) {
817 /* need to restart interface to cope with this change */
818 if (ospfd_process == PROC_OSPF_ENGINE)
819 if_fsm(i, IF_EVT_DOWN);
820 i->passive = xi->passive;
821 if (ospfd_process == PROC_OSPF_ENGINE)
822 if_fsm(i, IF_EVT_UP);
823 }
824#endif
825 }
826 return (dirty);
827}
828
829struct iface *
830iface_lookup(struct area *area, struct iface *iface)
831{
832 struct iface *i;
833
834 LIST_FOREACH(i, &area->iface_list, entry)for((i) = ((&area->iface_list)->lh_first); (i)!= ((
void*)0); (i) = ((i)->entry.le_next))
835 if (i->ifindex == iface->ifindex)
836 return (i);
837 return (NULL((void*)0));
838}
839
840int
841ifstate_is_up(struct iface *iface)
842{
843 if (!(iface->flags & IFF_UP0x1))
844 return (0);
845 if (iface->if_type == IFT_CARP0xf7 &&
846 iface->linkstate == LINK_STATE_UNKNOWN0)
847 return (0);
848 return LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0);
849}