Bug Summary

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