Bug Summary

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