Bug Summary

File:src/usr.sbin/ospfd/interface.c
Warning:line 468, 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/ospfd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ospfd -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/ospfd/interface.c
1/* $OpenBSD: interface.c,v 1.86 2021/01/16 08:03:55 claudio Exp $ */
2
3/*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004, 2005 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 "ospfd.h"
37#include "ospf.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
70static int vlink_cnt = 0;
71
72const char * const if_event_names[] = {
73 "NOTHING",
74 "UP",
75 "WAITTIMER",
76 "BACKUPSEEN",
77 "NEIGHBORCHANGE",
78 "LOOP",
79 "UNLOOP",
80 "DOWN"
81};
82
83const char * const if_action_names[] = {
84 "NOTHING",
85 "START",
86 "ELECT",
87 "RESET"
88};
89
90int
91if_fsm(struct iface *iface, enum iface_event event)
92{
93 int old_state;
94 int new_state = 0;
95 int i, ret = 0;
96
97 old_state = iface->state;
98
99 for (i = 0; iface_fsm[i].state != -1; i++)
2
Assuming the condition is true
3
Loop condition is true. Entering loop body
100 if ((iface_fsm[i].state & old_state) &&
4
Assuming the condition is true
6
Taking true branch
101 (iface_fsm[i].event == event)) {
5
Assuming 'event' is equal to field 'event'
102 new_state = iface_fsm[i].new_state;
103 break;
7
Execution continues on line 106
104 }
105
106 if (iface_fsm[i].state == -1) {
8
Taking false branch
107 /* event outside of the defined fsm, ignore it. */
108 log_debug("if_fsm: interface %s, "
109 "event %s not expected in state %s", iface->name,
110 if_event_names[event], if_state_name(old_state));
111 return (0);
112 }
113
114 switch (iface_fsm[i].action) {
9
Control jumps to 'case IF_ACT_ELECT:' at line 118
115 case IF_ACT_STRT:
116 ret = if_act_start(iface);
117 break;
118 case IF_ACT_ELECT:
119 ret = if_act_elect(iface);
10
Calling 'if_act_elect'
120 break;
121 case IF_ACT_RST:
122 ret = if_act_reset(iface);
123 break;
124 case IF_ACT_NOTHING:
125 /* do nothing */
126 break;
127 }
128
129 if (ret) {
130 log_debug("if_fsm: error changing state for interface %s, "
131 "event %s, state %s", iface->name, if_event_names[event],
132 if_state_name(old_state));
133 return (-1);
134 }
135
136 if (new_state != 0)
137 iface->state = new_state;
138
139 if (iface->state != old_state) {
140 area_track(iface->area);
141 orig_rtr_lsa(iface->area);
142 }
143
144 if (old_state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08) &&
145 (iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0)
146 ospfe_demote_iface(iface, 0);
147 if ((old_state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0 &&
148 iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08))
149 ospfe_demote_iface(iface, 1);
150
151 log_debug("if_fsm: event %s resulted in action %s and changing "
152 "state for interface %s from %s to %s",
153 if_event_names[event], if_action_names[iface_fsm[i].action],
154 iface->name, if_state_name(old_state), if_state_name(iface->state));
155
156 return (ret);
157}
158
159struct iface *
160if_new(struct kif *kif, struct kif_addr *ka)
161{
162 struct iface *iface;
163
164 if ((iface = calloc(1, sizeof(*iface))) == NULL((void*)0))
165 err(1, "if_new: calloc");
166
167 iface->state = IF_STA_DOWN0x01;
168
169 LIST_INIT(&iface->nbr_list)do { ((&iface->nbr_list)->lh_first) = ((void*)0); }
while (0)
;
170 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)
;
171 TAILQ_INIT(&iface->auth_md_list)do { (&iface->auth_md_list)->tqh_first = ((void*)0)
; (&iface->auth_md_list)->tqh_last = &(&iface
->auth_md_list)->tqh_first; } while (0)
;
172 RB_INIT(&iface->lsa_tree)do { (&iface->lsa_tree)->rbh_root = ((void*)0); } while
(0)
;
173
174 iface->crypt_seq_num = arc4random() & 0x0fffffff;
175
176 if (kif == NULL((void*)0)) {
177 iface->type = IF_TYPE_VIRTUALLINK;
178 snprintf(iface->name, sizeof(iface->name), "vlink%d",
179 vlink_cnt++);
180 iface->flags |= IFF_UP0x1;
181 iface->mtu = IP_MSS576;
182 return (iface);
183 }
184
185 strlcpy(iface->name, kif->ifname, sizeof(iface->name));
186
187 /* get type */
188 if (kif->flags & IFF_POINTOPOINT0x10)
189 iface->type = IF_TYPE_POINTOPOINT;
190 if (kif->flags & IFF_BROADCAST0x2 &&
191 kif->flags & IFF_MULTICAST0x8000)
192 iface->type = IF_TYPE_BROADCAST;
193 if (kif->flags & IFF_LOOPBACK0x8) {
194 iface->type = IF_TYPE_POINTOPOINT;
195 iface->passive = 1;
196 }
197
198 /* get mtu, index and flags */
199 iface->mtu = kif->mtu;
200 iface->ifindex = kif->ifindex;
201 iface->rdomain = kif->rdomain;
202 iface->flags = kif->flags;
203 iface->linkstate = kif->link_state;
204 iface->if_type = kif->if_type;
205 iface->baudrate = kif->baudrate;
206
207 /* set address, mask and p2p addr */
208 iface->addr = ka->addr;
209 iface->mask = ka->mask;
210 if (kif->flags & IFF_POINTOPOINT0x10) {
211 iface->dst = ka->dstbrd;
212 }
213
214 return (iface);
215}
216
217void
218if_del(struct iface *iface)
219{
220 struct nbr *nbr = NULL((void*)0);
221
222 /* revert the demotion when the interface is deleted */
223 if ((iface->state & (IF_STA_MULTI(0x10 | 0x20 | 0x40) | IF_STA_POINTTOPOINT0x08)) == 0)
224 ospfe_demote_iface(iface, 1);
225
226 /* clear lists etc */
227 while ((nbr = LIST_FIRST(&iface->nbr_list)((&iface->nbr_list)->lh_first)) != NULL((void*)0))
228 nbr_del(nbr);
229
230 if (evtimer_pending(&iface->hello_timer, NULL)event_pending(&iface->hello_timer, 0x01, ((void*)0)))
231 evtimer_del(&iface->hello_timer)event_del(&iface->hello_timer);
232 if (evtimer_pending(&iface->wait_timer, NULL)event_pending(&iface->wait_timer, 0x01, ((void*)0)))
233 evtimer_del(&iface->wait_timer)event_del(&iface->wait_timer);
234 if (evtimer_pending(&iface->lsack_tx_timer, NULL)event_pending(&iface->lsack_tx_timer, 0x01, ((void*)0)
)
)
235 evtimer_del(&iface->lsack_tx_timer)event_del(&iface->lsack_tx_timer);
236
237 ls_ack_list_clr(iface);
238 md_list_clr(&iface->auth_md_list);
239 free(iface);
240}
241
242void
243if_init(struct ospfd_conf *xconf, struct iface *iface)
244{
245 /* init the dummy local neighbor */
246 iface->self = nbr_new(ospfe_router_id(), iface, 1);
247
248 /* set event handlers for interface */
249 evtimer_set(&iface->lsack_tx_timer, ls_ack_tx_timer, iface)event_set(&iface->lsack_tx_timer, -1, 0, ls_ack_tx_timer
, iface)
;
250 evtimer_set(&iface->hello_timer, if_hello_timer, iface)event_set(&iface->hello_timer, -1, 0, if_hello_timer, iface
)
;
251 evtimer_set(&iface->wait_timer, if_wait_timer, iface)event_set(&iface->wait_timer, -1, 0, if_wait_timer, iface
)
;
252
253 iface->fd = xconf->ospf_socket;
254
255 ospfe_demote_iface(iface, 0);
256}
257
258/* timers */
259/* ARGSUSED */
260void
261if_hello_timer(int fd, short event, void *arg)
262{
263 struct iface *iface = arg;
264 struct timeval tv;
265
266 send_hello(iface);
267
268 /* reschedule hello_timer */
269 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
270 if (iface->dead_interval == FAST_RTR_DEAD_TIME1)
271 tv.tv_usec = iface->fast_hello_interval * 1000;
272 else
273 tv.tv_sec = iface->hello_interval;
274 if (evtimer_add(&iface->hello_timer, &tv)event_add(&iface->hello_timer, &tv) == -1)
275 fatal("if_hello_timer");
276}
277
278void
279if_start_hello_timer(struct iface *iface)
280{
281 struct timeval tv;
282
283 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
284 if (evtimer_add(&iface->hello_timer, &tv)event_add(&iface->hello_timer, &tv) == -1)
285 fatal("if_start_hello_timer");
286}
287
288void
289if_stop_hello_timer(struct iface *iface)
290{
291 if (evtimer_del(&iface->hello_timer)event_del(&iface->hello_timer) == -1)
292 fatal("if_stop_hello_timer");
293}
294
295/* ARGSUSED */
296void
297if_wait_timer(int fd, short event, void *arg)
298{
299 struct iface *iface = arg;
300
301 if_fsm(iface, IF_EVT_WTIMER);
1
Calling 'if_fsm'
302}
303
304void
305if_start_wait_timer(struct iface *iface)
306{
307 struct timeval tv;
308
309 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
310 tv.tv_sec = iface->dead_interval;
311 if (evtimer_add(&iface->wait_timer, &tv)event_add(&iface->wait_timer, &tv) == -1)
312 fatal("if_start_wait_timer");
313}
314
315void
316if_stop_wait_timer(struct iface *iface)
317{
318 if (evtimer_del(&iface->wait_timer)event_del(&iface->wait_timer) == -1)
319 fatal("if_stop_wait_timer");
320}
321
322/* actions */
323int
324if_act_start(struct iface *iface)
325{
326 struct in_addr addr;
327 struct timeval now;
328
329 if (!(iface->flags & IFF_UP0x1) ||
330 (!LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0) &&
331 !(iface->if_type == IFT_CARP0xf7 &&
332 iface->linkstate == LINK_STATE_DOWN2)))
333 return (0);
334
335 if (iface->if_type == IFT_CARP0xf7 && iface->passive == 0) {
336 /* force passive mode on carp interfaces */
337 log_warnx("if_act_start: forcing interface %s to passive",
338 iface->name);
339 iface->passive = 1;
340 }
341
342 gettimeofday(&now, NULL((void*)0));
343 iface->uptime = now.tv_sec;
344
345 /* loopback interfaces have a special state and are passive */
346 if (iface->flags & IFF_LOOPBACK0x8)
347 iface->state = IF_STA_LOOPBACK0x02;
348
349 if (iface->passive) {
350 /* for an update of stub network entries */
351 orig_rtr_lsa(iface->area);
352 return (0);
353 }
354
355 switch (iface->type) {
356 case IF_TYPE_POINTOPOINT:
357 inet_aton(AllSPFRouters"224.0.0.5", &addr);
358 if (if_join_group(iface, &addr))
359 return (-1);
360 iface->state = IF_STA_POINTTOPOINT0x08;
361 break;
362 case IF_TYPE_VIRTUALLINK:
363 iface->state = IF_STA_POINTTOPOINT0x08;
364 break;
365 case IF_TYPE_POINTOMULTIPOINT:
366 case IF_TYPE_NBMA:
367 log_debug("if_act_start: type %s not supported, interface %s",
368 if_type_name(iface->type), iface->name);
369 return (-1);
370 case IF_TYPE_BROADCAST:
371 inet_aton(AllSPFRouters"224.0.0.5", &addr);
372 if (if_join_group(iface, &addr))
373 return (-1);
374 if (iface->priority == 0) {
375 iface->state = IF_STA_DROTHER0x10;
376 } else {
377 iface->state = IF_STA_WAITING0x04;
378 if_start_wait_timer(iface);
379 }
380 break;
381 default:
382 fatalx("if_act_start: unknown interface type");
383 }
384
385 /* hello timer needs to be started in any case */
386 if_start_hello_timer(iface);
387 return (0);
388}
389
390struct nbr *
391if_elect(struct nbr *a, struct nbr *b)
392{
393 if (a->priority > b->priority)
394 return (a);
395 if (a->priority < b->priority)
396 return (b);
397 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))
)
398 return (a);
399 return (b);
400}
401
402int
403if_act_elect(struct iface *iface)
404{
405 struct in_addr addr;
406 struct nbr *nbr, *bdr = NULL((void*)0), *dr = NULL((void*)0);
407 int round = 0;
408 int changed = 0;
409 int old_state;
410 char b1[16], b2[16], b3[16], b4[16];
411
412start:
413 /* elect backup designated router */
414 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 437
415 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
416 nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004) || /* not available */
14
Assuming the condition is false
417 nbr->dr.s_addr == nbr->addr.s_addr) /* don't elect DR */
15
Assuming 'nbr->dr.s_addr' is equal to 'nbr->addr.s_addr'
418 continue;
17
Execution continues on line 414
419 if (bdr != NULL((void*)0)) {
420 /*
421 * routers announcing themselves as BDR have higher
422 * precedence over those routers announcing a
423 * different BDR.
424 */
425 if (nbr->bdr.s_addr == nbr->addr.s_addr) {
426 if (bdr->bdr.s_addr == bdr->addr.s_addr)
427 bdr = if_elect(bdr, nbr);
428 else
429 bdr = nbr;
430 } else if (bdr->bdr.s_addr != bdr->addr.s_addr)
431 bdr = if_elect(bdr, nbr);
432 } else
433 bdr = nbr;
434 }
435
436 /* elect designated router */
437 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 448
438 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
439 (nbr
20.2
'nbr' is not equal to 'dr'
!= dr && nbr->dr.s_addr
20.3
'nbr->dr.s_addr' is equal to 'nbr->addr.s_addr'
!= nbr->addr.s_addr))
440 /* only DR may be elected check priority too */
441 continue;
442 if (dr
21.1
'dr' is equal to NULL
== NULL((void*)0))
22
Taking true branch
443 dr = nbr;
444 else
445 dr = if_elect(dr, nbr);
446 }
447
448 if (dr
23.1
'dr' is not equal to NULL
== NULL((void*)0)) {
24
Taking false branch
449 /* no designated router found use backup DR */
450 dr = bdr;
451 bdr = NULL((void*)0);
452 }
453
454 /*
455 * if we are involved in the election (e.g. new DR or no
456 * longer BDR) redo the election
457 */
458 if (round
24.1
'round' is equal to 0
== 0 &&
459 ((iface->self == dr && iface->self != iface->dr) ||
25
Assuming 'dr' is not equal to field 'self'
460 (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'
461 (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'
462 (iface->self != bdr && iface->self == iface->bdr))) {
463 /*
464 * Reset announced DR/BDR to calculated one, so
465 * that we may get elected in the second round.
466 * This is needed to drop from a DR to a BDR.
467 */
468 iface->self->dr.s_addr = dr->addr.s_addr;
30
Dereference of null pointer
469 if (bdr)
470 iface->self->bdr.s_addr = bdr->addr.s_addr;
471 round = 1;
472 goto start;
473 }
474
475 log_debug("if_act_elect: interface %s old dr %s new dr %s, "
476 "old bdr %s new bdr %s", iface->name,
477 iface->dr ? inet_ntop(AF_INET2, &iface->dr->addr, b1, sizeof(b1)) :
478 "none", dr ? inet_ntop(AF_INET2, &dr->addr, b2, sizeof(b2)) : "none",
479 iface->bdr ? inet_ntop(AF_INET2, &iface->bdr->addr, b3, sizeof(b3)) :
480 "none", bdr ? inet_ntop(AF_INET2, &bdr->addr, b4, sizeof(b4)) :
481 "none");
482
483 /*
484 * After the second round still DR or BDR change state to DR or BDR,
485 * etc.
486 */
487 old_state = iface->state;
488 if (dr == iface->self)
489 iface->state = IF_STA_DR0x40;
490 else if (bdr == iface->self)
491 iface->state = IF_STA_BACKUP0x20;
492 else
493 iface->state = IF_STA_DROTHER0x10;
494
495 /* TODO if iface is NBMA send all non eligible neighbors event Start */
496
497 /*
498 * if DR or BDR changed issue a AdjOK? event for all neighbors > 2-Way
499 */
500 if (iface->dr != dr || iface->bdr != bdr)
501 changed = 1;
502
503 iface->dr = dr;
504 iface->bdr = bdr;
505
506 if (changed) {
507 inet_aton(AllDRouters"224.0.0.6", &addr);
508 if (old_state & IF_STA_DRORBDR(0x40 | 0x20) &&
509 (iface->state & IF_STA_DRORBDR(0x40 | 0x20)) == 0) {
510 if (if_leave_group(iface, &addr))
511 return (-1);
512 } else if ((old_state & IF_STA_DRORBDR(0x40 | 0x20)) == 0 &&
513 iface->state & IF_STA_DRORBDR(0x40 | 0x20)) {
514 if (if_join_group(iface, &addr))
515 return (-1);
516 }
517
518 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
519 if (nbr->state & NBR_STA_BIDIR(0x0008 | (0x0010 | 0x0020 | (0x0040 | 0x0080 | 0x0100))))
520 nbr_fsm(nbr, NBR_EVT_ADJ_OK);
521 }
522
523 orig_rtr_lsa(iface->area);
524 if (iface->state & IF_STA_DR0x40 || old_state & IF_STA_DR0x40)
525 orig_net_lsa(iface);
526 }
527
528 if_start_hello_timer(iface);
529 return (0);
530}
531
532int
533if_act_reset(struct iface *iface)
534{
535 struct nbr *nbr = NULL((void*)0);
536 struct in_addr addr;
537
538 if (iface->passive) {
539 /* for an update of stub network entries */
540 orig_rtr_lsa(iface->area);
541 return (0);
542 }
543
544 switch (iface->type) {
545 case IF_TYPE_POINTOPOINT:
546 case IF_TYPE_BROADCAST:
547 /* try to cleanup */
548 inet_aton(AllSPFRouters"224.0.0.5", &addr);
549 if_leave_group(iface, &addr);
550 if (iface->state & IF_STA_DRORBDR(0x40 | 0x20)) {
551 inet_aton(AllDRouters"224.0.0.6", &addr);
552 if_leave_group(iface, &addr);
553 }
554 break;
555 case IF_TYPE_VIRTUALLINK:
556 /* nothing */
557 break;
558 case IF_TYPE_NBMA:
559 case IF_TYPE_POINTOMULTIPOINT:
560 log_debug("if_act_reset: type %s not supported, interface %s",
561 if_type_name(iface->type), iface->name);
562 return (-1);
563 default:
564 fatalx("if_act_reset: unknown interface type");
565 }
566
567 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
568 if (nbr_fsm(nbr, NBR_EVT_KILL_NBR)) {
569 log_debug("if_act_reset: error killing neighbor %s",
570 inet_ntoa(nbr->id));
571 }
572 }
573
574 iface->dr = NULL((void*)0);
575 iface->bdr = NULL((void*)0);
576
577 ls_ack_list_clr(iface);
578 stop_ls_ack_tx_timer(iface);
579 if_stop_hello_timer(iface);
580 if_stop_wait_timer(iface);
581
582 /* send empty hello to tell everybody that we are going down */
583 send_hello(iface);
584
585 return (0);
586}
587
588struct ctl_iface *
589if_to_ctl(struct iface *iface)
590{
591 static struct ctl_iface ictl;
592 struct timeval tv, now, res;
593 struct nbr *nbr;
594
595 memcpy(ictl.name, iface->name, sizeof(ictl.name));
596 memcpy(&ictl.addr, &iface->addr, sizeof(ictl.addr));
597 memcpy(&ictl.mask, &iface->mask, sizeof(ictl.mask));
598 ictl.rtr_id.s_addr = ospfe_router_id();
599 memcpy(&ictl.area, &iface->area->id, sizeof(ictl.area));
600 if (iface->dr) {
601 memcpy(&ictl.dr_id, &iface->dr->id, sizeof(ictl.dr_id));
602 memcpy(&ictl.dr_addr, &iface->dr->addr, sizeof(ictl.dr_addr));
603 } else {
604 bzero(&ictl.dr_id, sizeof(ictl.dr_id));
605 bzero(&ictl.dr_addr, sizeof(ictl.dr_addr));
606 }
607 if (iface->bdr) {
608 memcpy(&ictl.bdr_id, &iface->bdr->id, sizeof(ictl.bdr_id));
609 memcpy(&ictl.bdr_addr, &iface->bdr->addr,
610 sizeof(ictl.bdr_addr));
611 } else {
612 bzero(&ictl.bdr_id, sizeof(ictl.bdr_id));
613 bzero(&ictl.bdr_addr, sizeof(ictl.bdr_addr));
614 }
615 ictl.ifindex = iface->ifindex;
616 ictl.state = iface->state;
617 ictl.mtu = iface->mtu;
618 ictl.nbr_cnt = 0;
619 ictl.adj_cnt = 0;
620 ictl.baudrate = iface->baudrate;
621 ictl.dead_interval = iface->dead_interval;
622 ictl.fast_hello_interval = iface->fast_hello_interval;
623 ictl.transmit_delay = iface->transmit_delay;
624 ictl.hello_interval = iface->hello_interval;
625 ictl.flags = iface->flags;
626 ictl.metric = iface->metric;
627 ictl.rxmt_interval = iface->rxmt_interval;
628 ictl.type = iface->type;
629 ictl.linkstate = iface->linkstate;
630 ictl.if_type = iface->if_type;
631 ictl.priority = iface->priority;
632 ictl.passive = iface->passive;
633 ictl.auth_type = iface->auth_type;
634 ictl.auth_keyid = iface->auth_keyid;
635
636 memcpy(ictl.dependon, iface->dependon, sizeof(ictl.dependon));
637 ictl.depend_ok = iface->depend_ok;
638
639 gettimeofday(&now, NULL((void*)0));
640 if (evtimer_pending(&iface->hello_timer, &tv)event_pending(&iface->hello_timer, 0x01, &tv)) {
641 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)
;
642 ictl.hello_timer = res;
643 } else {
644 ictl.hello_timer.tv_sec = -1;
645 }
646
647 if (iface->state != IF_STA_DOWN0x01 &&
648 iface->uptime != 0) {
649 ictl.uptime = now.tv_sec - iface->uptime;
650 } else
651 ictl.uptime = 0;
652
653 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void*)0); (nbr) = ((nbr)->entry.le_next))
{
654 if (nbr == iface->self)
655 continue;
656 ictl.nbr_cnt++;
657 if (nbr->state & NBR_STA_ADJFORM(0x0010 | 0x0020 | (0x0040 | 0x0080 | 0x0100)))
658 ictl.adj_cnt++;
659 }
660
661 return (&ictl);
662}
663
664/* misc */
665int
666if_set_recvif(int fd, int enable)
667{
668 if (setsockopt(fd, IPPROTO_IP0, IP_RECVIF30, &enable,
669 sizeof(enable)) == -1) {
670 log_warn("if_set_recvif: error setting IP_RECVIF");
671 return (-1);
672 }
673 return (0);
674}
675
676void
677if_set_sockbuf(int fd)
678{
679 int bsize;
680
681 bsize = 256 * 1024;
682 while (setsockopt(fd, SOL_SOCKET0xffff, SO_RCVBUF0x1002, &bsize,
683 sizeof(bsize)) == -1)
684 bsize /= 2;
685
686 if (bsize != 256 * 1024)
687 log_warnx("if_set_sockbuf: recvbuf size only %d", bsize);
688
689 bsize = 64 * 1024;
690 while (setsockopt(fd, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize,
691 sizeof(bsize)) == -1)
692 bsize /= 2;
693
694 if (bsize != 64 * 1024)
695 log_warnx("if_set_sockbuf: sendbuf size only %d", bsize);
696}
697
698/*
699 * only one JOIN or DROP per interface and address is allowed so we need
700 * to keep track of what is added and removed.
701 */
702struct if_group_count {
703 LIST_ENTRY(if_group_count)struct { struct if_group_count *le_next; struct if_group_count
**le_prev; }
entry;
704 struct in_addr addr;
705 unsigned int ifindex;
706 int count;
707};
708
709LIST_HEAD(,if_group_count)struct { struct if_group_count *lh_first; } ifglist = LIST_HEAD_INITIALIZER(ifglist){ ((void*)0) };
710
711int
712if_join_group(struct iface *iface, struct in_addr *addr)
713{
714 struct ip_mreqn mreq;
715 struct if_group_count *ifg;
716
717 switch (iface->type) {
718 case IF_TYPE_POINTOPOINT:
719 case IF_TYPE_BROADCAST:
720 LIST_FOREACH(ifg, &ifglist, entry)for((ifg) = ((&ifglist)->lh_first); (ifg)!= ((void*)0)
; (ifg) = ((ifg)->entry.le_next))
721 if (iface->ifindex == ifg->ifindex &&
722 addr->s_addr == ifg->addr.s_addr)
723 break;
724 if (ifg == NULL((void*)0)) {
725 if ((ifg = calloc(1, sizeof(*ifg))) == NULL((void*)0))
726 fatal("if_join_group");
727 ifg->addr.s_addr = addr->s_addr;
728 ifg->ifindex = iface->ifindex;
729 LIST_INSERT_HEAD(&ifglist, ifg, entry)do { if (((ifg)->entry.le_next = (&ifglist)->lh_first
) != ((void*)0)) (&ifglist)->lh_first->entry.le_prev
= &(ifg)->entry.le_next; (&ifglist)->lh_first =
(ifg); (ifg)->entry.le_prev = &(&ifglist)->lh_first
; } while (0)
;
730 }
731
732 if (ifg->count++ != 0)
733 /* already joined */
734 return (0);
735
736 memset(&mreq, 0, sizeof(mreq));
737 mreq.imr_multiaddr.s_addr = addr->s_addr;
738 mreq.imr_ifindex = iface->ifindex;
739
740 if (setsockopt(iface->fd, IPPROTO_IP0, IP_ADD_MEMBERSHIP12,
741 (void *)&mreq, sizeof(mreq)) == -1) {
742 log_warn("if_join_group: error IP_ADD_MEMBERSHIP, "
743 "interface %s address %s", iface->name,
744 inet_ntoa(*addr));
745 return (-1);
746 }
747 break;
748 case IF_TYPE_POINTOMULTIPOINT:
749 case IF_TYPE_VIRTUALLINK:
750 case IF_TYPE_NBMA:
751 log_debug("if_join_group: type %s not supported, interface %s",
752 if_type_name(iface->type), iface->name);
753 return (-1);
754 default:
755 fatalx("if_join_group: unknown interface type");
756 }
757
758 return (0);
759}
760
761int
762if_leave_group(struct iface *iface, struct in_addr *addr)
763{
764 struct ip_mreqn mreq;
765 struct if_group_count *ifg;
766
767 switch (iface->type) {
768 case IF_TYPE_POINTOPOINT:
769 case IF_TYPE_BROADCAST:
770 LIST_FOREACH(ifg, &ifglist, entry)for((ifg) = ((&ifglist)->lh_first); (ifg)!= ((void*)0)
; (ifg) = ((ifg)->entry.le_next))
771 if (iface->ifindex == ifg->ifindex &&
772 addr->s_addr == ifg->addr.s_addr)
773 break;
774
775 /* if interface is not found just try to drop membership */
776 if (ifg) {
777 if (--ifg->count != 0)
778 /* others still joined */
779 return (0);
780
781 LIST_REMOVE(ifg, entry)do { if ((ifg)->entry.le_next != ((void*)0)) (ifg)->entry
.le_next->entry.le_prev = (ifg)->entry.le_prev; *(ifg)->
entry.le_prev = (ifg)->entry.le_next; ; ; } while (0)
;
782 free(ifg);
783 }
784
785 memset(&mreq, 0, sizeof(mreq));
786 mreq.imr_multiaddr.s_addr = addr->s_addr;
787 mreq.imr_ifindex = iface->ifindex;
788
789 if (setsockopt(iface->fd, IPPROTO_IP0, IP_DROP_MEMBERSHIP13,
790 (void *)&mreq, sizeof(mreq)) == -1) {
791 log_warn("if_leave_group: error IP_DROP_MEMBERSHIP, "
792 "interface %s address %s", iface->name,
793 inet_ntoa(*addr));
794 return (-1);
795 }
796 break;
797 case IF_TYPE_POINTOMULTIPOINT:
798 case IF_TYPE_VIRTUALLINK:
799 case IF_TYPE_NBMA:
800 log_debug("if_leave_group: type %s not supported, interface %s",
801 if_type_name(iface->type), iface->name);
802 return (-1);
803 default:
804 fatalx("if_leave_group: unknown interface type");
805 }
806
807 return (0);
808}
809
810int
811if_set_mcast(struct iface *iface)
812{
813 struct ip_mreqn mreq;
814
815 switch (iface->type) {
816 case IF_TYPE_POINTOPOINT:
817 case IF_TYPE_BROADCAST:
818 memset(&mreq, 0, sizeof(mreq));
819 mreq.imr_ifindex = iface->ifindex;
820 if (setsockopt(iface->fd, IPPROTO_IP0, IP_MULTICAST_IF9,
821 &mreq, sizeof(mreq)) == -1) {
822 log_warn("if_set_mcast: error setting "
823 "IP_MULTICAST_IF, interface %s", iface->name);
824 return (-1);
825 }
826 break;
827 case IF_TYPE_POINTOMULTIPOINT:
828 case IF_TYPE_VIRTUALLINK:
829 case IF_TYPE_NBMA:
830 log_debug("if_set_mcast: type %s not supported, interface %s",
831 if_type_name(iface->type), iface->name);
832 return (-1);
833 default:
834 fatalx("if_set_mcast: unknown interface type");
835 }
836
837 return (0);
838}
839
840int
841if_set_mcast_loop(int fd)
842{
843 u_int8_t loop = 0;
844
845 if (setsockopt(fd, IPPROTO_IP0, IP_MULTICAST_LOOP11,
846 (char *)&loop, sizeof(loop)) == -1) {
847 log_warn("if_set_mcast_loop: error setting IP_MULTICAST_LOOP");
848 return (-1);
849 }
850
851 return (0);
852}
853
854int
855if_set_ip_hdrincl(int fd)
856{
857 int hincl = 1;
858
859 if (setsockopt(fd, IPPROTO_IP0, IP_HDRINCL2, &hincl, sizeof(hincl)) == -1) {
860 log_warn("if_set_ip_hdrincl: error setting IP_HDRINCL");
861 return (-1);
862 }
863
864 return (0);
865}