Bug Summary

File:src/usr.sbin/ospfd/interface.c
Warning:line 771, column 26
Use of memory after it is freed

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_RST:' at line 121
115 case IF_ACT_STRT:
116 ret = if_act_start(iface);
117 break;
118 case IF_ACT_ELECT:
119 ret = if_act_elect(iface);
120 break;
121 case IF_ACT_RST:
122 ret = if_act_reset(iface);
10
Calling 'if_act_reset'
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))
{
415 if (nbr->priority == 0 || nbr == dr || /* not electable */
416 nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004) || /* not available */
417 nbr->dr.s_addr == nbr->addr.s_addr) /* don't elect DR */
418 continue;
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))
{
438 if (nbr->priority == 0 || nbr->state & NBR_STA_PRELIM(0x0001 | 0x0002 | 0x0004) ||
439 (nbr != dr && nbr->dr.s_addr != nbr->addr.s_addr))
440 /* only DR may be elected check priority too */
441 continue;
442 if (dr == NULL((void*)0))
443 dr = nbr;
444 else
445 dr = if_elect(dr, nbr);
446 }
447
448 if (dr == NULL((void*)0)) {
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 == 0 &&
459 ((iface->self == dr && iface->self != iface->dr) ||
460 (iface->self != dr && iface->self == iface->dr) ||
461 (iface->self == bdr && iface->self != iface->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;
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) {
11
Assuming field 'passive' is 0
12
Taking false branch
539 /* for an update of stub network entries */
540 orig_rtr_lsa(iface->area);
541 return (0);
542 }
543
544 switch (iface->type) {
13
Control jumps to 'case IF_TYPE_POINTOPOINT:' at line 545
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);
14
Calling 'if_leave_group'
32
Returning; memory was released
550 if (iface->state & IF_STA_DRORBDR(0x40 | 0x20)) {
33
Assuming the condition is true
34
Taking true branch
551 inet_aton(AllDRouters"224.0.0.6", &addr);
552 if_leave_group(iface, &addr);
35
Calling 'if_leave_group'
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) {
15
Control jumps to 'case IF_TYPE_POINTOPOINT:' at line 768
36
Control jumps to 'case IF_TYPE_POINTOPOINT:' at line 768
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))
16
Assuming 'ifg' is not equal to null
17
Loop condition is true. Entering loop body
37
Loop condition is true. Entering loop body
771 if (iface->ifindex == ifg->ifindex &&
18
Assuming 'iface->ifindex' is equal to 'ifg->ifindex'
20
Taking true branch
38
Use of memory after it is freed
772 addr->s_addr == ifg->addr.s_addr)
19
Assuming 'addr->s_addr' is equal to 'ifg->addr.s_addr'
773 break;
21
Execution continues on line 776
774
775 /* if interface is not found just try to drop membership */
776 if (ifg
21.1
'ifg' is non-null
) {
22
Taking true branch
777 if (--ifg->count != 0)
23
Assuming the condition is false
24
Taking false branch
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)
;
25
Assuming field 'le_next' is equal to null
26
Taking false branch
27
Loop condition is false. Exiting loop
782 free(ifg);
28
Memory is released
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,
29
Assuming the condition is false
30
Taking false branch
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;
31
Execution continues on line 807
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}