Bug Summary

File:src/usr.sbin/ospf6d/interface.c
Warning:line 516, column 26
Dereference of null pointer

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 interface.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/interface.c
1/* $OpenBSD: interface.c,v 1.29 2020/05/27 09:03:56 denis Exp $ */
2
3/*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004, 2005, 2007 Esben Norby <norby@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <sys/ioctl.h>
22#include <sys/time.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <net/if.h>
27#include <net/if_types.h>
28#include <ctype.h>
29#include <err.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <string.h>
34#include <event.h>
35
36#include "ospf6d.h"
37#include "ospf6.h"
38#include "log.h"
39#include "ospfe.h"
40
41void if_hello_timer(int, short, void *);
42void if_start_hello_timer(struct iface *);
43void if_stop_hello_timer(struct iface *);
44void if_stop_wait_timer(struct iface *);
45void if_wait_timer(int, short, void *);
46void if_start_wait_timer(struct iface *);
47void if_stop_wait_timer(struct iface *);
48struct nbr *if_elect(struct nbr *, struct nbr *);
49
50struct {
51 int state;
52 enum iface_event event;
53 enum iface_action action;
54 int new_state;
55} iface_fsm[] = {
56 /* current state event that happened action to take resulting state */
57 {IF_STA_DOWN0x01, IF_EVT_UP, IF_ACT_STRT, 0},
58 {IF_STA_WAITING0x04, IF_EVT_BACKUP_SEEN, IF_ACT_ELECT, 0},
59 {IF_STA_WAITING0x04, IF_EVT_WTIMER, IF_ACT_ELECT, 0},
60 {IF_STA_ANY0x7f, IF_EVT_WTIMER, IF_ACT_NOTHING, 0},
61 {IF_STA_WAITING0x04, IF_EVT_NBR_CHNG, IF_ACT_NOTHING, 0},
62 {IF_STA_MULTI(0x10 | 0x20 | 0x40), IF_EVT_NBR_CHNG, IF_ACT_ELECT, 0},
63 {IF_STA_ANY0x7f, IF_EVT_NBR_CHNG, IF_ACT_NOTHING, 0},
64 {IF_STA_ANY0x7f, IF_EVT_DOWN, IF_ACT_RST, IF_STA_DOWN0x01},
65 {IF_STA_ANY0x7f, IF_EVT_LOOP, IF_ACT_RST, IF_STA_LOOPBACK0x02},
66 {IF_STA_LOOPBACK0x02, IF_EVT_UNLOOP, IF_ACT_NOTHING, IF_STA_DOWN0x01},
67 {-1, IF_EVT_NOTHING, IF_ACT_NOTHING, 0},
68};
69
70#if 0
71/* TODO virtual links */
72static int vlink_cnt = 0;
73#endif
74
75TAILQ_HEAD(, iface)struct { struct iface *tqh_first; struct iface **tqh_last; } iflist;
76
77const char * const if_event_names[] = {
78 "NOTHING",
79 "UP",
80 "WAITTIMER",
81 "BACKUPSEEN",
82 "NEIGHBORCHANGE",
83 "LOOP",
84 "UNLOOP",
85 "DOWN"
86};
87
88const char * const if_action_names[] = {
89 "NOTHING",
90 "START",
91 "ELECT",
92 "RESET"
93};
94
95int
96if_fsm(struct iface *iface, enum iface_event event)
97{
98 int old_state;
99 int new_state = 0;
100 int i, ret = 0;
101
102 old_state = iface->state;
103
104 for (i = 0; iface_fsm[i].state != -1; i++)
2
Assuming the condition is true
3
Loop condition is true. Entering loop body
105 if ((iface_fsm[i].state & old_state) &&
4
Assuming the condition is true
6
Taking true branch
106 (iface_fsm[i].event == event)) {
5
Assuming 'event' is equal to field 'event'
107 new_state = iface_fsm[i].new_state;
108 break;
7
Execution continues on line 111
109 }
110
111 if (iface_fsm[i].state == -1) {
8
Taking false branch
112 /* event outside of the defined fsm, ignore it. */
113 log_debug("if_fsm: interface %s, "
114 "event %s not expected in state %s", iface->name,
115 if_event_names[event], if_state_name(old_state));
116 return (0);
117 }
118
119 switch (iface_fsm[i].action) {
9
Control jumps to 'case IF_ACT_ELECT:' at line 123
120 case IF_ACT_STRT:
121 ret = if_act_start(iface);
122 break;
123 case IF_ACT_ELECT:
124 ret = if_act_elect(iface);
10
Calling 'if_act_elect'
125 break;
126 case IF_ACT_RST:
127 ret = if_act_reset(iface);
128 break;
129 case IF_ACT_NOTHING:
130 /* do nothing */
131 break;
132 }
133
134 if (ret) {
135 log_debug("if_fsm: error changing state for interface %s, "
136 "event %s, state %s", iface->name, if_event_names[event],
137 if_state_name(old_state));
138 return (-1);
139 }
140
141 if (new_state != 0)
142 iface->state = new_state;
143
144 if (iface->state != old_state) {
145 area_track(iface->area);
146 orig_rtr_lsa(iface->area);
147 orig_link_lsa(iface);
148
149 /* state change inform RDE */
150 ospfe_imsg_compose_rde(IMSG_IFINFO, iface->self->peerid, 0,
151 &iface->state, sizeof(iface->state));
152 }
153
154 if (old_state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08) &&
155 (iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0)
156 ospfe_demote_iface(iface, 0);
157 if ((old_state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0 &&
158 iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08))
159 ospfe_demote_iface(iface, 1);
160
161 log_debug("if_fsm: event %s resulted in action %s and changing "
162 "state for interface %s from %s to %s",
163 if_event_names[event], if_action_names[iface_fsm[i].action],
164 iface->name, if_state_name(old_state), if_state_name(iface->state));
165
166 return (ret);
167}
168
169int
170if_init(void)
171{
172 TAILQ_INIT(&iflist)do { (&iflist)->tqh_first = ((void*)0); (&iflist)->
tqh_last = &(&iflist)->tqh_first; } while (0)
;
173
174 return (fetchifs(0));
175}
176
177/* XXX using a linked list should be OK for now */
178struct iface *
179if_find(unsigned int ifindex)
180{
181 struct iface *iface;
182
183 TAILQ_FOREACH(iface, &iflist, list)for((iface) = ((&iflist)->tqh_first); (iface) != ((void
*)0); (iface) = ((iface)->list.tqe_next))
{
184 if (ifindex == iface->ifindex)
185 return (iface);
186 }
187 return (NULL((void*)0));
188}
189
190struct iface *
191if_findname(char *name)
192{
193 struct iface *iface;
194
195 TAILQ_FOREACH(iface, &iflist, list)for((iface) = ((&iflist)->tqh_first); (iface) != ((void
*)0); (iface) = ((iface)->list.tqe_next))
{
196 if (!strcmp(name, iface->name))
197 return (iface);
198 }
199 return (NULL((void*)0));
200}
201
202struct iface *
203if_new(u_short ifindex, char *ifname)
204{
205 struct iface *iface;
206
207 if ((iface = calloc(1, sizeof(*iface))) == NULL((void*)0))
208 err(1, "if_new: calloc");
209
210 iface->state = IF_STA_DOWN0x01;
211
212 LIST_INIT(&iface->nbr_list)do { ((&iface->nbr_list)->lh_first) = ((void*)0); }
while (0)
;
213 TAILQ_INIT(&iface->ifa_list)do { (&iface->ifa_list)->tqh_first = ((void*)0); (&
iface->ifa_list)->tqh_last = &(&iface->ifa_list
)->tqh_first; } while (0)
;
214 TAILQ_INIT(&iface->ls_ack_list)do { (&iface->ls_ack_list)->tqh_first = ((void*)0);
(&iface->ls_ack_list)->tqh_last = &(&iface
->ls_ack_list)->tqh_first; } while (0)
;
215 RB_INIT(&iface->lsa_tree)do { (&iface->lsa_tree)->rbh_root = ((void*)0); } while
(0)
;
216
217#if 0
218 /* TODO */
219 if (virtual) {
220 iface->type = IF_TYPE_VIRTUALLINK;
221 snprintf(iface->name, sizeof(iface->name), "vlink%d",
222 vlink_cnt++);
223 iface->flags |= IFF_UP0x1;
224 iface->mtu = IP_MSS576;
225 return (iface);
226 }
227#endif
228 strlcpy(iface->name, ifname, sizeof(iface->name));
229 iface->ifindex = ifindex;
230
231 TAILQ_INSERT_TAIL(&iflist, iface, list)do { (iface)->list.tqe_next = ((void*)0); (iface)->list
.tqe_prev = (&iflist)->tqh_last; *(&iflist)->tqh_last
= (iface); (&iflist)->tqh_last = &(iface)->list
.tqe_next; } while (0)
;
232
233 return (iface);
234}
235
236void
237if_update(struct iface *iface, int mtu, int flags, u_int8_t type,
238 u_int8_t state, u_int64_t rate, u_int32_t rdomain)
239{
240 iface->mtu = mtu;
241 iface->flags = flags;
242 iface->if_type = type;
243 iface->linkstate = state;
244 iface->baudrate = rate;
245 iface->rdomain = rdomain;
246
247 /* set type */
248 if (flags & IFF_POINTOPOINT0x10)
249 iface->type = IF_TYPE_POINTOPOINT;
250 if (flags & IFF_BROADCAST0x2 && flags & IFF_MULTICAST0x8000)
251 iface->type = IF_TYPE_BROADCAST;
252 if (flags & IFF_LOOPBACK0x8) {
253 iface->type = IF_TYPE_POINTOPOINT;
254 iface->cflags |= F_IFACE_PASSIVE0x01;
255 }
256}
257
258void
259if_del(struct iface *iface)
260{
261 struct nbr *nbr = NULL((void*)0);
262
263 log_debug("if_del: interface %s", iface->name);
264
265 /* revert the demotion when the interface is deleted */
266 if ((iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0)
267 ospfe_demote_iface(iface, 1);
268
269 /* clear lists etc */
270 while ((nbr = LIST_FIRST(&iface->nbr_list)((&iface->nbr_list)->lh_first)) != NULL((void*)0))
271 nbr_del(nbr);
272
273 if (evtimer_pending(&iface->hello_timer, NULL)event_pending(&iface->hello_timer, 0x01, ((void*)0)))
274 evtimer_del(&iface->hello_timer)event_del(&iface->hello_timer);
275 if (evtimer_pending(&iface->wait_timer, NULL)event_pending(&iface->wait_timer, 0x01, ((void*)0)))
276 evtimer_del(&iface->wait_timer)event_del(&iface->wait_timer);
277 if (evtimer_pending(&iface->lsack_tx_timer, NULL)event_pending(&iface->lsack_tx_timer, 0x01, ((void*)0)
)
)
278 evtimer_del(&iface->lsack_tx_timer)event_del(&iface->lsack_tx_timer);
279
280 ls_ack_list_clr(iface);
281 TAILQ_REMOVE(&iflist, iface, list)do { if (((iface)->list.tqe_next) != ((void*)0)) (iface)->
list.tqe_next->list.tqe_prev = (iface)->list.tqe_prev; else
(&iflist)->tqh_last = (iface)->list.tqe_prev; *(iface
)->list.tqe_prev = (iface)->list.tqe_next; ; ; } while (
0)
;
282 free(iface);
283}
284
285void
286if_start(struct ospfd_conf *xconf, struct iface *iface)
287{
288 /* init the dummy local neighbor */
289 iface->self = nbr_new(ospfe_router_id(), iface, iface->ifindex, 1,
290 NULL((void*)0));
291
292 /* set event handlers for interface */
293 evtimer_set(&iface->lsack_tx_timer, ls_ack_tx_timer, iface)event_set(&iface->lsack_tx_timer, -1, 0, ls_ack_tx_timer
, iface)
;
294 evtimer_set(&iface->hello_timer, if_hello_timer, iface)event_set(&iface->hello_timer, -1, 0, if_hello_timer, iface
)
;
295 evtimer_set(&iface->wait_timer, if_wait_timer, iface)event_set(&iface->wait_timer, -1, 0, if_wait_timer, iface
)
;
296
297 iface->fd = xconf->ospf_socket;
298
299 ospfe_demote_iface(iface, 0);
300
301 if (if_fsm(iface, IF_EVT_UP))
302 log_debug("error starting interface %s", iface->name);
303}
304
305/* timers */
306/* ARGSUSED */
307void
308if_hello_timer(int fd, short event, void *arg)
309{
310 struct iface *iface = arg;
311 struct timeval tv;
312
313 send_hello(iface);
314
315 /* reschedule hello_timer */
316 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
317 tv.tv_sec = iface->hello_interval;
318 if (evtimer_add(&iface->hello_timer, &tv)event_add(&iface->hello_timer, &tv) == -1)
319 fatal("if_hello_timer");
320}
321
322void
323if_start_hello_timer(struct iface *iface)
324{
325 struct timeval tv;
326
327 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
328 if (evtimer_add(&iface->hello_timer, &tv)event_add(&iface->hello_timer, &tv) == -1)
329 fatal("if_start_hello_timer");
330}
331
332void
333if_stop_hello_timer(struct iface *iface)
334{
335 if (evtimer_del(&iface->hello_timer)event_del(&iface->hello_timer) == -1)
336 fatal("if_stop_hello_timer");
337}
338
339/* ARGSUSED */
340void
341if_wait_timer(int fd, short event, void *arg)
342{
343 struct iface *iface = arg;
344
345 if_fsm(iface, IF_EVT_WTIMER);
1
Calling 'if_fsm'
346}
347
348void
349if_start_wait_timer(struct iface *iface)
350{
351 struct timeval tv;
352
353 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
354 tv.tv_sec = iface->dead_interval;
355 if (evtimer_add(&iface->wait_timer, &tv)event_add(&iface->wait_timer, &tv) == -1)
356 fatal("if_start_wait_timer");
357}
358
359void
360if_stop_wait_timer(struct iface *iface)
361{
362 if (evtimer_del(&iface->wait_timer)event_del(&iface->wait_timer) == -1)
363 fatal("if_stop_wait_timer");
364}
365
366/* actions */
367int
368if_act_start(struct iface *iface)
369{
370 struct in6_addr addr;
371 struct timeval now;
372
373 if (!((iface->flags & IFF_UP0x1) &&
374 LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0))) {
375 log_debug("if_act_start: interface %s link down",
376 iface->name);
377 return (0);
378 }
379
380 if (iface->if_type == IFT_CARP0xf7 &&
381 !(iface->cflags & F_IFACE_PASSIVE0x01)) {
382 /* force passive mode on carp interfaces */
383 log_warnx("if_act_start: forcing interface %s to passive",
384 iface->name);
385 iface->cflags |= F_IFACE_PASSIVE0x01;
386 }
387
388 gettimeofday(&now, NULL((void*)0));
389 iface->uptime = now.tv_sec;
390
391 /* loopback interfaces have a special state */
392 if (iface->flags & IFF_LOOPBACK0x8)
393 iface->state = IF_STA_LOOPBACK0x02;
394
395 if (iface->cflags & F_IFACE_PASSIVE0x01) {
396 /* for an update of stub network entries */
397 orig_rtr_lsa(iface->area);
398 return (0);
399 }
400
401 switch (iface->type) {
402 case IF_TYPE_POINTOPOINT:
403 inet_pton(AF_INET624, AllSPFRouters"ff02::5", &addr);
404
405 if (if_join_group(iface, &addr))
406 return (-1);
407 iface->state = IF_STA_POINTTOPOINT0x08;
408 break;
409 case IF_TYPE_VIRTUALLINK:
410 iface->state = IF_STA_POINTTOPOINT0x08;
411 break;
412 case IF_TYPE_POINTOMULTIPOINT:
413 case IF_TYPE_NBMA:
414 log_debug("if_act_start: type %s not supported, interface %s",
415 if_type_name(iface->type), iface->name);
416 return (-1);
417 case IF_TYPE_BROADCAST:
418 inet_pton(AF_INET624, AllSPFRouters"ff02::5", &addr);
419
420 if (if_join_group(iface, &addr))
421 return (-1);
422 if (iface->priority == 0) {
423 iface->state = IF_STA_DROTHER0x10;
424 } else {
425 iface->state = IF_STA_WAITING0x04;
426 if_start_wait_timer(iface);
427 }
428 break;
429 default:
430 fatalx("if_act_start: unknown interface type");
431 }
432
433 /* hello timer needs to be started in any case */
434 if_start_hello_timer(iface);
435 return (0);
436}
437
438struct nbr *
439if_elect(struct nbr *a, struct nbr *b)
440{
441 if (a->priority > b->priority)
442 return (a);
443 if (a->priority < b->priority)
444 return (b);
445 if (ntohl(a->id.s_addr)(__uint32_t)(__builtin_constant_p(a->id.s_addr) ? (__uint32_t
)(((__uint32_t)(a->id.s_addr) & 0xff) << 24 | ((
__uint32_t)(a->id.s_addr) & 0xff00) << 8 | ((__uint32_t
)(a->id.s_addr) & 0xff0000) >> 8 | ((__uint32_t)
(a->id.s_addr) & 0xff000000) >> 24) : __swap32md
(a->id.s_addr))
> ntohl(b->id.s_addr)(__uint32_t)(__builtin_constant_p(b->id.s_addr) ? (__uint32_t
)(((__uint32_t)(b->id.s_addr) & 0xff) << 24 | ((
__uint32_t)(b->id.s_addr) & 0xff00) << 8 | ((__uint32_t
)(b->id.s_addr) & 0xff0000) >> 8 | ((__uint32_t)
(b->id.s_addr) & 0xff000000) >> 24) : __swap32md
(b->id.s_addr))
)
446 return (a);
447 return (b);
448}
449
450int
451if_act_elect(struct iface *iface)
452{
453 struct in6_addr addr;
454 struct nbr *nbr, *bdr = NULL((void*)0), *dr = NULL((void*)0);
455 int round = 0;
456 int changed = 0;
457 int old_state;
458 char b1[16], b2[16], b3[16], b4[16];
459
460start:
461 /* elect backup designated router */
462 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
11
Assuming 'nbr' is not equal to null
12
Loop condition is true. Entering loop body
18
Assuming 'nbr' is equal to null
19
Loop condition is false. Execution continues on line 485
463 if (nbr->priority == 0 || nbr
13.1
'nbr' is not equal to 'dr'
== dr || /* not electable */
13
Assuming field 'priority' is not equal to 0
16
Taking true branch
464 nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004) || /* not available */
14
Assuming the condition is false
465 nbr->dr.s_addr == nbr->id.s_addr) /* don't elect DR */
15
Assuming 'nbr->dr.s_addr' is equal to 'nbr->id.s_addr'
466 continue;
17
Execution continues on line 462
467 if (bdr != NULL((void*)0)) {
468 /*
469 * routers announcing themselves as BDR have higher
470 * precedence over those routers announcing a
471 * different BDR.
472 */
473 if (nbr->bdr.s_addr == nbr->id.s_addr) {
474 if (bdr->bdr.s_addr == bdr->id.s_addr)
475 bdr = if_elect(bdr, nbr);
476 else
477 bdr = nbr;
478 } else if (bdr->bdr.s_addr != bdr->id.s_addr)
479 bdr = if_elect(bdr, nbr);
480 } else
481 bdr = nbr;
482 }
483
484 /* elect designated router */
485 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
20
Loop condition is true. Entering loop body
23
Loop condition is false. Execution continues on line 496
486 if (nbr->priority
20.1
Field 'priority' is not equal to 0
== 0 || nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004) ||
21
Taking false branch
487 (nbr
20.2
'nbr' is not equal to 'dr'
!= dr && nbr->dr.s_addr
20.3
'nbr->dr.s_addr' is equal to 'nbr->id.s_addr'
!= nbr->id.s_addr))
488 /* only DR may be elected check priority too */
489 continue;
490 if (dr
21.1
'dr' is equal to NULL
== NULL((void*)0))
22
Taking true branch
491 dr = nbr;
492 else
493 dr = if_elect(dr, nbr);
494 }
495
496 if (dr
23.1
'dr' is not equal to NULL
== NULL((void*)0)) {
24
Taking false branch
497 /* no designate router found use backup DR */
498 dr = bdr;
499 bdr = NULL((void*)0);
500 }
501
502 /*
503 * if we are involved in the election (e.g. new DR or no
504 * longer BDR) redo the election
505 */
506 if (round
24.1
'round' is equal to 0
== 0 &&
507 ((iface->self == dr && iface->self != iface->dr) ||
25
Assuming 'dr' is not equal to field 'self'
508 (iface->self != dr
25.1
'dr' is not equal to field 'self'
&& iface->self == iface->dr) ||
26
Assuming field 'self' is not equal to field 'dr'
509 (iface->self == bdr && iface->self != iface->bdr) ||
27
Assuming 'bdr' is equal to field 'self'
28
Assuming pointer value is null
29
Assuming field 'self' is not equal to field 'bdr'
510 (iface->self != bdr && iface->self == iface->bdr))) {
511 /*
512 * Reset announced DR/BDR to calculated one, so
513 * that we may get elected in the second round.
514 * This is needed to drop from a DR to a BDR.
515 */
516 iface->self->dr.s_addr = dr->id.s_addr;
30
Dereference of null pointer
517 if (bdr)
518 iface->self->bdr.s_addr = bdr->id.s_addr;
519 round = 1;
520 goto start;
521 }
522
523 log_debug("if_act_elect: interface %s old dr %s new dr %s, "
524 "old bdr %s new bdr %s", iface->name,
525 iface->dr ? inet_ntop(AF_INET2, &iface->dr->id, b1, sizeof(b1)) :
526 "none", dr ? inet_ntop(AF_INET2, &dr->id, b2, sizeof(b2)) : "none",
527 iface->bdr ? inet_ntop(AF_INET2, &iface->bdr->id, b3, sizeof(b3)) :
528 "none", bdr ? inet_ntop(AF_INET2, &bdr->id, b4, sizeof(b4)) :
529 "none");
530
531 /*
532 * After the second round still DR or BDR change state to DR or BDR,
533 * etc.
534 */
535 old_state = iface->state;
536 if (dr == iface->self)
537 iface->state = IF_STA_DR0x40;
538 else if (bdr == iface->self)
539 iface->state = IF_STA_BACKUP0x20;
540 else
541 iface->state = IF_STA_DROTHER0x10;
542
543 /* TODO if iface is NBMA send all non eligible neighbors event Start */
544
545 /*
546 * if DR or BDR changed issue a AdjOK? event for all neighbors > 2-Way
547 */
548 if (iface->dr != dr || iface->bdr != bdr)
549 changed = 1;
550
551 iface->dr = dr;
552 iface->bdr = bdr;
553
554 if (changed) {
555 inet_pton(AF_INET624, AllDRouters"ff02::6", &addr);
556 if (old_state & IF_STA_DRORBDR(0x40 | 0x20) &&
557 (iface->state & IF_STA_DRORBDR(0x40 | 0x20)) == 0) {
558 if (if_leave_group(iface, &addr))
559 return (-1);
560 } else if ((old_state & IF_STA_DRORBDR(0x40 | 0x20)) == 0 &&
561 iface->state & IF_STA_DRORBDR(0x40 | 0x20)) {
562 if (if_join_group(iface, &addr))
563 return (-1);
564 }
565
566 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
567 if (nbr->state & NBR_STA_BIDIR(0x0008 | (0x0010 | 0x0020 | (0x0040 | 0x0080 | 0x0100))))
568 nbr_fsm(nbr, NBR_EVT_ADJ_OK);
569 }
570
571 orig_rtr_lsa(iface->area);
572 if (iface->state & IF_STA_DR0x40 || old_state & IF_STA_DR0x40)
573 orig_net_lsa(iface);
574 }
575
576 if_start_hello_timer(iface);
577 return (0);
578}
579
580int
581if_act_reset(struct iface *iface)
582{
583 struct nbr *nbr = NULL((void*)0);
584 struct in6_addr addr;
585
586 if (iface->cflags & F_IFACE_PASSIVE0x01) {
587 /* for an update of stub network entries */
588 orig_rtr_lsa(iface->area);
589 return (0);
590 }
591
592 switch (iface->type) {
593 case IF_TYPE_POINTOPOINT:
594 case IF_TYPE_BROADCAST:
595 inet_pton(AF_INET624, AllSPFRouters"ff02::5", &addr);
596 if (if_leave_group(iface, &addr)) {
597 log_warnx("if_act_reset: error leaving group %s, "
598 "interface %s", log_in6addr(&addr), iface->name);
599 }
600 if (iface->state & IF_STA_DRORBDR(0x40 | 0x20)) {
601 inet_pton(AF_INET624, AllDRouters"ff02::6", &addr);
602 if (if_leave_group(iface, &addr)) {
603 log_warnx("if_act_reset: "
604 "error leaving group %s, interface %s",
605 log_in6addr(&addr), iface->name);
606 }
607 }
608 break;
609 case IF_TYPE_VIRTUALLINK:
610 /* nothing */
611 break;
612 case IF_TYPE_NBMA:
613 case IF_TYPE_POINTOMULTIPOINT:
614 log_debug("if_act_reset: type %s not supported, interface %s",
615 if_type_name(iface->type), iface->name);
616 return (-1);
617 default:
618 fatalx("if_act_reset: unknown interface type");
619 }
620
621 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
622 if (nbr_fsm(nbr, NBR_EVT_KILL_NBR)) {
623 log_debug("if_act_reset: error killing neighbor %s",
624 inet_ntoa(nbr->id));
625 }
626 }
627
628 iface->dr = NULL((void*)0);
629 iface->bdr = NULL((void*)0);
630
631 ls_ack_list_clr(iface);
632 stop_ls_ack_tx_timer(iface);
633 if_stop_hello_timer(iface);
634 if_stop_wait_timer(iface);
635
636 /* send empty hello to tell everybody that we are going down */
637 send_hello(iface);
638
639 return (0);
640}
641
642struct ctl_iface *
643if_to_ctl(struct iface *iface)
644{
645 static struct ctl_iface ictl;
646 struct timeval tv, now, res;
647 struct nbr *nbr;
648
649 memcpy(ictl.name, iface->name, sizeof(ictl.name));
650 memcpy(&ictl.addr, &iface->addr, sizeof(ictl.addr));
651 ictl.rtr_id.s_addr = ospfe_router_id();
652 memcpy(&ictl.area, &iface->area->id, sizeof(ictl.area));
653 if (iface->dr) {
654 memcpy(&ictl.dr_id, &iface->dr->id, sizeof(ictl.dr_id));
655 memcpy(&ictl.dr_addr, &iface->dr->addr, sizeof(ictl.dr_addr));
656 } else {
657 bzero(&ictl.dr_id, sizeof(ictl.dr_id));
658 bzero(&ictl.dr_addr, sizeof(ictl.dr_addr));
659 }
660 if (iface->bdr) {
661 memcpy(&ictl.bdr_id, &iface->bdr->id, sizeof(ictl.bdr_id));
662 memcpy(&ictl.bdr_addr, &iface->bdr->addr,
663 sizeof(ictl.bdr_addr));
664 } else {
665 bzero(&ictl.bdr_id, sizeof(ictl.bdr_id));
666 bzero(&ictl.bdr_addr, sizeof(ictl.bdr_addr));
667 }
668 ictl.ifindex = iface->ifindex;
669 ictl.state = iface->state;
670 ictl.mtu = iface->mtu;
671 ictl.nbr_cnt = 0;
672 ictl.adj_cnt = 0;
673 ictl.baudrate = iface->baudrate;
674 ictl.dead_interval = iface->dead_interval;
675 ictl.transmit_delay = iface->transmit_delay;
676 ictl.hello_interval = iface->hello_interval;
677 ictl.flags = iface->flags;
678 ictl.metric = iface->metric;
679 ictl.rxmt_interval = iface->rxmt_interval;
680 ictl.type = iface->type;
681 ictl.linkstate = iface->linkstate;
682 ictl.if_type = iface->if_type;
683 ictl.priority = iface->priority;
684 ictl.passive = (iface->cflags & F_IFACE_PASSIVE0x01) == F_IFACE_PASSIVE0x01;
685
686 gettimeofday(&now, NULL((void*)0));
687 if (evtimer_pending(&iface->hello_timer, &tv)event_pending(&iface->hello_timer, 0x01, &tv)) {
688 timersub(&tv, &now, &res)do { (&res)->tv_sec = (&tv)->tv_sec - (&now
)->tv_sec; (&res)->tv_usec = (&tv)->tv_usec -
(&now)->tv_usec; if ((&res)->tv_usec < 0) {
(&res)->tv_sec--; (&res)->tv_usec += 1000000; }
} while (0)
;
689 ictl.hello_timer = res.tv_sec;
690 } else
691 ictl.hello_timer = -1;
692
693 if (iface->state != IF_STA_DOWN0x01) {
694 ictl.uptime = now.tv_sec - iface->uptime;
695 } else
696 ictl.uptime = 0;
697
698 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
699 if (nbr == iface->self)
700 continue;
701 ictl.nbr_cnt++;
702 if (nbr->state & NBR_STA_ADJFORM(0x0010 | 0x0020 | (0x0040 | 0x0080 | 0x0100)))
703 ictl.adj_cnt++;
704 }
705
706 return (&ictl);
707}
708
709/* misc */
710void
711if_set_sockbuf(int fd)
712{
713 int bsize;
714
715 bsize = 256 * 1024;
716 while (setsockopt(fd, SOL_SOCKET0xffff, SO_RCVBUF0x1002, &bsize,
717 sizeof(bsize)) == -1)
718 bsize /= 2;
719
720 if (bsize != 256 * 1024)
721 log_warnx("if_set_sockbuf: recvbuf size only %d", bsize);
722
723 bsize = 64 * 1024;
724 while (setsockopt(fd, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize,
725 sizeof(bsize)) == -1)
726 bsize /= 2;
727
728 if (bsize != 64 * 1024)
729 log_warnx("if_set_sockbuf: sendbuf size only %d", bsize);
730}
731
732int
733if_join_group(struct iface *iface, struct in6_addr *addr)
734{
735 struct ipv6_mreq mreq;
736
737 switch (iface->type) {
738 case IF_TYPE_POINTOPOINT:
739 case IF_TYPE_BROADCAST:
740 log_debug("if_join_group: interface %s addr %s",
741 iface->name, log_in6addr(addr));
742 mreq.ipv6mr_multiaddr = *addr;
743 mreq.ipv6mr_interface = iface->ifindex;
744
745 if (setsockopt(iface->fd, IPPROTO_IPV641, IPV6_JOIN_GROUP12,
746 &mreq, sizeof(mreq)) == -1) {
747 log_warn("if_join_group: error IPV6_JOIN_GROUP, "
748 "interface %s address %s", iface->name,
749 log_in6addr(addr));
750 return (-1);
751 }
752 break;
753 case IF_TYPE_POINTOMULTIPOINT:
754 case IF_TYPE_VIRTUALLINK:
755 case IF_TYPE_NBMA:
756 log_debug("if_join_group: type %s not supported, interface %s",
757 if_type_name(iface->type), iface->name);
758 return (-1);
759 default:
760 fatalx("if_join_group: unknown interface type");
761 }
762
763 return (0);
764}
765
766int
767if_leave_group(struct iface *iface, struct in6_addr *addr)
768{
769 struct ipv6_mreq mreq;
770
771 switch (iface->type) {
772 case IF_TYPE_POINTOPOINT:
773 case IF_TYPE_BROADCAST:
774 log_debug("if_leave_group: interface %s addr %s",
775 iface->name, log_in6addr(addr));
776 mreq.ipv6mr_multiaddr = *addr;
777 mreq.ipv6mr_interface = iface->ifindex;
778
779 if (setsockopt(iface->fd, IPPROTO_IPV641, IPV6_LEAVE_GROUP13,
780 (void *)&mreq, sizeof(mreq)) == -1) {
781 log_warn("if_leave_group: error IPV6_LEAVE_GROUP, "
782 "interface %s address %s", iface->name,
783 log_in6addr(addr));
784 return (-1);
785 }
786 break;
787 case IF_TYPE_POINTOMULTIPOINT:
788 case IF_TYPE_VIRTUALLINK:
789 case IF_TYPE_NBMA:
790 log_debug("if_leave_group: type %s not supported, interface %s",
791 if_type_name(iface->type), iface->name);
792 return (-1);
793 default:
794 fatalx("if_leave_group: unknown interface type");
795 }
796 return (0);
797}
798
799int
800if_set_mcast(struct iface *iface)
801{
802 switch (iface->type) {
803 case IF_TYPE_POINTOPOINT:
804 case IF_TYPE_BROADCAST:
805 if (setsockopt(iface->fd, IPPROTO_IPV641, IPV6_MULTICAST_IF9,
806 &iface->ifindex, sizeof(iface->ifindex)) == -1) {
807 log_debug("if_set_mcast: error setting "
808 "IP_MULTICAST_IF, interface %s", iface->name);
809 return (-1);
810 }
811 break;
812 case IF_TYPE_POINTOMULTIPOINT:
813 case IF_TYPE_VIRTUALLINK:
814 case IF_TYPE_NBMA:
815 log_debug("if_set_mcast: type %s not supported, interface %s",
816 if_type_name(iface->type), iface->name);
817 return (-1);
818 default:
819 fatalx("if_set_mcast: unknown interface type");
820 }
821
822 return (0);
823}
824
825int
826if_set_mcast_loop(int fd)
827{
828 u_int loop = 0;
829
830 if (setsockopt(fd, IPPROTO_IPV641, IPV6_MULTICAST_LOOP11,
831 (u_int *)&loop, sizeof(loop)) == -1) {
832 log_warn("if_set_mcast_loop: error setting "
833 "IPV6_MULTICAST_LOOP");
834 return (-1);
835 }
836
837 return (0);
838}
839
840int
841if_set_ipv6_pktinfo(int fd, int enable)
842{
843 if (setsockopt(fd, IPPROTO_IPV641, IPV6_RECVPKTINFO36, &enable,
844 sizeof(enable)) == -1) {
845 log_warn("if_set_ipv6_pktinfo: error setting IPV6_PKTINFO");
846 return (-1);
847 }
848
849 return (0);
850}
851
852int
853if_set_ipv6_checksum(int fd)
854{
855 int offset = offsetof(struct ospf_hdr, chksum)__builtin_offsetof(struct ospf_hdr, chksum);
856
857 log_debug("if_set_ipv6_checksum setting cksum offset to %d", offset);
858 if (setsockopt(fd, IPPROTO_IPV641, IPV6_CHECKSUM26, &offset,
859 sizeof(offset)) == -1) {
860 log_warn("if_set_ipv6_checksum: error setting IPV6_CHECKSUM");
861 return (-1);
862 }
863 return (0);
864}