Bug Summary

File:src/usr.sbin/ospf6d/ospfe.c
Warning:line 391, column 9
Access to field 'flags' results in a dereference of a null pointer (loaded from variable 'noeconf')

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 ospfe.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/ospfe.c
1/* $OpenBSD: ospfe.c,v 1.67 2021/01/19 09:54:08 claudio 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 <netinet/in.h>
25#include <arpa/inet.h>
26#include <net/if_types.h>
27#include <stdlib.h>
28#include <signal.h>
29#include <string.h>
30#include <fcntl.h>
31#include <pwd.h>
32#include <unistd.h>
33#include <event.h>
34#include <err.h>
35#include <errno(*__errno()).h>
36#include <stdio.h>
37
38#include "ospf6.h"
39#include "ospf6d.h"
40#include "ospfe.h"
41#include "rde.h"
42#include "control.h"
43#include "log.h"
44
45void ospfe_sig_handler(int, short, void *);
46__dead__attribute__((__noreturn__)) void ospfe_shutdown(void);
47void orig_rtr_lsa_all(struct area *);
48struct iface *find_vlink(struct abr_rtr *);
49
50struct ospfd_conf *oeconf = NULL((void*)0), *noeconf;
51static struct imsgev *iev_main;
52static struct imsgev *iev_rde;
53int oe_nofib;
54
55/* ARGSUSED */
56void
57ospfe_sig_handler(int sig, short event, void *bula)
58{
59 switch (sig) {
60 case SIGINT2:
61 case SIGTERM15:
62 ospfe_shutdown();
63 /* NOTREACHED */
64 default:
65 fatalx("unexpected signal");
66 }
67}
68
69/* ospf engine */
70pid_t
71ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
72 int pipe_parent2rde[2])
73{
74 struct area *area;
75 struct iface *iface;
76 struct passwd *pw;
77 struct event ev_sigint, ev_sigterm;
78 pid_t pid;
79
80 switch (pid = fork()) {
81 case -1:
82 fatal("cannot fork");
83 case 0:
84 break;
85 default:
86 return (pid);
87 }
88
89 /* create the raw ip socket */
90 if ((xconf->ospf_socket = socket(AF_INET624,
91 SOCK_RAW3 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, IPPROTO_OSPF89)) == -1)
92 fatal("error creating raw socket");
93
94 /* set some defaults */
95 if (if_set_mcast_loop(xconf->ospf_socket) == -1)
96 fatal("if_set_mcast_loop");
97 if (if_set_ipv6_checksum(xconf->ospf_socket) == -1)
98 fatal("if_set_ipv6_checksum");
99 if (if_set_ipv6_pktinfo(xconf->ospf_socket, 1) == -1)
100 fatal("if_set_ipv6_pktinfo");
101 if_set_sockbuf(xconf->ospf_socket);
102
103 oeconf = xconf;
104 if (oeconf->flags & OSPFD_FLAG_NO_FIB_UPDATE0x0001)
105 oe_nofib = 1;
106
107 if ((pw = getpwnam(OSPF6D_USER"_ospf6d")) == NULL((void*)0))
108 fatal("getpwnam");
109
110 if (chroot(pw->pw_dir) == -1)
111 fatal("chroot");
112 if (chdir("/") == -1)
113 fatal("chdir(\"/\")");
114
115 setproctitle("ospf engine");
116 /*
117 * XXX needed with fork+exec
118 * log_init(debug, LOG_DAEMON);
119 * log_setverbose(verbose);
120 */
121
122 ospfd_process = PROC_OSPF_ENGINE;
123 log_procinit(log_procnames[ospfd_process]);
124
125 if (setgroups(1, &pw->pw_gid) ||
126 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
127 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
128 fatal("can't drop privileges");
129
130 if (pledge("stdio inet mcast recvfd", NULL((void*)0)) == -1)
131 fatal("pledge");
132
133 event_init();
134 nbr_init(NBR_HASHSIZE128);
135 lsa_cache_init(LSA_HASHSIZE512);
136
137 /* setup signal handler */
138 signal_set(&ev_sigint, SIGINT, ospfe_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, ospfe_sig_handler, ((
void*)0))
;
139 signal_set(&ev_sigterm, SIGTERM, ospfe_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, ospfe_sig_handler, (
(void*)0))
;
140 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0));
141 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0));
142 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
143 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
144
145 /* setup pipes */
146 close(pipe_parent2ospfe[0]);
147 close(pipe_ospfe2rde[1]);
148 close(pipe_parent2rde[0]);
149 close(pipe_parent2rde[1]);
150
151 if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL((void*)0) ||
152 (iev_main = malloc(sizeof(struct imsgev))) == NULL((void*)0))
153 fatal(NULL((void*)0));
154 imsg_init(&iev_rde->ibuf, pipe_ospfe2rde[0]);
155 iev_rde->handler = ospfe_dispatch_rde;
156 imsg_init(&iev_main->ibuf, pipe_parent2ospfe[1]);
157 iev_main->handler = ospfe_dispatch_main;
158
159 /* setup event handler */
160 iev_rde->events = EV_READ0x02;
161 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
162 iev_rde->handler, iev_rde);
163 event_add(&iev_rde->ev, NULL((void*)0));
164
165 iev_main->events = EV_READ0x02;
166 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
167 iev_main->handler, iev_main);
168 event_add(&iev_main->ev, NULL((void*)0));
169
170 event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ0x02|EV_PERSIST0x10,
171 recv_packet, oeconf);
172 event_add(&oeconf->ev, NULL((void*)0));
173
174 /* remove unneeded config stuff */
175 conf_clear_redist_list(&oeconf->redist_list);
176
177 /* start interfaces */
178 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
{
179 ospfe_demote_area(area, 0);
180 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
181 if_start(xconf, iface);
182 }
183
184 event_dispatch();
185
186 ospfe_shutdown();
187 /* NOTREACHED */
188 return (0);
189}
190
191__dead__attribute__((__noreturn__)) void
192ospfe_shutdown(void)
193{
194 struct area *area;
195 struct iface *iface;
196
197 /* close pipes */
198 msgbuf_write(&iev_rde->ibuf.w);
199 msgbuf_clear(&iev_rde->ibuf.w);
200 close(iev_rde->ibuf.fd);
201 msgbuf_write(&iev_main->ibuf.w);
202 msgbuf_clear(&iev_main->ibuf.w);
203 close(iev_main->ibuf.fd);
204
205 /* stop all interfaces and remove all areas */
206 while ((area = LIST_FIRST(&oeconf->area_list)((&oeconf->area_list)->lh_first)) != NULL((void*)0)) {
207 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
208 if (if_fsm(iface, IF_EVT_DOWN)) {
209 log_debug("error stopping interface %s",
210 iface->name);
211 }
212 }
213 LIST_REMOVE(area, entry)do { if ((area)->entry.le_next != ((void*)0)) (area)->entry
.le_next->entry.le_prev = (area)->entry.le_prev; *(area
)->entry.le_prev = (area)->entry.le_next; ; ; } while (
0)
;
214 area_del(area);
215 }
216
217 close(oeconf->ospf_socket);
218
219 /* clean up */
220 free(iev_rde);
221 free(iev_main);
222 free(oeconf);
223
224 log_info("ospf engine exiting");
225 _exit(0);
226}
227
228/* imesg */
229int
230ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
231{
232 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
233}
234
235int
236ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
237 void *data, u_int16_t datalen)
238{
239 return (imsg_compose_event(iev_rde, type, peerid, pid, -1,
240 data, datalen));
241}
242
243/* ARGSUSED */
244void
245ospfe_dispatch_main(int fd, short event, void *bula)
246{
247 static struct area *narea;
248 struct area *area;
249 struct iface *iface, *ifp, *i;
250 struct ifaddrchange *ifc;
251 struct iface_addr *ia, *nia;
252 struct imsg imsg;
253 struct imsgev *iev = bula;
254 struct imsgbuf *ibuf = &iev->ibuf;
255 int n, stub_changed, shut = 0, isvalid, wasvalid;
256
257 if (event & EV_READ0x02) {
1
Assuming the condition is false
2
Taking false branch
258 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
259 fatal("imsg_read error");
260 if (n == 0) /* connection closed */
261 shut = 1;
262 }
263 if (event & EV_WRITE0x04) {
3
Assuming the condition is false
4
Taking false branch
264 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
265 fatal("msgbuf_write");
266 if (n == 0) /* connection closed */
267 shut = 1;
268 }
269
270 for (;;) {
5
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
271 if ((n = imsg_get(ibuf, &imsg)) == -1)
6
Assuming the condition is false
7
Taking false branch
17
Assuming the condition is false
18
Taking false branch
272 fatal("ospfe_dispatch_main: imsg_get error");
273 if (n == 0)
8
Assuming 'n' is not equal to 0
9
Taking false branch
19
Assuming 'n' is not equal to 0
20
Taking false branch
274 break;
275
276 switch (imsg.hdr.type) {
10
Control jumps to 'case IMSG_RECONF_END:' at line 389
21
Control jumps to 'case IMSG_RECONF_END:' at line 389
277 case IMSG_IFINFO:
278 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
279 sizeof(struct iface))
280 fatalx("IFINFO imsg with wrong len");
281 ifp = imsg.data;
282
283 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
{
284 LIST_FOREACH(i, &area->iface_list, entry)for((i) = ((&area->iface_list)->lh_first); (i)!= ((
void*)0); (i) = ((i)->entry.le_next))
{
285 if (strcmp(i->dependon,
286 ifp->name) == 0) {
287 log_warnx("interface %s"
288 " changed state, %s"
289 " depends on it",
290 ifp->name, i->name);
291 i->depend_ok =
292 ifstate_is_up(ifp);
293 if (ifstate_is_up(i))
294 orig_rtr_lsa(i->area);
295 }
296 }
297 }
298
299 if (!(ifp->cflags & F_IFACE_CONFIGURED0x02))
300 break;
301 iface = if_find(ifp->ifindex);
302 if (iface == NULL((void*)0))
303 fatalx("interface lost in ospfe");
304
305 wasvalid = (iface->flags & IFF_UP0x1) &&
306 LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0);
307
308 if_update(iface, ifp->mtu, ifp->flags, ifp->if_type,
309 ifp->linkstate, ifp->baudrate, ifp->rdomain);
310
311 isvalid = (iface->flags & IFF_UP0x1) &&
312 LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0);
313
314 if (wasvalid == isvalid)
315 break;
316
317 if (isvalid) {
318 if_fsm(iface, IF_EVT_UP);
319 log_warnx("interface %s up", iface->name);
320 } else {
321 if_fsm(iface, IF_EVT_DOWN);
322 log_warnx("interface %s down", iface->name);
323 }
324 break;
325 case IMSG_IFADDRNEW:
326 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
327 sizeof(struct ifaddrchange))
328 fatalx("IFADDRNEW imsg with wrong len");
329 ifc = imsg.data;
330
331 iface = if_find(ifc->ifindex);
332 if (iface == NULL((void*)0))
333 fatalx("IFADDRNEW interface lost in ospfe");
334
335 if ((ia = calloc(1, sizeof(struct iface_addr))) ==
336 NULL((void*)0))
337 fatal("ospfe_dispatch_main IFADDRNEW");
338 ia->addr = ifc->addr;
339 ia->dstbrd = ifc->dstbrd;
340 ia->prefixlen = ifc->prefixlen;
341
342 TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry)do { (ia)->entry.tqe_next = ((void*)0); (ia)->entry.tqe_prev
= (&iface->ifa_list)->tqh_last; *(&iface->ifa_list
)->tqh_last = (ia); (&iface->ifa_list)->tqh_last
= &(ia)->entry.tqe_next; } while (0)
;
343 orig_link_lsa(iface);
344 break;
345 case IMSG_IFADDRDEL:
346 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
347 sizeof(struct ifaddrchange))
348 fatalx("IFADDRDEL imsg with wrong len");
349 ifc = imsg.data;
350
351 iface = if_find(ifc->ifindex);
352 if (iface == NULL((void*)0))
353 fatalx("IFADDRDEL interface lost in ospfe");
354
355 for (ia = TAILQ_FIRST(&iface->ifa_list)((&iface->ifa_list)->tqh_first); ia != NULL((void*)0);
356 ia = nia) {
357 nia = TAILQ_NEXT(ia, entry)((ia)->entry.tqe_next);
358
359 if (IN6_ARE_ADDR_EQUAL(&ia->addr,(memcmp(&(&ia->addr)->__u6_addr.__u6_addr8[0], &
(&ifc->addr)->__u6_addr.__u6_addr8[0], sizeof(struct
in6_addr)) == 0)
360 &ifc->addr)(memcmp(&(&ia->addr)->__u6_addr.__u6_addr8[0], &
(&ifc->addr)->__u6_addr.__u6_addr8[0], sizeof(struct
in6_addr)) == 0)
) {
361 TAILQ_REMOVE(&iface->ifa_list, ia,do { if (((ia)->entry.tqe_next) != ((void*)0)) (ia)->entry
.tqe_next->entry.tqe_prev = (ia)->entry.tqe_prev; else (
&iface->ifa_list)->tqh_last = (ia)->entry.tqe_prev
; *(ia)->entry.tqe_prev = (ia)->entry.tqe_next; ; ; } while
(0)
362 entry)do { if (((ia)->entry.tqe_next) != ((void*)0)) (ia)->entry
.tqe_next->entry.tqe_prev = (ia)->entry.tqe_prev; else (
&iface->ifa_list)->tqh_last = (ia)->entry.tqe_prev
; *(ia)->entry.tqe_prev = (ia)->entry.tqe_next; ; ; } while
(0)
;
363 free(ia);
364 break;
365 }
366 }
367 orig_link_lsa(iface);
368 break;
369 case IMSG_RECONF_CONF:
370 if ((noeconf = malloc(sizeof(struct ospfd_conf))) ==
371 NULL((void*)0))
372 fatal(NULL((void*)0));
373 memcpy(noeconf, imsg.data, sizeof(struct ospfd_conf));
374
375 LIST_INIT(&noeconf->area_list)do { ((&noeconf->area_list)->lh_first) = ((void*)0)
; } while (0)
;
376 LIST_INIT(&noeconf->cand_list)do { ((&noeconf->cand_list)->lh_first) = ((void*)0)
; } while (0)
;
377 break;
378 case IMSG_RECONF_AREA:
379 if ((narea = area_new()) == NULL((void*)0))
380 fatal(NULL((void*)0));
381 memcpy(narea, imsg.data, sizeof(struct area));
382
383 LIST_INIT(&narea->iface_list)do { ((&narea->iface_list)->lh_first) = ((void*)0);
} while (0)
;
384 LIST_INIT(&narea->nbr_list)do { ((&narea->nbr_list)->lh_first) = ((void*)0); }
while (0)
;
385 RB_INIT(&narea->lsa_tree)do { (&narea->lsa_tree)->rbh_root = ((void*)0); } while
(0)
;
386
387 LIST_INSERT_HEAD(&noeconf->area_list, narea, entry)do { if (((narea)->entry.le_next = (&noeconf->area_list
)->lh_first) != ((void*)0)) (&noeconf->area_list)->
lh_first->entry.le_prev = &(narea)->entry.le_next; (
&noeconf->area_list)->lh_first = (narea); (narea)->
entry.le_prev = &(&noeconf->area_list)->lh_first
; } while (0)
;
388 break;
389 case IMSG_RECONF_END:
390 if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002) !=
11
Assuming the condition is false
12
Taking false branch
391 (noeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002))
22
Access to field 'flags' results in a dereference of a null pointer (loaded from variable 'noeconf')
392 stub_changed = 1;
393 else
394 stub_changed = 0;
395 merge_config(oeconf, noeconf);
396 noeconf = NULL((void*)0);
13
Null pointer value stored to 'noeconf'
397 if (stub_changed
13.1
'stub_changed' is 0
)
14
Taking false branch
398 orig_rtr_lsa_all(NULL((void*)0));
399 break;
15
Execution continues on line 419
400 case IMSG_CTL_KROUTE:
401 case IMSG_CTL_KROUTE_ADDR:
402 case IMSG_CTL_END:
403 control_imsg_relay(&imsg);
404 break;
405 case IMSG_CONTROLFD:
406 if ((fd = imsg.fd) == -1)
407 fatalx("%s: expected to receive imsg control"
408 "fd but didn't receive any", __func__);
409 /* Listen on control socket. */
410 control_listen(fd);
411 if (pledge("stdio inet mcast", NULL((void*)0)) == -1)
412 fatal("pledge");
413 break;
414 default:
415 log_debug("ospfe_dispatch_main: error handling imsg %d",
416 imsg.hdr.type);
417 break;
418 }
419 imsg_free(&imsg);
420 }
421 if (!shut)
422 imsg_event_add(iev);
423 else {
424 /* this pipe is dead, so remove the event handler */
425 event_del(&iev->ev);
426 event_loopexit(NULL((void*)0));
427 }
428}
429
430/* ARGSUSED */
431void
432ospfe_dispatch_rde(int fd, short event, void *bula)
433{
434 struct lsa_hdr lsa_hdr;
435 struct lsa_link lsa_link;
436 struct imsgev *iev = bula;
437 struct imsgbuf *ibuf = &iev->ibuf;
438 struct nbr *nbr;
439 struct lsa_hdr *lhp;
440 struct lsa_ref *ref;
441 struct area *area;
442 struct iface *iface;
443 struct lsa_entry *le;
444 struct imsg imsg;
445 struct abr_rtr ar;
446 int n, noack = 0, shut = 0;
447 u_int16_t l, age;
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("ospfe_dispatch_rde: imsg_get error");
465 if (n == 0)
466 break;
467
468 switch (imsg.hdr.type) {
469 case IMSG_DD:
470 nbr = nbr_find_peerid(imsg.hdr.peerid);
471 if (nbr == NULL((void*)0))
472 break;
473
474 /* put these on my ls_req_list for retrieval */
475 lhp = lsa_hdr_new();
476 memcpy(lhp, imsg.data, sizeof(*lhp));
477 ls_req_list_add(nbr, lhp);
478 break;
479 case IMSG_DD_END:
480 nbr = nbr_find_peerid(imsg.hdr.peerid);
481 if (nbr == NULL((void*)0))
482 break;
483
484 nbr->dd_pending--;
485 if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD0x0080) {
486 if (ls_req_list_empty(nbr))
487 nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
488 else
489 start_ls_req_tx_timer(nbr);
490 }
491 break;
492 case IMSG_DB_SNAPSHOT:
493 nbr = nbr_find_peerid(imsg.hdr.peerid);
494 if (nbr == NULL((void*)0))
495 break;
496 if (nbr->state != NBR_STA_SNAP0x0020) /* discard */
497 break;
498
499 /* add LSA header to the neighbor db_sum_list */
500 lhp = lsa_hdr_new();
501 memcpy(lhp, imsg.data, sizeof(*lhp));
502 db_sum_list_add(nbr, lhp);
503 break;
504 case IMSG_DB_END:
505 nbr = nbr_find_peerid(imsg.hdr.peerid);
506 if (nbr == NULL((void*)0))
507 break;
508
509 nbr->dd_snapshot = 0;
510 if (nbr->state != NBR_STA_SNAP0x0020)
511 break;
512
513 /* snapshot done, start tx of dd packets */
514 nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
515 break;
516 case IMSG_LS_FLOOD:
517 nbr = nbr_find_peerid(imsg.hdr.peerid);
518 if (nbr == NULL((void*)0))
519 break;
520
521 l = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
522 if (l < sizeof(lsa_hdr))
523 fatalx("ospfe_dispatch_rde: "
524 "bad imsg size");
525 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
526
527 ref = lsa_cache_add(imsg.data, l);
528
529 if (lsa_hdr.type == htons(LSA_TYPE_EXTERNAL)(__uint16_t)(__builtin_constant_p(0x4005) ? (__uint16_t)(((__uint16_t
)(0x4005) & 0xffU) << 8 | ((__uint16_t)(0x4005) &
0xff00U) >> 8) : __swap16md(0x4005))
) {
530 /*
531 * flood on all areas but stub areas and
532 * virtual links
533 */
534 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
{
535 if (area->stub)
536 continue;
537 LIST_FOREACH(iface, &area->iface_list,for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
538 entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
539 noack += lsa_flood(iface, nbr,
540 &lsa_hdr, imsg.data);
541 }
542 }
543 } else if (lsa_hdr.type == htons(LSA_TYPE_LINK)(__uint16_t)(__builtin_constant_p(0x0008) ? (__uint16_t)(((__uint16_t
)(0x0008) & 0xffU) << 8 | ((__uint16_t)(0x0008) &
0xff00U) >> 8) : __swap16md(0x0008))
) {
544 /*
545 * Save link-LSA options of neighbor.
546 * This is needed to originate network-LSA.
547 */
548 if (l - sizeof(lsa_hdr) < sizeof(lsa_link))
549 fatalx("ospfe_dispatch_rde: "
550 "bad imsg link size");
551 memcpy(&lsa_link, (char *)imsg.data +
552 sizeof(lsa_hdr), sizeof(lsa_link));
553 nbr->link_options = lsa_link.opts &
554 htonl(LSA_24_MASK)(__uint32_t)(__builtin_constant_p(0xffffff) ? (__uint32_t)(((
__uint32_t)(0xffffff) & 0xff) << 24 | ((__uint32_t)
(0xffffff) & 0xff00) << 8 | ((__uint32_t)(0xffffff)
& 0xff0000) >> 8 | ((__uint32_t)(0xffffff) & 0xff000000
) >> 24) : __swap32md(0xffffff))
;
555
556 /*
557 * flood on interface only
558 */
559 noack += lsa_flood(nbr->iface, nbr,
560 &lsa_hdr, imsg.data);
561 } else {
562 /*
563 * flood on all area interfaces on
564 * area 0.0.0.0 include also virtual links.
565 */
566 LIST_FOREACH(iface,for((iface) = ((&nbr->iface->area->iface_list)->
lh_first); (iface)!= ((void*)0); (iface) = ((iface)->entry
.le_next))
567 &nbr->iface->area->iface_list, entry)for((iface) = ((&nbr->iface->area->iface_list)->
lh_first); (iface)!= ((void*)0); (iface) = ((iface)->entry
.le_next))
{
568 noack += lsa_flood(iface, nbr,
569 &lsa_hdr, imsg.data);
570 }
571 /* XXX virtual links */
572 }
573
574 /* remove from ls_req_list */
575 le = ls_req_list_get(nbr, &lsa_hdr);
576 if (!(nbr->state & NBR_STA_FULL0x0100) && le != NULL((void*)0)) {
577 ls_req_list_free(nbr, le);
578 /*
579 * XXX no need to ack requested lsa
580 * the problem is that the RFC is very
581 * unclear about this.
582 */
583 noack = 1;
584 }
585
586 if (!noack && nbr->iface != NULL((void*)0) &&
587 nbr->iface->self != nbr) {
588 if (!(nbr->iface->state & IF_STA_BACKUP0x20) ||
589 nbr->iface->dr == nbr) {
590 /* delayed ack */
591 lhp = lsa_hdr_new();
592 memcpy(lhp, &lsa_hdr, sizeof(*lhp));
593 ls_ack_list_add(nbr->iface, lhp);
594 }
595 }
596
597 lsa_cache_put(ref, nbr);
598 break;
599 case IMSG_LS_UPD:
600 case IMSG_LS_SNAP:
601 /*
602 * IMSG_LS_UPD is used in two cases:
603 * 1. as response to ls requests
604 * 2. as response to ls updates where the DB
605 * is newer then the sent LSA
606 * IMSG_LS_SNAP is used in one case:
607 * in EXSTART when the LSA has age MaxAge
608 */
609 l = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr);
610 if (l < sizeof(lsa_hdr))
611 fatalx("ospfe_dispatch_rde: "
612 "bad imsg size");
613
614 nbr = nbr_find_peerid(imsg.hdr.peerid);
615 if (nbr == NULL((void*)0))
616 break;
617
618 if (nbr->iface->self == nbr)
619 break;
620
621 if (imsg.hdr.type == IMSG_LS_SNAP &&
622 nbr->state != NBR_STA_SNAP0x0020)
623 break;
624
625 memcpy(&age, imsg.data, sizeof(age));
626 ref = lsa_cache_add(imsg.data, l);
627 if (ntohs(age)(__uint16_t)(__builtin_constant_p(age) ? (__uint16_t)(((__uint16_t
)(age) & 0xffU) << 8 | ((__uint16_t)(age) & 0xff00U
) >> 8) : __swap16md(age))
>= MAX_AGE3600)
628 /* add to retransmit list */
629 ls_retrans_list_add(nbr, imsg.data, 0, 0);
630 else
631 ls_retrans_list_add(nbr, imsg.data, 0, 1);
632
633 lsa_cache_put(ref, nbr);
634 break;
635 case IMSG_LS_ACK:
636 /*
637 * IMSG_LS_ACK is used in two cases:
638 * 1. LSA was a duplicate
639 * 2. LS age is MaxAge and there is no current
640 * instance in the DB plus no neighbor in state
641 * Exchange or Loading
642 */
643 nbr = nbr_find_peerid(imsg.hdr.peerid);
644 if (nbr == NULL((void*)0))
645 break;
646
647 if (nbr->iface->self == nbr)
648 break;
649
650 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(lsa_hdr))
651 fatalx("ospfe_dispatch_rde: bad imsg size");
652 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
653
654 /* for case one check for implied acks */
655 if (nbr->iface->state & IF_STA_DROTHER0x10)
656 if (ls_retrans_list_del(nbr->iface->self,
657 &lsa_hdr) == 0)
658 break;
659 if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
660 break;
661
662 /* send a direct acknowledgement */
663 send_direct_ack(nbr->iface, nbr->addr, imsg.data,
664 imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr));
665
666 break;
667 case IMSG_LS_BADREQ:
668 nbr = nbr_find_peerid(imsg.hdr.peerid);
669 if (nbr == NULL((void*)0))
670 break;
671
672 if (nbr->iface->self == nbr)
673 fatalx("ospfe_dispatch_rde: "
674 "dummy neighbor got BADREQ");
675
676 nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
677 break;
678 case IMSG_ABR_UP:
679 memcpy(&ar, imsg.data, sizeof(ar));
680
681 if ((iface = find_vlink(&ar)) != NULL((void*)0) &&
682 iface->state == IF_STA_DOWN0x01)
683 if (if_fsm(iface, IF_EVT_UP)) {
684 log_debug("error starting interface %s",
685 iface->name);
686 }
687 break;
688 case IMSG_ABR_DOWN:
689 memcpy(&ar, imsg.data, sizeof(ar));
690
691 if ((iface = find_vlink(&ar)) != NULL((void*)0) &&
692 iface->state == IF_STA_POINTTOPOINT0x08)
693 if (if_fsm(iface, IF_EVT_DOWN)) {
694 log_debug("error stopping interface %s",
695 iface->name);
696 }
697 break;
698 case IMSG_CTL_AREA:
699 case IMSG_CTL_IFACE:
700 case IMSG_CTL_END:
701 case IMSG_CTL_SHOW_DATABASE:
702 case IMSG_CTL_SHOW_DB_EXT:
703 case IMSG_CTL_SHOW_DB_LINK:
704 case IMSG_CTL_SHOW_DB_NET:
705 case IMSG_CTL_SHOW_DB_RTR:
706 case IMSG_CTL_SHOW_DB_INTRA:
707 case IMSG_CTL_SHOW_DB_SELF:
708 case IMSG_CTL_SHOW_DB_SUM:
709 case IMSG_CTL_SHOW_DB_ASBR:
710 case IMSG_CTL_SHOW_RIB:
711 case IMSG_CTL_SHOW_SUM:
712 case IMSG_CTL_SHOW_SUM_AREA:
713 control_imsg_relay(&imsg);
714 break;
715 default:
716 log_debug("ospfe_dispatch_rde: error handling imsg %d",
717 imsg.hdr.type);
718 break;
719 }
720 imsg_free(&imsg);
721 }
722 if (!shut)
723 imsg_event_add(iev);
724 else {
725 /* this pipe is dead, so remove the event handler */
726 event_del(&iev->ev);
727 event_loopexit(NULL((void*)0));
728 }
729}
730
731struct iface *
732find_vlink(struct abr_rtr *ar)
733{
734 struct area *area;
735 struct iface *iface = NULL((void*)0);
736
737 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
738 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
739 if (iface->abr_id.s_addr == ar->abr_id.s_addr &&
740 iface->type == IF_TYPE_VIRTUALLINK &&
741 iface->area->id.s_addr == ar->area.s_addr) {
742 iface->dst = ar->dst_ip;
743 iface->addr = ar->addr;
744 iface->metric = ar->metric;
745
746 return (iface);
747 }
748
749 return (iface);
750}
751
752void
753orig_rtr_lsa_all(struct area *area)
754{
755 struct area *a;
756
757 /*
758 * update all router LSA in all areas except area itself,
759 * as this update is already running.
760 */
761 LIST_FOREACH(a, &oeconf->area_list, entry)for((a) = ((&oeconf->area_list)->lh_first); (a)!= (
(void*)0); (a) = ((a)->entry.le_next))
762 if (a != area)
763 orig_rtr_lsa(a);
764}
765
766void
767orig_rtr_lsa(struct area *area)
768{
769 struct lsa_hdr lsa_hdr;
770 struct lsa_rtr lsa_rtr;
771 struct lsa_rtr_link rtr_link;
772 struct iface *iface;
773 struct ibuf *buf;
774 struct nbr *nbr, *self = NULL((void*)0);
775 u_int32_t flags;
776 u_int16_t chksum;
777 u_int8_t border, virtual = 0;
778
779 log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id));
780
781 /* XXX IBUF_READ_SIZE */
782 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE65535)) == NULL((void*)0))
783 fatal("orig_rtr_lsa");
784
785 /* reserve space for LSA header and LSA Router header */
786 if (ibuf_reserve(buf, sizeof(lsa_hdr)) == NULL((void*)0))
787 fatal("orig_rtr_lsa: ibuf_reserve failed");
788
789 if (ibuf_reserve(buf, sizeof(lsa_rtr)) == NULL((void*)0))
790 fatal("orig_rtr_lsa: ibuf_reserve failed");
791
792 /* links */
793 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
{
794 if (self == NULL((void*)0) && iface->self != NULL((void*)0))
795 self = iface->self;
796
797 bzero(&rtr_link, sizeof(rtr_link));
798
799 switch (iface->type) {
800 case IF_TYPE_POINTOPOINT:
801 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
802 if (nbr != iface->self &&
803 nbr->state & NBR_STA_FULL0x0100)
804 break;
805 if (nbr && iface->state & IF_STA_POINTTOPOINT0x08) {
806 log_debug("orig_rtr_lsa: point-to-point, "
807 "interface %s", iface->name);
808 rtr_link.type = LINK_TYPE_POINTTOPOINT1;
809 if (iface->dependon[0] != '\0' &&
810 iface->depend_ok == 0)
811 rtr_link.metric = MAX_METRIC65535;
812 else
813 rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t
)(((__uint16_t)(iface->metric) & 0xffU) << 8 | (
(__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md
(iface->metric))
;
814 rtr_link.iface_id = htonl(iface->ifindex)(__uint32_t)(__builtin_constant_p(iface->ifindex) ? (__uint32_t
)(((__uint32_t)(iface->ifindex) & 0xff) << 24 | (
(__uint32_t)(iface->ifindex) & 0xff00) << 8 | ((
__uint32_t)(iface->ifindex) & 0xff0000) >> 8 | (
(__uint32_t)(iface->ifindex) & 0xff000000) >> 24
) : __swap32md(iface->ifindex))
;
815 rtr_link.nbr_iface_id = htonl(nbr->iface_id)(__uint32_t)(__builtin_constant_p(nbr->iface_id) ? (__uint32_t
)(((__uint32_t)(nbr->iface_id) & 0xff) << 24 | (
(__uint32_t)(nbr->iface_id) & 0xff00) << 8 | ((__uint32_t
)(nbr->iface_id) & 0xff0000) >> 8 | ((__uint32_t
)(nbr->iface_id) & 0xff000000) >> 24) : __swap32md
(nbr->iface_id))
;
816 rtr_link.nbr_rtr_id = nbr->id.s_addr;
817 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
818 fatalx("orig_rtr_lsa: ibuf_add failed");
819 }
820 continue;
821 case IF_TYPE_BROADCAST:
822 case IF_TYPE_NBMA:
823 if ((iface->state & IF_STA_MULTI(0x10 | 0x20 | 0x40))) {
824 if (iface->dr == iface->self) {
825 LIST_FOREACH(nbr, &iface->nbr_list,for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
826 entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
827 if (nbr != iface->self &&
828 nbr->state & NBR_STA_FULL0x0100)
829 break;
830 } else
831 nbr = iface->dr;
832
833 if (nbr && nbr->state & NBR_STA_FULL0x0100) {
834 log_debug("orig_rtr_lsa: transit net, "
835 "interface %s", iface->name);
836
837 rtr_link.type = LINK_TYPE_TRANSIT_NET2;
838 if (iface->dependon[0] != '\0' &&
839 iface->depend_ok == 0)
840 rtr_link.metric = MAX_METRIC65535;
841 else
842 rtr_link.metric =
843 htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t
)(((__uint16_t)(iface->metric) & 0xffU) << 8 | (
(__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md
(iface->metric))
;
844 rtr_link.iface_id = htonl(iface->ifindex)(__uint32_t)(__builtin_constant_p(iface->ifindex) ? (__uint32_t
)(((__uint32_t)(iface->ifindex) & 0xff) << 24 | (
(__uint32_t)(iface->ifindex) & 0xff00) << 8 | ((
__uint32_t)(iface->ifindex) & 0xff0000) >> 8 | (
(__uint32_t)(iface->ifindex) & 0xff000000) >> 24
) : __swap32md(iface->ifindex))
;
845 rtr_link.nbr_iface_id = htonl(iface->dr->iface_id)(__uint32_t)(__builtin_constant_p(iface->dr->iface_id) ?
(__uint32_t)(((__uint32_t)(iface->dr->iface_id) & 0xff
) << 24 | ((__uint32_t)(iface->dr->iface_id) &
0xff00) << 8 | ((__uint32_t)(iface->dr->iface_id
) & 0xff0000) >> 8 | ((__uint32_t)(iface->dr->
iface_id) & 0xff000000) >> 24) : __swap32md(iface->
dr->iface_id))
;
846 rtr_link.nbr_rtr_id = iface->dr->id.s_addr;
847 if (ibuf_add(buf, &rtr_link,
848 sizeof(rtr_link)))
849 fatalx("orig_rtr_lsa: "
850 "ibuf_add failed");
851 break;
852 }
853 }
854 break;
855#if 0 /* TODO virtualllink/pointtomulti */
856 case IF_TYPE_VIRTUALLINK:
857 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
858 if (nbr != iface->self &&
859 nbr->state & NBR_STA_FULL0x0100)
860 break;
861 }
862 if (nbr) {
863 rtr_link.id = nbr->id.s_addr;
864//XXX rtr_link.data = iface->addr.s_addr;
865 rtr_link.type = LINK_TYPE_VIRTUAL4;
866 /* RFC 3137: stub router support */
867 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002 ||
868 oe_nofib)
869 rtr_link.metric = 0xffff;
870 else
871 rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t
)(((__uint16_t)(iface->metric) & 0xffU) << 8 | (
(__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md
(iface->metric))
;
872 virtual = 1;
873 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
874 fatalx("orig_rtr_lsa: ibuf_add failed");
875
876 log_debug("orig_rtr_lsa: virtual link, "
877 "interface %s", iface->name);
878 }
879 continue;
880 case IF_TYPE_POINTOMULTIPOINT:
881 log_debug("orig_rtr_lsa: stub net, "
882 "interface %s", iface->name);
883//XXX rtr_link.id = iface->addr.s_addr;
884 rtr_link.data = 0xffffffff;
885 rtr_link.type = LINK_TYPE_STUB_NET;
886 rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t
)(((__uint16_t)(iface->metric) & 0xffU) << 8 | (
(__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md
(iface->metric))
;
887 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
888 fatalx("orig_rtr_lsa: ibuf_add failed");
889
890 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
891 if (nbr != iface->self &&
892 nbr->state & NBR_STA_FULL0x0100) {
893 bzero(&rtr_link, sizeof(rtr_link));
894 log_debug("orig_rtr_lsa: "
895 "point-to-multipoint, interface %s",
896 iface->name);
897//XXX rtr_link.id = nbr->addr.s_addr;
898//XXX rtr_link.data = iface->addr.s_addr;
899 rtr_link.type = LINK_TYPE_POINTTOPOINT1;
900 /* RFC 3137: stub router support */
901 if (oe_nofib || oeconf->flags &
902 OSPFD_FLAG_STUB_ROUTER0x0002)
903 rtr_link.metric = MAX_METRIC65535;
904 else if (iface->dependon[0] != '\0' &&
905 iface->dependon_ok == 0)
906 rtr_link.metric = MAX_METRIC65535;
907 else
908 rtr_link.metric =
909 htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t
)(((__uint16_t)(iface->metric) & 0xffU) << 8 | (
(__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md
(iface->metric))
;
910 if (ibuf_add(buf, &rtr_link,
911 sizeof(rtr_link)))
912 fatalx("orig_rtr_lsa: "
913 "ibuf_add failed");
914 }
915 }
916 continue;
917#endif /* TODO virtualllink/pointtomulti */
918 default:
919 fatalx("orig_rtr_lsa: unknown interface type");
920 }
921 }
922
923 /* LSA router header */
924 lsa_rtr.opts = 0;
925 flags = 0;
926
927 /*
928 * Set the E bit as soon as an as-ext lsa may be redistributed, only
929 * setting it in case we redistribute something is not worth the fuss.
930 */
931 if (oeconf->redistribute && !area->stub)
932 flags |= OSPF_RTR_E0x02;
933
934 border = (area_border_router(oeconf) != 0);
935 if (border != oeconf->border) {
936 oeconf->border = border;
937 orig_rtr_lsa_all(area);
938 }
939
940 if (oeconf->border)
941 flags |= OSPF_RTR_B0x01;
942 /* TODO set V flag if a active virtual link ends here and the
943 * area is the transit area for this link. */
944 if (virtual)
945 flags |= OSPF_RTR_V0x04;
946
947 LSA_24_SETLO(lsa_rtr.opts, area_ospf_options(area))((lsa_rtr.opts) = ((area_ospf_options(area)) & 0xffffff) |
((lsa_rtr.opts) & ~0xffffff))
;
948 LSA_24_SETHI(lsa_rtr.opts, flags)((lsa_rtr.opts) = ((lsa_rtr.opts) & 0xffffff) | (((flags)
& 0xff) << 24))
;
949 lsa_rtr.opts = htonl(lsa_rtr.opts)(__uint32_t)(__builtin_constant_p(lsa_rtr.opts) ? (__uint32_t
)(((__uint32_t)(lsa_rtr.opts) & 0xff) << 24 | ((__uint32_t
)(lsa_rtr.opts) & 0xff00) << 8 | ((__uint32_t)(lsa_rtr
.opts) & 0xff0000) >> 8 | ((__uint32_t)(lsa_rtr.opts
) & 0xff000000) >> 24) : __swap32md(lsa_rtr.opts))
;
950 memcpy(ibuf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)),
951 &lsa_rtr, sizeof(lsa_rtr));
952
953 /* LSA header */
954 lsa_hdr.age = htons(DEFAULT_AGE)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
955 lsa_hdr.type = htons(LSA_TYPE_ROUTER)(__uint16_t)(__builtin_constant_p(0x2001) ? (__uint16_t)(((__uint16_t
)(0x2001) & 0xffU) << 8 | ((__uint16_t)(0x2001) &
0xff00U) >> 8) : __swap16md(0x2001))
;
956 /* XXX needs to be fixed if multiple router-lsa need to be announced */
957 lsa_hdr.ls_id = 0;
958 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
959 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM)(__uint32_t)(__builtin_constant_p(0x80000001U) ? (__uint32_t)
(((__uint32_t)(0x80000001U) & 0xff) << 24 | ((__uint32_t
)(0x80000001U) & 0xff00) << 8 | ((__uint32_t)(0x80000001U
) & 0xff0000) >> 8 | ((__uint32_t)(0x80000001U) &
0xff000000) >> 24) : __swap32md(0x80000001U))
;
960 lsa_hdr.len = htons(buf->wpos)(__uint16_t)(__builtin_constant_p(buf->wpos) ? (__uint16_t
)(((__uint16_t)(buf->wpos) & 0xffU) << 8 | ((__uint16_t
)(buf->wpos) & 0xff00U) >> 8) : __swap16md(buf->
wpos))
;
961 lsa_hdr.ls_chksum = 0; /* updated later */
962 memcpy(ibuf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
963
964 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET))(__uint16_t)(__builtin_constant_p(iso_cksum(buf->buf, buf->
wpos, __builtin_offsetof(struct lsa_hdr, ls_chksum))) ? (__uint16_t
)(((__uint16_t)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof
(struct lsa_hdr, ls_chksum))) & 0xffU) << 8 | ((__uint16_t
)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))) & 0xff00U) >> 8) : __swap16md
(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))))
;
965 memcpy(ibuf_seek(buf, LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum), sizeof(chksum)),
966 &chksum, sizeof(chksum));
967
968 if (self)
969 imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0,
970 -1, buf->buf, buf->wpos);
971 else
972 log_warnx("orig_rtr_lsa: empty area %s",
973 inet_ntoa(area->id));
974
975 ibuf_free(buf);
976}
977
978void
979orig_net_lsa(struct iface *iface)
980{
981 struct lsa_hdr lsa_hdr;
982 struct nbr *nbr;
983 struct ibuf *buf;
984 struct lsa_net lsa_net;
985 int num_rtr = 0;
986 u_int16_t chksum;
987
988 /* XXX IBUF_READ_SIZE */
989 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE65535)) == NULL((void*)0))
990 fatal("orig_net_lsa");
991
992 /* reserve space for LSA header and options field */
993 if (ibuf_reserve(buf, sizeof(lsa_hdr) + sizeof(lsa_net)) == NULL((void*)0))
994 fatal("orig_net_lsa: ibuf_reserve failed");
995
996 lsa_net.opts = 0;
997 /* fully adjacent neighbors + self */
998 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
999 if (nbr->state & NBR_STA_FULL0x0100) {
1000 if (ibuf_add(buf, &nbr->id, sizeof(nbr->id)))
1001 fatal("orig_net_lsa: ibuf_add failed");
1002 lsa_net.opts |= nbr->link_options;
1003 num_rtr++;
1004 }
1005
1006 if (num_rtr == 1) {
1007 /* non transit net therefore no need to generate a net lsa */
1008 ibuf_free(buf);
1009 return;
1010 }
1011
1012 /* LSA header */
1013 if (iface->state & IF_STA_DR0x40)
1014 lsa_hdr.age = htons(DEFAULT_AGE)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
1015 else
1016 lsa_hdr.age = htons(MAX_AGE)(__uint16_t)(__builtin_constant_p(3600) ? (__uint16_t)(((__uint16_t
)(3600) & 0xffU) << 8 | ((__uint16_t)(3600) & 0xff00U
) >> 8) : __swap16md(3600))
;
1017
1018 lsa_hdr.type = htons(LSA_TYPE_NETWORK)(__uint16_t)(__builtin_constant_p(0x2002) ? (__uint16_t)(((__uint16_t
)(0x2002) & 0xffU) << 8 | ((__uint16_t)(0x2002) &
0xff00U) >> 8) : __swap16md(0x2002))
;
1019 /* for network LSAs, the link state ID equals the interface ID */
1020 lsa_hdr.ls_id = htonl(iface->ifindex)(__uint32_t)(__builtin_constant_p(iface->ifindex) ? (__uint32_t
)(((__uint32_t)(iface->ifindex) & 0xff) << 24 | (
(__uint32_t)(iface->ifindex) & 0xff00) << 8 | ((
__uint32_t)(iface->ifindex) & 0xff0000) >> 8 | (
(__uint32_t)(iface->ifindex) & 0xff000000) >> 24
) : __swap32md(iface->ifindex))
;
1021 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1022 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM)(__uint32_t)(__builtin_constant_p(0x80000001U) ? (__uint32_t)
(((__uint32_t)(0x80000001U) & 0xff) << 24 | ((__uint32_t
)(0x80000001U) & 0xff00) << 8 | ((__uint32_t)(0x80000001U
) & 0xff0000) >> 8 | ((__uint32_t)(0x80000001U) &
0xff000000) >> 24) : __swap32md(0x80000001U))
;
1023 lsa_hdr.len = htons(buf->wpos)(__uint16_t)(__builtin_constant_p(buf->wpos) ? (__uint16_t
)(((__uint16_t)(buf->wpos) & 0xffU) << 8 | ((__uint16_t
)(buf->wpos) & 0xff00U) >> 8) : __swap16md(buf->
wpos))
;
1024 lsa_hdr.ls_chksum = 0; /* updated later */
1025 memcpy(ibuf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
1026
1027 lsa_net.opts &= lsa_net.opts & htonl(LSA_24_MASK)(__uint32_t)(__builtin_constant_p(0xffffff) ? (__uint32_t)(((
__uint32_t)(0xffffff) & 0xff) << 24 | ((__uint32_t)
(0xffffff) & 0xff00) << 8 | ((__uint32_t)(0xffffff)
& 0xff0000) >> 8 | ((__uint32_t)(0xffffff) & 0xff000000
) >> 24) : __swap32md(0xffffff))
;
1028 memcpy(ibuf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_net)), &lsa_net,
1029 sizeof(lsa_net));
1030
1031 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET))(__uint16_t)(__builtin_constant_p(iso_cksum(buf->buf, buf->
wpos, __builtin_offsetof(struct lsa_hdr, ls_chksum))) ? (__uint16_t
)(((__uint16_t)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof
(struct lsa_hdr, ls_chksum))) & 0xffU) << 8 | ((__uint16_t
)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))) & 0xff00U) >> 8) : __swap16md
(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))))
;
1032 memcpy(ibuf_seek(buf, LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum), sizeof(chksum)),
1033 &chksum, sizeof(chksum));
1034
1035 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1036 -1, buf->buf, buf->wpos);
1037
1038 ibuf_free(buf);
1039}
1040
1041void
1042orig_link_lsa(struct iface *iface)
1043{
1044 struct lsa_hdr lsa_hdr;
1045 struct lsa_link lsa_link;
1046 struct lsa_prefix lsa_prefix;
1047 struct ibuf *buf;
1048 struct iface_addr *ia;
1049 struct in6_addr prefix;
1050 unsigned int num_prefix = 0;
1051 u_int16_t chksum;
1052 u_int32_t options;
1053
1054 log_debug("orig_link_lsa: interface %s", iface->name);
1055
1056 switch (iface->type) {
1057 case IF_TYPE_VIRTUALLINK: /* forbidden by rfc5340 */
1058 return;
1059 case IF_TYPE_BROADCAST:
1060 case IF_TYPE_NBMA:
1061 if ((iface->state & IF_STA_MULTI(0x10 | 0x20 | 0x40)) == 0)
1062 return;
1063 break;
1064 case IF_TYPE_POINTOPOINT:
1065 case IF_TYPE_POINTOMULTIPOINT:
1066 if ((iface->state & IF_STA_POINTTOPOINT0x08) == 0)
1067 return;
1068 break;
1069 default:
1070 fatalx("orig_link_lsa: unknown interface type");
1071 }
1072
1073 /* XXX IBUF_READ_SIZE */
1074 if ((buf = ibuf_dynamic(sizeof(lsa_hdr) + sizeof(lsa_link),
1075 IBUF_READ_SIZE65535)) == NULL((void*)0))
1076 fatal("orig_link_lsa");
1077
1078 /* reserve space for LSA header and LSA link header */
1079 if (ibuf_reserve(buf, sizeof(lsa_hdr) + sizeof(lsa_link)) == NULL((void*)0))
1080 fatal("orig_link_lsa: ibuf_reserve failed");
1081
1082 /* link-local address, and all prefixes configured on interface */
1083 TAILQ_FOREACH(ia, &iface->ifa_list, entry)for((ia) = ((&iface->ifa_list)->tqh_first); (ia) !=
((void*)0); (ia) = ((ia)->entry.tqe_next))
{
1084 if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)(((&ia->addr)->__u6_addr.__u6_addr8[0] == 0xfe) &&
(((&ia->addr)->__u6_addr.__u6_addr8[1] & 0xc0)
== 0x80))
) {
1085 log_debug("orig_link_lsa: link local address %s",
1086 log_in6addr(&ia->addr));
1087 lsa_link.lladdr = ia->addr;
1088 continue;
1089 }
1090
1091 lsa_prefix.prefixlen = ia->prefixlen;
1092 lsa_prefix.options = 0;
1093 lsa_prefix.metric = 0;
1094 inet6applymask(&prefix, &ia->addr, ia->prefixlen);
1095 log_debug("orig_link_lsa: prefix %s", log_in6addr(&prefix));
1096 if (ibuf_add(buf, &lsa_prefix, sizeof(lsa_prefix)))
1097 fatal("orig_link_lsa: ibuf_add failed");
1098 if (ibuf_add(buf, &prefix.s6_addr__u6_addr.__u6_addr8[0],
1099 LSA_PREFIXSIZE(ia->prefixlen)(((ia->prefixlen) + 31)/32 * 4)))
1100 fatal("orig_link_lsa: ibuf_add failed");
1101 num_prefix++;
1102 }
1103
1104 /* LSA link header (lladdr has already been filled in above) */
1105 LSA_24_SETHI(lsa_link.opts, iface->priority)((lsa_link.opts) = ((lsa_link.opts) & 0xffffff) | (((iface
->priority) & 0xff) << 24))
;
1106 options = area_ospf_options(iface->area);
1107 LSA_24_SETLO(lsa_link.opts, options)((lsa_link.opts) = ((options) & 0xffffff) | ((lsa_link.opts
) & ~0xffffff))
;
1108 lsa_link.opts = htonl(lsa_link.opts)(__uint32_t)(__builtin_constant_p(lsa_link.opts) ? (__uint32_t
)(((__uint32_t)(lsa_link.opts) & 0xff) << 24 | ((__uint32_t
)(lsa_link.opts) & 0xff00) << 8 | ((__uint32_t)(lsa_link
.opts) & 0xff0000) >> 8 | ((__uint32_t)(lsa_link.opts
) & 0xff000000) >> 24) : __swap32md(lsa_link.opts))
;
1109 lsa_link.numprefix = htonl(num_prefix)(__uint32_t)(__builtin_constant_p(num_prefix) ? (__uint32_t)(
((__uint32_t)(num_prefix) & 0xff) << 24 | ((__uint32_t
)(num_prefix) & 0xff00) << 8 | ((__uint32_t)(num_prefix
) & 0xff0000) >> 8 | ((__uint32_t)(num_prefix) &
0xff000000) >> 24) : __swap32md(num_prefix))
;
1110 memcpy(ibuf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_link)),
1111 &lsa_link, sizeof(lsa_link));
1112
1113 /* LSA header */
1114 lsa_hdr.age = htons(DEFAULT_AGE)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
1115 lsa_hdr.type = htons(LSA_TYPE_LINK)(__uint16_t)(__builtin_constant_p(0x0008) ? (__uint16_t)(((__uint16_t
)(0x0008) & 0xffU) << 8 | ((__uint16_t)(0x0008) &
0xff00U) >> 8) : __swap16md(0x0008))
;
1116 /* for link LSAs, the link state ID equals the interface ID */
1117 lsa_hdr.ls_id = htonl(iface->ifindex)(__uint32_t)(__builtin_constant_p(iface->ifindex) ? (__uint32_t
)(((__uint32_t)(iface->ifindex) & 0xff) << 24 | (
(__uint32_t)(iface->ifindex) & 0xff00) << 8 | ((
__uint32_t)(iface->ifindex) & 0xff0000) >> 8 | (
(__uint32_t)(iface->ifindex) & 0xff000000) >> 24
) : __swap32md(iface->ifindex))
;
1118 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1119 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM)(__uint32_t)(__builtin_constant_p(0x80000001U) ? (__uint32_t)
(((__uint32_t)(0x80000001U) & 0xff) << 24 | ((__uint32_t
)(0x80000001U) & 0xff00) << 8 | ((__uint32_t)(0x80000001U
) & 0xff0000) >> 8 | ((__uint32_t)(0x80000001U) &
0xff000000) >> 24) : __swap32md(0x80000001U))
;
1120 lsa_hdr.len = htons(buf->wpos)(__uint16_t)(__builtin_constant_p(buf->wpos) ? (__uint16_t
)(((__uint16_t)(buf->wpos) & 0xffU) << 8 | ((__uint16_t
)(buf->wpos) & 0xff00U) >> 8) : __swap16md(buf->
wpos))
;
1121 lsa_hdr.ls_chksum = 0; /* updated later */
1122 memcpy(ibuf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
1123
1124 chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET))(__uint16_t)(__builtin_constant_p(iso_cksum(buf->buf, buf->
wpos, __builtin_offsetof(struct lsa_hdr, ls_chksum))) ? (__uint16_t
)(((__uint16_t)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof
(struct lsa_hdr, ls_chksum))) & 0xffU) << 8 | ((__uint16_t
)(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))) & 0xff00U) >> 8) : __swap16md
(iso_cksum(buf->buf, buf->wpos, __builtin_offsetof(struct
lsa_hdr, ls_chksum))))
;
1125 memcpy(ibuf_seek(buf, LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum), sizeof(chksum)),
1126 &chksum, sizeof(chksum));
1127
1128 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1129 -1, buf->buf, buf->wpos);
1130
1131 ibuf_free(buf);
1132}
1133
1134u_int32_t
1135ospfe_router_id(void)
1136{
1137 return (oeconf->rtr_id.s_addr);
1138}
1139
1140void
1141ospfe_fib_update(int type)
1142{
1143 int old = oe_nofib;
1144
1145 if (type == IMSG_CTL_FIB_COUPLE)
1146 oe_nofib = 0;
1147 if (type == IMSG_CTL_FIB_DECOUPLE)
1148 oe_nofib = 1;
1149 if (old != oe_nofib)
1150 orig_rtr_lsa_all(NULL((void*)0));
1151}
1152
1153void
1154ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx)
1155{
1156 struct area *area;
1157 struct iface *iface;
1158 struct ctl_iface *ictl;
1159
1160 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
1161 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
1162 if (idx == 0 || idx == iface->ifindex) {
1163 ictl = if_to_ctl(iface);
1164 imsg_compose_event(&c->iev,
1165 IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1166 ictl, sizeof(struct ctl_iface));
1167 }
1168}
1169
1170void
1171ospfe_nbr_ctl(struct ctl_conn *c)
1172{
1173 struct area *area;
1174 struct iface *iface;
1175 struct nbr *nbr;
1176 struct ctl_nbr *nctl;
1177
1178 LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area
)!= ((void*)0); (area) = ((area)->entry.le_next))
1179 LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface
)!= ((void*)0); (iface) = ((iface)->entry.le_next))
1180 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
1181 if (iface->self != nbr) {
1182 nctl = nbr_to_ctl(nbr);
1183 imsg_compose_event(&c->iev,
1184 IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
1185 sizeof(struct ctl_nbr));
1186 }
1187 }
1188
1189 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL((void*)0), 0);
1190}
1191
1192void
1193ospfe_demote_area(struct area *area, int active)
1194{
1195 struct demote_msg dmsg;
1196
1197 if (ospfd_process != PROC_OSPF_ENGINE ||
1198 area->demote_group[0] == '\0')
1199 return;
1200
1201 bzero(&dmsg, sizeof(dmsg));
1202 strlcpy(dmsg.demote_group, area->demote_group,
1203 sizeof(dmsg.demote_group));
1204 dmsg.level = area->demote_level;
1205 if (active)
1206 dmsg.level = -dmsg.level;
1207
1208 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1209}
1210
1211void
1212ospfe_demote_iface(struct iface *iface, int active)
1213{
1214 struct demote_msg dmsg;
1215
1216 if (ospfd_process != PROC_OSPF_ENGINE ||
1217 iface->demote_group[0] == '\0')
1218 return;
1219
1220 bzero(&dmsg, sizeof(dmsg));
1221 strlcpy(dmsg.demote_group, iface->demote_group,
1222 sizeof(dmsg.demote_group));
1223 if (active)
1224 dmsg.level = -1;
1225 else
1226 dmsg.level = 1;
1227
1228 log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group,
1229 dmsg.level);
1230
1231 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1232}