Bug Summary

File:src/usr.sbin/eigrpd/interface.c
Warning:line 240, column 7
Use of memory after it is freed

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 interface.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/eigrpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/eigrpd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/eigrpd/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/eigrpd/interface.c
1/* $OpenBSD: interface.c,v 1.26 2023/03/08 04:43:13 guenther Exp $ */
2
3/*
4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004, 2005 Esben Norby <norby@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/ioctl.h>
24#include <arpa/inet.h>
25
26#include <ctype.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31#include "eigrpd.h"
32#include "eigrpe.h"
33#include "log.h"
34
35static __inline int iface_id_compare(struct eigrp_iface *,
36 struct eigrp_iface *);
37static struct iface *if_new(struct eigrpd_conf *, struct kif *);
38static void if_del(struct iface *);
39static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *);
40static void eigrp_if_start(struct eigrp_iface *);
41static void eigrp_if_reset(struct eigrp_iface *);
42static void eigrp_if_hello_timer(int, short, void *);
43static void eigrp_if_start_hello_timer(struct eigrp_iface *);
44static void eigrp_if_stop_hello_timer(struct eigrp_iface *);
45static int if_join_ipv4_group(struct iface *, struct in_addr *);
46static int if_leave_ipv4_group(struct iface *, struct in_addr *);
47static int if_join_ipv6_group(struct iface *, struct in6_addr *);
48static int if_leave_ipv6_group(struct iface *, struct in6_addr *);
49
50RB_GENERATE(iface_id_head, eigrp_iface, id_tree, iface_id_compare)void iface_id_head_RB_INSERT_COLOR(struct iface_id_head *head
, struct eigrp_iface *elm) { struct eigrp_iface *parent, *gparent
, *tmp; while ((parent = (elm)->id_tree.rbe_parent) &&
(parent)->id_tree.rbe_color == 1) { gparent = (parent)->
id_tree.rbe_parent; if (parent == (gparent)->id_tree.rbe_left
) { tmp = (gparent)->id_tree.rbe_right; if (tmp &&
(tmp)->id_tree.rbe_color == 1) { (tmp)->id_tree.rbe_color
= 0; do { (parent)->id_tree.rbe_color = 0; (gparent)->
id_tree.rbe_color = 1; } while (0); elm = gparent; continue; }
if ((parent)->id_tree.rbe_right == elm) { do { (tmp) = (parent
)->id_tree.rbe_right; if (((parent)->id_tree.rbe_right =
(tmp)->id_tree.rbe_left)) { ((tmp)->id_tree.rbe_left)->
id_tree.rbe_parent = (parent); } do {} while (0); if (((tmp)->
id_tree.rbe_parent = (parent)->id_tree.rbe_parent)) { if (
(parent) == ((parent)->id_tree.rbe_parent)->id_tree.rbe_left
) ((parent)->id_tree.rbe_parent)->id_tree.rbe_left = (tmp
); else ((parent)->id_tree.rbe_parent)->id_tree.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->id_tree
.rbe_left = (parent); (parent)->id_tree.rbe_parent = (tmp)
; do {} while (0); if (((tmp)->id_tree.rbe_parent)) do {} while
(0); } while (0); tmp = parent; parent = elm; elm = tmp; } do
{ (parent)->id_tree.rbe_color = 0; (gparent)->id_tree.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->id_tree
.rbe_left; if (((gparent)->id_tree.rbe_left = (tmp)->id_tree
.rbe_right)) { ((tmp)->id_tree.rbe_right)->id_tree.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->id_tree.rbe_parent
= (gparent)->id_tree.rbe_parent)) { if ((gparent) == ((gparent
)->id_tree.rbe_parent)->id_tree.rbe_left) ((gparent)->
id_tree.rbe_parent)->id_tree.rbe_left = (tmp); else ((gparent
)->id_tree.rbe_parent)->id_tree.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->id_tree.rbe_right = (
gparent); (gparent)->id_tree.rbe_parent = (tmp); do {} while
(0); if (((tmp)->id_tree.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->id_tree.rbe_left; if (tmp &&
(tmp)->id_tree.rbe_color == 1) { (tmp)->id_tree.rbe_color
= 0; do { (parent)->id_tree.rbe_color = 0; (gparent)->
id_tree.rbe_color = 1; } while (0); elm = gparent; continue; }
if ((parent)->id_tree.rbe_left == elm) { do { (tmp) = (parent
)->id_tree.rbe_left; if (((parent)->id_tree.rbe_left = (
tmp)->id_tree.rbe_right)) { ((tmp)->id_tree.rbe_right)->
id_tree.rbe_parent = (parent); } do {} while (0); if (((tmp)->
id_tree.rbe_parent = (parent)->id_tree.rbe_parent)) { if (
(parent) == ((parent)->id_tree.rbe_parent)->id_tree.rbe_left
) ((parent)->id_tree.rbe_parent)->id_tree.rbe_left = (tmp
); else ((parent)->id_tree.rbe_parent)->id_tree.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->id_tree
.rbe_right = (parent); (parent)->id_tree.rbe_parent = (tmp
); do {} while (0); if (((tmp)->id_tree.rbe_parent)) do {}
while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->id_tree.rbe_color = 0; (gparent)->id_tree
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->id_tree
.rbe_right; if (((gparent)->id_tree.rbe_right = (tmp)->
id_tree.rbe_left)) { ((tmp)->id_tree.rbe_left)->id_tree
.rbe_parent = (gparent); } do {} while (0); if (((tmp)->id_tree
.rbe_parent = (gparent)->id_tree.rbe_parent)) { if ((gparent
) == ((gparent)->id_tree.rbe_parent)->id_tree.rbe_left)
((gparent)->id_tree.rbe_parent)->id_tree.rbe_left = (tmp
); else ((gparent)->id_tree.rbe_parent)->id_tree.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->id_tree
.rbe_left = (gparent); (gparent)->id_tree.rbe_parent = (tmp
); do {} while (0); if (((tmp)->id_tree.rbe_parent)) do {}
while (0); } while (0); } } (head->rbh_root)->id_tree.
rbe_color = 0; } void iface_id_head_RB_REMOVE_COLOR(struct iface_id_head
*head, struct eigrp_iface *parent, struct eigrp_iface *elm) {
struct eigrp_iface *tmp; while ((elm == ((void *)0) || (elm)
->id_tree.rbe_color == 0) && elm != (head)->rbh_root
) { if ((parent)->id_tree.rbe_left == elm) { tmp = (parent
)->id_tree.rbe_right; if ((tmp)->id_tree.rbe_color == 1
) { do { (tmp)->id_tree.rbe_color = 0; (parent)->id_tree
.rbe_color = 1; } while (0); do { (tmp) = (parent)->id_tree
.rbe_right; if (((parent)->id_tree.rbe_right = (tmp)->id_tree
.rbe_left)) { ((tmp)->id_tree.rbe_left)->id_tree.rbe_parent
= (parent); } do {} while (0); if (((tmp)->id_tree.rbe_parent
= (parent)->id_tree.rbe_parent)) { if ((parent) == ((parent
)->id_tree.rbe_parent)->id_tree.rbe_left) ((parent)->
id_tree.rbe_parent)->id_tree.rbe_left = (tmp); else ((parent
)->id_tree.rbe_parent)->id_tree.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->id_tree.rbe_left = (parent
); (parent)->id_tree.rbe_parent = (tmp); do {} while (0); if
(((tmp)->id_tree.rbe_parent)) do {} while (0); } while (0
); tmp = (parent)->id_tree.rbe_right; } if (((tmp)->id_tree
.rbe_left == ((void *)0) || ((tmp)->id_tree.rbe_left)->
id_tree.rbe_color == 0) && ((tmp)->id_tree.rbe_right
== ((void *)0) || ((tmp)->id_tree.rbe_right)->id_tree.
rbe_color == 0)) { (tmp)->id_tree.rbe_color = 1; elm = parent
; parent = (elm)->id_tree.rbe_parent; } else { if ((tmp)->
id_tree.rbe_right == ((void *)0) || ((tmp)->id_tree.rbe_right
)->id_tree.rbe_color == 0) { struct eigrp_iface *oleft; if
((oleft = (tmp)->id_tree.rbe_left)) (oleft)->id_tree.rbe_color
= 0; (tmp)->id_tree.rbe_color = 1; do { (oleft) = (tmp)->
id_tree.rbe_left; if (((tmp)->id_tree.rbe_left = (oleft)->
id_tree.rbe_right)) { ((oleft)->id_tree.rbe_right)->id_tree
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->id_tree
.rbe_parent = (tmp)->id_tree.rbe_parent)) { if ((tmp) == (
(tmp)->id_tree.rbe_parent)->id_tree.rbe_left) ((tmp)->
id_tree.rbe_parent)->id_tree.rbe_left = (oleft); else ((tmp
)->id_tree.rbe_parent)->id_tree.rbe_right = (oleft); } else
(head)->rbh_root = (oleft); (oleft)->id_tree.rbe_right
= (tmp); (tmp)->id_tree.rbe_parent = (oleft); do {} while
(0); if (((oleft)->id_tree.rbe_parent)) do {} while (0); }
while (0); tmp = (parent)->id_tree.rbe_right; } (tmp)->
id_tree.rbe_color = (parent)->id_tree.rbe_color; (parent)->
id_tree.rbe_color = 0; if ((tmp)->id_tree.rbe_right) ((tmp
)->id_tree.rbe_right)->id_tree.rbe_color = 0; do { (tmp
) = (parent)->id_tree.rbe_right; if (((parent)->id_tree
.rbe_right = (tmp)->id_tree.rbe_left)) { ((tmp)->id_tree
.rbe_left)->id_tree.rbe_parent = (parent); } do {} while (
0); if (((tmp)->id_tree.rbe_parent = (parent)->id_tree.
rbe_parent)) { if ((parent) == ((parent)->id_tree.rbe_parent
)->id_tree.rbe_left) ((parent)->id_tree.rbe_parent)->
id_tree.rbe_left = (tmp); else ((parent)->id_tree.rbe_parent
)->id_tree.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->id_tree.rbe_left = (parent); (parent)->id_tree
.rbe_parent = (tmp); do {} while (0); if (((tmp)->id_tree.
rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root
; break; } } else { tmp = (parent)->id_tree.rbe_left; if (
(tmp)->id_tree.rbe_color == 1) { do { (tmp)->id_tree.rbe_color
= 0; (parent)->id_tree.rbe_color = 1; } while (0); do { (
tmp) = (parent)->id_tree.rbe_left; if (((parent)->id_tree
.rbe_left = (tmp)->id_tree.rbe_right)) { ((tmp)->id_tree
.rbe_right)->id_tree.rbe_parent = (parent); } do {} while (
0); if (((tmp)->id_tree.rbe_parent = (parent)->id_tree.
rbe_parent)) { if ((parent) == ((parent)->id_tree.rbe_parent
)->id_tree.rbe_left) ((parent)->id_tree.rbe_parent)->
id_tree.rbe_left = (tmp); else ((parent)->id_tree.rbe_parent
)->id_tree.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->id_tree.rbe_right = (parent); (parent)->
id_tree.rbe_parent = (tmp); do {} while (0); if (((tmp)->id_tree
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
id_tree.rbe_left; } if (((tmp)->id_tree.rbe_left == ((void
*)0) || ((tmp)->id_tree.rbe_left)->id_tree.rbe_color ==
0) && ((tmp)->id_tree.rbe_right == ((void *)0) ||
((tmp)->id_tree.rbe_right)->id_tree.rbe_color == 0)) {
(tmp)->id_tree.rbe_color = 1; elm = parent; parent = (elm
)->id_tree.rbe_parent; } else { if ((tmp)->id_tree.rbe_left
== ((void *)0) || ((tmp)->id_tree.rbe_left)->id_tree.rbe_color
== 0) { struct eigrp_iface *oright; if ((oright = (tmp)->
id_tree.rbe_right)) (oright)->id_tree.rbe_color = 0; (tmp)
->id_tree.rbe_color = 1; do { (oright) = (tmp)->id_tree
.rbe_right; if (((tmp)->id_tree.rbe_right = (oright)->id_tree
.rbe_left)) { ((oright)->id_tree.rbe_left)->id_tree.rbe_parent
= (tmp); } do {} while (0); if (((oright)->id_tree.rbe_parent
= (tmp)->id_tree.rbe_parent)) { if ((tmp) == ((tmp)->id_tree
.rbe_parent)->id_tree.rbe_left) ((tmp)->id_tree.rbe_parent
)->id_tree.rbe_left = (oright); else ((tmp)->id_tree.rbe_parent
)->id_tree.rbe_right = (oright); } else (head)->rbh_root
= (oright); (oright)->id_tree.rbe_left = (tmp); (tmp)->
id_tree.rbe_parent = (oright); do {} while (0); if (((oright)
->id_tree.rbe_parent)) do {} while (0); } while (0); tmp =
(parent)->id_tree.rbe_left; } (tmp)->id_tree.rbe_color
= (parent)->id_tree.rbe_color; (parent)->id_tree.rbe_color
= 0; if ((tmp)->id_tree.rbe_left) ((tmp)->id_tree.rbe_left
)->id_tree.rbe_color = 0; do { (tmp) = (parent)->id_tree
.rbe_left; if (((parent)->id_tree.rbe_left = (tmp)->id_tree
.rbe_right)) { ((tmp)->id_tree.rbe_right)->id_tree.rbe_parent
= (parent); } do {} while (0); if (((tmp)->id_tree.rbe_parent
= (parent)->id_tree.rbe_parent)) { if ((parent) == ((parent
)->id_tree.rbe_parent)->id_tree.rbe_left) ((parent)->
id_tree.rbe_parent)->id_tree.rbe_left = (tmp); else ((parent
)->id_tree.rbe_parent)->id_tree.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->id_tree.rbe_right = (
parent); (parent)->id_tree.rbe_parent = (tmp); do {} while
(0); if (((tmp)->id_tree.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
id_tree.rbe_color = 0; } struct eigrp_iface * iface_id_head_RB_REMOVE
(struct iface_id_head *head, struct eigrp_iface *elm) { struct
eigrp_iface *child, *parent, *old = elm; int color; if ((elm
)->id_tree.rbe_left == ((void *)0)) child = (elm)->id_tree
.rbe_right; else if ((elm)->id_tree.rbe_right == ((void *)
0)) child = (elm)->id_tree.rbe_left; else { struct eigrp_iface
*left; elm = (elm)->id_tree.rbe_right; while ((left = (elm
)->id_tree.rbe_left)) elm = left; child = (elm)->id_tree
.rbe_right; parent = (elm)->id_tree.rbe_parent; color = (elm
)->id_tree.rbe_color; if (child) (child)->id_tree.rbe_parent
= parent; if (parent) { if ((parent)->id_tree.rbe_left ==
elm) (parent)->id_tree.rbe_left = child; else (parent)->
id_tree.rbe_right = child; do {} while (0); } else (head)->
rbh_root = child; if ((elm)->id_tree.rbe_parent == old) parent
= elm; (elm)->id_tree = (old)->id_tree; if ((old)->
id_tree.rbe_parent) { if (((old)->id_tree.rbe_parent)->
id_tree.rbe_left == old) ((old)->id_tree.rbe_parent)->id_tree
.rbe_left = elm; else ((old)->id_tree.rbe_parent)->id_tree
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; ((old)->id_tree.rbe_left)->id_tree.rbe_parent =
elm; if ((old)->id_tree.rbe_right) ((old)->id_tree.rbe_right
)->id_tree.rbe_parent = elm; if (parent) { left = parent; do
{ do {} while (0); } while ((left = (left)->id_tree.rbe_parent
)); } goto color; } parent = (elm)->id_tree.rbe_parent; color
= (elm)->id_tree.rbe_color; if (child) (child)->id_tree
.rbe_parent = parent; if (parent) { if ((parent)->id_tree.
rbe_left == elm) (parent)->id_tree.rbe_left = child; else (
parent)->id_tree.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) iface_id_head_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct eigrp_iface * iface_id_head_RB_INSERT
(struct iface_id_head *head, struct eigrp_iface *elm) { struct
eigrp_iface *tmp; struct eigrp_iface *parent = ((void *)0); int
comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp
; comp = (iface_id_compare)(elm, parent); if (comp < 0) tmp
= (tmp)->id_tree.rbe_left; else if (comp > 0) tmp = (tmp
)->id_tree.rbe_right; else return (tmp); } do { (elm)->
id_tree.rbe_parent = parent; (elm)->id_tree.rbe_left = (elm
)->id_tree.rbe_right = ((void *)0); (elm)->id_tree.rbe_color
= 1; } while (0); if (parent != ((void *)0)) { if (comp <
0) (parent)->id_tree.rbe_left = elm; else (parent)->id_tree
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; iface_id_head_RB_INSERT_COLOR(head, elm); return (((void
*)0)); } struct eigrp_iface * iface_id_head_RB_FIND(struct iface_id_head
*head, struct eigrp_iface *elm) { struct eigrp_iface *tmp = (
head)->rbh_root; int comp; while (tmp) { comp = iface_id_compare
(elm, tmp); if (comp < 0) tmp = (tmp)->id_tree.rbe_left
; else if (comp > 0) tmp = (tmp)->id_tree.rbe_right; else
return (tmp); } return (((void *)0)); } struct eigrp_iface *
iface_id_head_RB_NFIND(struct iface_id_head *head, struct eigrp_iface
*elm) { struct eigrp_iface *tmp = (head)->rbh_root; struct
eigrp_iface *res = ((void *)0); int comp; while (tmp) { comp
= iface_id_compare(elm, tmp); if (comp < 0) { res = tmp; tmp
= (tmp)->id_tree.rbe_left; } else if (comp > 0) tmp = (
tmp)->id_tree.rbe_right; else return (tmp); } return (res)
; } struct eigrp_iface * iface_id_head_RB_NEXT(struct eigrp_iface
*elm) { if ((elm)->id_tree.rbe_right) { elm = (elm)->id_tree
.rbe_right; while ((elm)->id_tree.rbe_left) elm = (elm)->
id_tree.rbe_left; } else { if ((elm)->id_tree.rbe_parent &&
(elm == ((elm)->id_tree.rbe_parent)->id_tree.rbe_left)
) elm = (elm)->id_tree.rbe_parent; else { while ((elm)->
id_tree.rbe_parent && (elm == ((elm)->id_tree.rbe_parent
)->id_tree.rbe_right)) elm = (elm)->id_tree.rbe_parent;
elm = (elm)->id_tree.rbe_parent; } } return (elm); } struct
eigrp_iface * iface_id_head_RB_PREV(struct eigrp_iface *elm)
{ if ((elm)->id_tree.rbe_left) { elm = (elm)->id_tree.
rbe_left; while ((elm)->id_tree.rbe_right) elm = (elm)->
id_tree.rbe_right; } else { if ((elm)->id_tree.rbe_parent &&
(elm == ((elm)->id_tree.rbe_parent)->id_tree.rbe_right
)) elm = (elm)->id_tree.rbe_parent; else { while ((elm)->
id_tree.rbe_parent && (elm == ((elm)->id_tree.rbe_parent
)->id_tree.rbe_left)) elm = (elm)->id_tree.rbe_parent; elm
= (elm)->id_tree.rbe_parent; } } return (elm); } struct eigrp_iface
* iface_id_head_RB_MINMAX(struct iface_id_head *head, int val
) { struct eigrp_iface *tmp = (head)->rbh_root; struct eigrp_iface
*parent = ((void *)0); while (tmp) { parent = tmp; if (val <
0) tmp = (tmp)->id_tree.rbe_left; else tmp = (tmp)->id_tree
.rbe_right; } return (parent); }
51
52struct iface_id_head ifaces_by_id = RB_INITIALIZER(&ifaces_by_id){ ((void *)0) };
53
54static __inline int
55iface_id_compare(struct eigrp_iface *a, struct eigrp_iface *b)
56{
57 return (a->ifaceid - b->ifaceid);
58}
59
60static struct iface *
61if_new(struct eigrpd_conf *xconf, struct kif *kif)
62{
63 struct iface *iface;
64
65 if ((iface = calloc(1, sizeof(*iface))) == NULL((void *)0))
66 fatal("if_new: calloc");
67
68 TAILQ_INIT(&iface->ei_list)do { (&iface->ei_list)->tqh_first = ((void *)0); (&
iface->ei_list)->tqh_last = &(&iface->ei_list
)->tqh_first; } while (0)
;
69 TAILQ_INIT(&iface->addr_list)do { (&iface->addr_list)->tqh_first = ((void *)0); (
&iface->addr_list)->tqh_last = &(&iface->
addr_list)->tqh_first; } while (0)
;
70
71 strlcpy(iface->name, kif->ifname, sizeof(iface->name));
72
73 /* get type */
74 if (kif->flags & IFF_POINTOPOINT0x10)
75 iface->type = IF_TYPE_POINTOPOINT;
76 if (kif->flags & IFF_BROADCAST0x2 &&
77 kif->flags & IFF_MULTICAST0x8000)
78 iface->type = IF_TYPE_BROADCAST;
79 if (kif->flags & IFF_LOOPBACK0x8)
80 iface->type = IF_TYPE_POINTOPOINT;
81
82 /* get index and flags */
83 iface->mtu = kif->mtu;
84 iface->ifindex = kif->ifindex;
85 iface->rdomain = kif->rdomain;
86 iface->flags = kif->flags;
87 iface->linkstate = kif->link_state;
88 iface->if_type = kif->if_type;
89 iface->baudrate = kif->baudrate;
90
91 TAILQ_INSERT_TAIL(&xconf->iface_list, iface, entry)do { (iface)->entry.tqe_next = ((void *)0); (iface)->entry
.tqe_prev = (&xconf->iface_list)->tqh_last; *(&
xconf->iface_list)->tqh_last = (iface); (&xconf->
iface_list)->tqh_last = &(iface)->entry.tqe_next; }
while (0)
;
92
93 return (iface);
94}
95
96static void
97if_del(struct iface *iface)
98{
99 struct if_addr *if_addr;
100
101 log_debug("%s: interface %s", __func__, iface->name);
102
103 while ((if_addr = TAILQ_FIRST(&iface->addr_list)((&iface->addr_list)->tqh_first)) != NULL((void *)0)) {
104 TAILQ_REMOVE(&iface->addr_list, if_addr, entry)do { if (((if_addr)->entry.tqe_next) != ((void *)0)) (if_addr
)->entry.tqe_next->entry.tqe_prev = (if_addr)->entry
.tqe_prev; else (&iface->addr_list)->tqh_last = (if_addr
)->entry.tqe_prev; *(if_addr)->entry.tqe_prev = (if_addr
)->entry.tqe_next; ; ; } while (0)
;
105 free(if_addr);
106 }
107
108 TAILQ_REMOVE(&econf->iface_list, iface, entry)do { if (((iface)->entry.tqe_next) != ((void *)0)) (iface)
->entry.tqe_next->entry.tqe_prev = (iface)->entry.tqe_prev
; else (&econf->iface_list)->tqh_last = (iface)->
entry.tqe_prev; *(iface)->entry.tqe_prev = (iface)->entry
.tqe_next; ; ; } while (0)
;
109 free(iface);
110}
111
112struct iface *
113if_lookup(struct eigrpd_conf *xconf, unsigned int ifindex)
114{
115 struct iface *iface;
116
117 TAILQ_FOREACH(iface, &xconf->iface_list, entry)for((iface) = ((&xconf->iface_list)->tqh_first); (iface
) != ((void *)0); (iface) = ((iface)->entry.tqe_next))
118 if (iface->ifindex == ifindex)
119 return (iface);
120
121 return (NULL((void *)0));
122}
123
124void
125if_addr_new(struct iface *iface, struct kaddr *ka)
126{
127 struct if_addr *if_addr;
128 struct eigrp_iface *ei;
129
130 if (ka->af == AF_INET624 && IN6_IS_ADDR_LINKLOCAL(&ka->addr.v6)(((&ka->addr.v6)->__u6_addr.__u6_addr8[0] == 0xfe) &&
(((&ka->addr.v6)->__u6_addr.__u6_addr8[1] & 0xc0
) == 0x80))
) {
131 iface->linklocal = ka->addr.v6;
132 if_update(iface, AF_INET624);
133 return;
134 }
135
136 if (if_addr_lookup(&iface->addr_list, ka) != NULL((void *)0))
137 return;
138
139 if ((if_addr = calloc(1, sizeof(*if_addr))) == NULL((void *)0))
140 fatal("if_addr_new: calloc");
141 if_addr->af = ka->af;
142 if_addr->addr = ka->addr;
143 if_addr->prefixlen = ka->prefixlen;
144 if_addr->dstbrd = ka->dstbrd;
145 TAILQ_INSERT_TAIL(&iface->addr_list, if_addr, entry)do { (if_addr)->entry.tqe_next = ((void *)0); (if_addr)->
entry.tqe_prev = (&iface->addr_list)->tqh_last; *(&
iface->addr_list)->tqh_last = (if_addr); (&iface->
addr_list)->tqh_last = &(if_addr)->entry.tqe_next; }
while (0)
;
146
147 TAILQ_FOREACH(ei, &iface->ei_list, i_entry)for((ei) = ((&iface->ei_list)->tqh_first); (ei) != (
(void *)0); (ei) = ((ei)->i_entry.tqe_next))
148 if (ei->state == IF_STA_ACTIVE0x02 && ei->eigrp->af == if_addr->af)
149 eigrpe_orig_local_route(ei, if_addr, 0);
150
151 if (if_addr->af == AF_INET2)
152 if_update(iface, AF_INET2);
153}
154
155void
156if_addr_del(struct iface *iface, struct kaddr *ka)
157{
158 struct if_addr *if_addr;
159 struct eigrp_iface *ei;
160 int af = ka->af;
161
162 if (ka->af == AF_INET624 &&
1
Assuming field 'af' is not equal to AF_INET6
163 IN6_ARE_ADDR_EQUAL(&iface->linklocal, &ka->addr.v6)(memcmp(&(&iface->linklocal)->__u6_addr.__u6_addr8
[0], &(&ka->addr.v6)->__u6_addr.__u6_addr8[0], sizeof
(struct in6_addr)) == 0)
) {
164 memset(&iface->linklocal, 0, sizeof(iface->linklocal));
165 if_update(iface, AF_INET624);
166 return;
167 }
168
169 if_addr = if_addr_lookup(&iface->addr_list, ka);
2
Calling 'if_addr_lookup'
8
Returning from 'if_addr_lookup'
170 if (if_addr
8.1
'if_addr' is not equal to NULL
== NULL((void *)0))
9
Taking false branch
171 return;
172
173 TAILQ_FOREACH(ei, &iface->ei_list, i_entry)for((ei) = ((&iface->ei_list)->tqh_first); (ei) != (
(void *)0); (ei) = ((ei)->i_entry.tqe_next))
10
Assuming 'ei' is equal to null
11
Loop condition is false. Execution continues on line 177
174 if (ei->state == IF_STA_ACTIVE0x02 && ei->eigrp->af == if_addr->af)
175 eigrpe_orig_local_route(ei, if_addr, 1);
176
177 TAILQ_REMOVE(&iface->addr_list, if_addr, entry)do { if (((if_addr)->entry.tqe_next) != ((void *)0)) (if_addr
)->entry.tqe_next->entry.tqe_prev = (if_addr)->entry
.tqe_prev; else (&iface->addr_list)->tqh_last = (if_addr
)->entry.tqe_prev; *(if_addr)->entry.tqe_prev = (if_addr
)->entry.tqe_next; ; ; } while (0)
;
12
Assuming field 'tqe_next' is equal to null
13
Taking false branch
14
Loop condition is false. Exiting loop
178 free(if_addr);
15
Memory is released
179
180 if (af == AF_INET2)
16
Assuming 'af' is equal to AF_INET
17
Taking true branch
181 if_update(iface, AF_INET2);
18
Calling 'if_update'
182}
183
184static struct if_addr *
185if_addr_lookup(struct if_addr_head *addr_list, struct kaddr *ka)
186{
187 struct if_addr *if_addr;
188 int af = ka->af;
189
190 TAILQ_FOREACH(if_addr, addr_list, entry)for((if_addr) = ((addr_list)->tqh_first); (if_addr) != ((void
*)0); (if_addr) = ((if_addr)->entry.tqe_next))
3
Assuming 'if_addr' is not equal to null
191 if (!eigrp_addrcmp(af, &if_addr->addr, &ka->addr) &&
4
Assuming the condition is true
7
Taking true branch
192 if_addr->prefixlen == ka->prefixlen &&
5
Assuming 'if_addr->prefixlen' is equal to 'ka->prefixlen'
193 !eigrp_addrcmp(af, &if_addr->dstbrd, &ka->dstbrd))
6
Assuming the condition is true
194 return (if_addr);
195
196 return (NULL((void *)0));
197}
198
199in_addr_t
200if_primary_addr(struct iface *iface)
201{
202 struct if_addr *if_addr;
203
204 TAILQ_FOREACH(if_addr, &iface->addr_list, entry)for((if_addr) = ((&iface->addr_list)->tqh_first); (
if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry.tqe_next
))
205 if (if_addr->af == AF_INET2)
206 return (if_addr->addr.v4.s_addr);
207
208 return (INADDR_ANY((u_int32_t)(0x00000000)));
209}
210
211uint8_t
212if_primary_addr_prefixlen(struct iface *iface)
213{
214 struct if_addr *if_addr;
215
216 TAILQ_FOREACH(if_addr, &iface->addr_list, entry)for((if_addr) = ((&iface->addr_list)->tqh_first); (
if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry.tqe_next
))
217 if (if_addr->af == AF_INET2)
218 return (if_addr->prefixlen);
219
220 return (0);
221}
222
223/* up/down events */
224void
225if_update(struct iface *iface, int af)
226{
227 struct eigrp_iface *ei;
228 int link_ok;
229 int addr_ok, addr4_ok = 0, addr6_ok = 0;
230 struct if_addr *if_addr;
231
232 link_ok = (iface->flags & IFF_UP0x1) &&
19
Assuming the condition is false
233 LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0);
234
235 /*
236 * NOTE: for EIGRPv4, each interface should have at least one valid
237 * IP address otherwise they can not be enabled in the routing domain.
238 */
239 TAILQ_FOREACH(if_addr, &iface->addr_list, entry)for((if_addr) = ((&iface->addr_list)->tqh_first); (
if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry.tqe_next
))
{
20
Loop condition is true. Entering loop body
240 if (if_addr->af == AF_INET2) {
21
Use of memory after it is freed
241 addr4_ok = 1;
242 break;
243 }
244 }
245 /* for IPv6 the link-local address is enough. */
246 if (IN6_IS_ADDR_LINKLOCAL(&iface->linklocal)(((&iface->linklocal)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&iface->linklocal)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
)
247 addr6_ok = 1;
248
249 TAILQ_FOREACH(ei, &iface->ei_list, i_entry)for((ei) = ((&iface->ei_list)->tqh_first); (ei) != (
(void *)0); (ei) = ((ei)->i_entry.tqe_next))
{
250 if (af != AF_UNSPEC0 && ei->eigrp->af != af)
251 continue;
252
253 switch (ei->eigrp->af) {
254 case AF_INET2:
255 addr_ok = addr4_ok;
256 break;
257 case AF_INET624:
258 addr_ok = addr6_ok;
259 break;
260 default:
261 fatalx("if_update: unknown af");
262 }
263
264 if (ei->state == IF_STA_DOWN0x01) {
265 if (!link_ok || !addr_ok)
266 continue;
267 ei->state = IF_STA_ACTIVE0x02;
268 eigrp_if_start(ei);
269 } else if (ei->state == IF_STA_ACTIVE0x02) {
270 if (link_ok && addr_ok)
271 continue;
272 ei->state = IF_STA_DOWN0x01;
273 eigrp_if_reset(ei);
274 }
275 }
276}
277
278struct eigrp_iface *
279eigrp_if_new(struct eigrpd_conf *xconf, struct eigrp *eigrp, struct kif *kif)
280{
281 struct iface *iface;
282 struct eigrp_iface *ei;
283 static uint32_t ifacecnt = 1;
284
285 iface = if_lookup(xconf, kif->ifindex);
286 if (iface == NULL((void *)0))
287 iface = if_new(xconf, kif);
288
289 if ((ei = calloc(1, sizeof(*ei))) == NULL((void *)0))
290 fatal("eigrp_if_new: calloc");
291
292 ei->state = IF_STA_DOWN0x01;
293 /* get next unused ifaceid */
294 while (eigrp_if_lookup_id(ifacecnt++))
295 ;
296 ei->ifaceid = ifacecnt;
297 ei->eigrp = eigrp;
298 ei->iface = iface;
299 if (ei->iface->flags & IFF_LOOPBACK0x8)
300 ei->passive = 1;
301
302 TAILQ_INIT(&ei->nbr_list)do { (&ei->nbr_list)->tqh_first = ((void *)0); (&
ei->nbr_list)->tqh_last = &(&ei->nbr_list)->
tqh_first; } while (0)
;
303 TAILQ_INIT(&ei->update_list)do { (&ei->update_list)->tqh_first = ((void *)0); (
&ei->update_list)->tqh_last = &(&ei->update_list
)->tqh_first; } while (0)
;
304 TAILQ_INIT(&ei->query_list)do { (&ei->query_list)->tqh_first = ((void *)0); (&
ei->query_list)->tqh_last = &(&ei->query_list
)->tqh_first; } while (0)
;
305 TAILQ_INIT(&ei->summary_list)do { (&ei->summary_list)->tqh_first = ((void *)0); (
&ei->summary_list)->tqh_last = &(&ei->summary_list
)->tqh_first; } while (0)
;
306 TAILQ_INSERT_TAIL(&iface->ei_list, ei, i_entry)do { (ei)->i_entry.tqe_next = ((void *)0); (ei)->i_entry
.tqe_prev = (&iface->ei_list)->tqh_last; *(&iface
->ei_list)->tqh_last = (ei); (&iface->ei_list)->
tqh_last = &(ei)->i_entry.tqe_next; } while (0)
;
307 TAILQ_INSERT_TAIL(&eigrp->ei_list, ei, e_entry)do { (ei)->e_entry.tqe_next = ((void *)0); (ei)->e_entry
.tqe_prev = (&eigrp->ei_list)->tqh_last; *(&eigrp
->ei_list)->tqh_last = (ei); (&eigrp->ei_list)->
tqh_last = &(ei)->e_entry.tqe_next; } while (0)
;
308 if (RB_INSERT(iface_id_head, &ifaces_by_id, ei)iface_id_head_RB_INSERT(&ifaces_by_id, ei) != NULL((void *)0))
309 fatalx("eigrp_if_new: RB_INSERT(ifaces_by_id) failed");
310
311 return (ei);
312}
313
314void
315eigrp_if_del(struct eigrp_iface *ei)
316{
317 struct summary_addr *summary;
318
319 RB_REMOVE(iface_id_head, &ifaces_by_id, ei)iface_id_head_RB_REMOVE(&ifaces_by_id, ei);
320 TAILQ_REMOVE(&ei->eigrp->ei_list, ei, e_entry)do { if (((ei)->e_entry.tqe_next) != ((void *)0)) (ei)->
e_entry.tqe_next->e_entry.tqe_prev = (ei)->e_entry.tqe_prev
; else (&ei->eigrp->ei_list)->tqh_last = (ei)->
e_entry.tqe_prev; *(ei)->e_entry.tqe_prev = (ei)->e_entry
.tqe_next; ; ; } while (0)
;
321 TAILQ_REMOVE(&ei->iface->ei_list, ei, i_entry)do { if (((ei)->i_entry.tqe_next) != ((void *)0)) (ei)->
i_entry.tqe_next->i_entry.tqe_prev = (ei)->i_entry.tqe_prev
; else (&ei->iface->ei_list)->tqh_last = (ei)->
i_entry.tqe_prev; *(ei)->i_entry.tqe_prev = (ei)->i_entry
.tqe_next; ; ; } while (0)
;
322 while ((summary = TAILQ_FIRST(&ei->summary_list)((&ei->summary_list)->tqh_first)) != NULL((void *)0)) {
323 TAILQ_REMOVE(&ei->summary_list, summary, entry)do { if (((summary)->entry.tqe_next) != ((void *)0)) (summary
)->entry.tqe_next->entry.tqe_prev = (summary)->entry
.tqe_prev; else (&ei->summary_list)->tqh_last = (summary
)->entry.tqe_prev; *(summary)->entry.tqe_prev = (summary
)->entry.tqe_next; ; ; } while (0)
;
324 free(summary);
325 }
326 message_list_clr(&ei->query_list);
327 message_list_clr(&ei->update_list);
328
329 if (ei->state == IF_STA_ACTIVE0x02)
330 eigrp_if_reset(ei);
331
332 if (TAILQ_EMPTY(&ei->iface->ei_list)(((&ei->iface->ei_list)->tqh_first) == ((void *)
0))
)
333 if_del(ei->iface);
334
335 free(ei);
336}
337
338struct eigrp_iface *
339eigrp_if_lookup(struct iface *iface, int af, uint16_t as)
340{
341 struct eigrp_iface *ei;
342
343 TAILQ_FOREACH(ei, &iface->ei_list, i_entry)for((ei) = ((&iface->ei_list)->tqh_first); (ei) != (
(void *)0); (ei) = ((ei)->i_entry.tqe_next))
344 if (ei->eigrp->af == af &&
345 ei->eigrp->as == as)
346 return (ei);
347
348 return (NULL((void *)0));
349}
350
351struct eigrp_iface *
352eigrp_if_lookup_id(uint32_t ifaceid)
353{
354 struct eigrp_iface e;
355 e.ifaceid = ifaceid;
356 return (RB_FIND(iface_id_head, &ifaces_by_id, &e)iface_id_head_RB_FIND(&ifaces_by_id, &e));
357}
358
359static void
360eigrp_if_start(struct eigrp_iface *ei)
361{
362 struct eigrp *eigrp = ei->eigrp;
363 struct timeval now;
364 struct if_addr *if_addr;
365 union eigrpd_addr addr;
366
367 log_debug("%s: %s as %u family %s", __func__, ei->iface->name,
368 eigrp->as, af_name(eigrp->af));
369
370 gettimeofday(&now, NULL((void *)0));
371 ei->uptime = now.tv_sec;
372
373 /* init the dummy self neighbor */
374 memset(&addr, 0, sizeof(addr));
375 ei->self = nbr_new(ei, &addr, 0, 1);
376 nbr_init(ei->self);
377
378 TAILQ_FOREACH(if_addr, &ei->iface->addr_list, entry)for((if_addr) = ((&ei->iface->addr_list)->tqh_first
); (if_addr) != ((void *)0); (if_addr) = ((if_addr)->entry
.tqe_next))
{
379 if (if_addr->af != eigrp->af)
380 continue;
381
382 eigrpe_orig_local_route(ei, if_addr, 0);
383 }
384
385 if (ei->passive)
386 return;
387
388 switch (eigrp->af) {
389 case AF_INET2:
390 if (if_join_ipv4_group(ei->iface, &global.mcast_addr_v4))
391 return;
392 break;
393 case AF_INET624:
394 if (if_join_ipv6_group(ei->iface, &global.mcast_addr_v6))
395 return;
396 break;
397 default:
398 fatalx("eigrp_if_start: unknown af");
399 }
400
401 evtimer_set(&ei->hello_timer, eigrp_if_hello_timer, ei)event_set(&ei->hello_timer, -1, 0, eigrp_if_hello_timer
, ei)
;
402 eigrp_if_start_hello_timer(ei);
403}
404
405static void
406eigrp_if_reset(struct eigrp_iface *ei)
407{
408 struct eigrp *eigrp = ei->eigrp;
409 struct nbr *nbr;
410
411 log_debug("%s: %s as %u family %s", __func__, ei->iface->name,
412 eigrp->as, af_name(eigrp->af));
413
414 /* the rde will withdraw the connected route for us */
415
416 while ((nbr = TAILQ_FIRST(&ei->nbr_list)((&ei->nbr_list)->tqh_first)) != NULL((void *)0))
417 nbr_del(nbr);
418
419 if (ei->passive)
420 return;
421
422 /* try to cleanup */
423 switch (eigrp->af) {
424 case AF_INET2:
425 if_leave_ipv4_group(ei->iface, &global.mcast_addr_v4);
426 break;
427 case AF_INET624:
428 if_leave_ipv6_group(ei->iface, &global.mcast_addr_v6);
429 break;
430 default:
431 fatalx("eigrp_if_reset: unknown af");
432 }
433
434 eigrp_if_stop_hello_timer(ei);
435}
436
437/* timers */
438static void
439eigrp_if_hello_timer(int fd, short event, void *arg)
440{
441 struct eigrp_iface *ei = arg;
442 struct timeval tv;
443
444 send_hello(ei, NULL((void *)0), 0);
445
446 /* reschedule hello_timer */
447 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
448 tv.tv_sec = ei->hello_interval;
449 if (evtimer_add(&ei->hello_timer, &tv)event_add(&ei->hello_timer, &tv) == -1)
450 fatal("eigrp_if_hello_timer");
451}
452
453static void
454eigrp_if_start_hello_timer(struct eigrp_iface *ei)
455{
456 struct timeval tv;
457
458 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
459 tv.tv_sec = ei->hello_interval;
460 if (evtimer_add(&ei->hello_timer, &tv)event_add(&ei->hello_timer, &tv) == -1)
461 fatal("eigrp_if_start_hello_timer");
462}
463
464static void
465eigrp_if_stop_hello_timer(struct eigrp_iface *ei)
466{
467 if (evtimer_pending(&ei->hello_timer, NULL)event_pending(&ei->hello_timer, 0x01, ((void *)0)) &&
468 evtimer_del(&ei->hello_timer)event_del(&ei->hello_timer) == -1)
469 fatal("eigrp_if_stop_hello_timer");
470}
471
472struct ctl_iface *
473if_to_ctl(struct eigrp_iface *ei)
474{
475 static struct ctl_iface ictl;
476 struct timeval now;
477 struct nbr *nbr;
478
479 ictl.af = ei->eigrp->af;
480 ictl.as = ei->eigrp->as;
481 memcpy(ictl.name, ei->iface->name, sizeof(ictl.name));
482 ictl.ifindex = ei->iface->ifindex;
483 switch (ei->eigrp->af) {
484 case AF_INET2:
485 ictl.addr.v4.s_addr = if_primary_addr(ei->iface);
486 ictl.prefixlen = if_primary_addr_prefixlen(ei->iface);
487 break;
488 case AF_INET624:
489 ictl.addr.v6 = ei->iface->linklocal;
490 if (!IN6_IS_ADDR_UNSPECIFIED(&ei->iface->linklocal)((*(const u_int32_t *)(const void *)(&(&ei->iface->
linklocal)->__u6_addr.__u6_addr8[0]) == 0) && (*(const
u_int32_t *)(const void *)(&(&ei->iface->linklocal
)->__u6_addr.__u6_addr8[4]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ei->iface->linklocal)->
__u6_addr.__u6_addr8[8]) == 0) && (*(const u_int32_t *
)(const void *)(&(&ei->iface->linklocal)->__u6_addr
.__u6_addr8[12]) == 0))
)
491 ictl.prefixlen = 64;
492 else
493 ictl.prefixlen = 0;
494 break;
495 default:
496 fatalx("if_to_ctl: unknown af");
497 }
498 ictl.flags = ei->iface->flags;
499 ictl.linkstate = ei->iface->linkstate;
500 ictl.mtu = ei->iface->mtu;
501 ictl.type = ei->iface->type;
502 ictl.if_type = ei->iface->if_type;
503 ictl.baudrate = ei->iface->baudrate;
504 ictl.delay = ei->delay;
505 ictl.bandwidth = ei->bandwidth;
506 ictl.hello_holdtime = ei->hello_holdtime;
507 ictl.hello_interval = ei->hello_interval;
508 ictl.splithorizon = ei->splithorizon;
509 ictl.passive = ei->passive;
510 ictl.nbr_cnt = 0;
511
512 gettimeofday(&now, NULL((void *)0));
513 if (ei->state != IF_STA_DOWN0x01 && ei->uptime != 0)
514 ictl.uptime = now.tv_sec - ei->uptime;
515 else
516 ictl.uptime = 0;
517
518 TAILQ_FOREACH(nbr, &ei->nbr_list, entry)for((nbr) = ((&ei->nbr_list)->tqh_first); (nbr) != (
(void *)0); (nbr) = ((nbr)->entry.tqe_next))
519 if (!(nbr->flags & (F_EIGRP_NBR_PENDING0x02|F_EIGRP_NBR_SELF0x01)))
520 ictl.nbr_cnt++;
521
522 return (&ictl);
523}
524
525/* misc */
526void
527if_set_sockbuf(int fd)
528{
529 int bsize;
530
531 bsize = 65535;
532 while (setsockopt(fd, SOL_SOCKET0xffff, SO_RCVBUF0x1002, &bsize,
533 sizeof(bsize)) == -1)
534 bsize /= 2;
535
536 if (bsize != 65535)
537 log_warnx("%s: recvbuf size only %d", __func__, bsize);
538
539 bsize = 65535;
540 while (setsockopt(fd, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize,
541 sizeof(bsize)) == -1)
542 bsize /= 2;
543
544 if (bsize != 65535)
545 log_warnx("%s: sendbuf size only %d", __func__, bsize);
546}
547
548static int
549if_join_ipv4_group(struct iface *iface, struct in_addr *addr)
550{
551 struct ip_mreq mreq;
552
553 if (iface->group_count_v4++ != 0)
554 /* already joined */
555 return (0);
556
557 log_debug("%s: interface %s addr %s", __func__, iface->name,
558 inet_ntoa(*addr));
559
560 mreq.imr_multiaddr = *addr;
561 mreq.imr_interface.s_addr = if_primary_addr(iface);
562
563 if (setsockopt(global.eigrp_socket_v4, IPPROTO_IP0, IP_ADD_MEMBERSHIP12,
564 (void *)&mreq, sizeof(mreq)) == -1) {
565 log_warn("%s: error IP_ADD_MEMBERSHIP, interface %s address %s",
566 __func__, iface->name, inet_ntoa(*addr));
567 return (-1);
568 }
569
570 return (0);
571}
572
573static int
574if_leave_ipv4_group(struct iface *iface, struct in_addr *addr)
575{
576 struct ip_mreq mreq;
577
578 if (--iface->group_count_v4 != 0)
579 /* others still joined */
580 return (0);
581
582 log_debug("%s: interface %s addr %s", __func__, iface->name,
583 inet_ntoa(*addr));
584
585 mreq.imr_multiaddr = *addr;
586 mreq.imr_interface.s_addr = if_primary_addr(iface);
587
588 if (setsockopt(global.eigrp_socket_v4, IPPROTO_IP0, IP_DROP_MEMBERSHIP13,
589 (void *)&mreq, sizeof(mreq)) == -1) {
590 log_warn("%s: error IP_DROP_MEMBERSHIP, interface %s "
591 "address %s", iface->name, __func__, inet_ntoa(*addr));
592 return (-1);
593 }
594
595 return (0);
596}
597
598int
599if_set_ipv4_mcast_ttl(int fd, uint8_t ttl)
600{
601 if (setsockopt(fd, IPPROTO_IP0, IP_MULTICAST_TTL10,
602 (char *)&ttl, sizeof(ttl)) == -1) {
603 log_warn("%s: error setting IP_MULTICAST_TTL to %d",
604 __func__, ttl);
605 return (-1);
606 }
607
608 return (0);
609}
610
611int
612if_set_ipv4_mcast(struct iface *iface)
613{
614 in_addr_t addr;
615
616 addr = if_primary_addr(iface);
617
618 if (setsockopt(global.eigrp_socket_v4, IPPROTO_IP0, IP_MULTICAST_IF9,
619 &addr, sizeof(addr)) == -1) {
620 log_warn("%s: error setting IP_MULTICAST_IF, interface %s",
621 __func__, iface->name);
622 return (-1);
623 }
624
625 return (0);
626}
627
628int
629if_set_ipv4_mcast_loop(int fd)
630{
631 uint8_t loop = 0;
632
633 if (setsockopt(fd, IPPROTO_IP0, IP_MULTICAST_LOOP11,
634 (char *)&loop, sizeof(loop)) == -1) {
635 log_warn("%s: error setting IP_MULTICAST_LOOP", __func__);
636 return (-1);
637 }
638
639 return (0);
640}
641
642int
643if_set_ipv4_recvif(int fd, int enable)
644{
645 if (setsockopt(fd, IPPROTO_IP0, IP_RECVIF30, &enable,
646 sizeof(enable)) == -1) {
647 log_warn("%s: error setting IP_RECVIF", __func__);
648 return (-1);
649 }
650 return (0);
651}
652
653int
654if_set_ipv4_hdrincl(int fd)
655{
656 int hincl = 1;
657
658 if (setsockopt(fd, IPPROTO_IP0, IP_HDRINCL2, &hincl, sizeof(hincl)) == -1) {
659 log_warn("%s: error setting IP_HDRINCL", __func__);
660 return (-1);
661 }
662
663 return (0);
664}
665
666static int
667if_join_ipv6_group(struct iface *iface, struct in6_addr *addr)
668{
669 struct ipv6_mreq mreq;
670
671 if (iface->group_count_v6++ != 0)
672 /* already joined */
673 return (0);
674
675 log_debug("%s: interface %s addr %s", __func__, iface->name,
676 log_in6addr(addr));
677
678 mreq.ipv6mr_multiaddr = *addr;
679 mreq.ipv6mr_interface = iface->ifindex;
680
681 if (setsockopt(global.eigrp_socket_v6, IPPROTO_IPV641, IPV6_JOIN_GROUP12,
682 &mreq, sizeof(mreq)) == -1) {
683 log_warn("%s: error IPV6_JOIN_GROUP, interface %s address %s",
684 __func__, iface->name, log_in6addr(addr));
685 return (-1);
686 }
687
688 return (0);
689}
690
691static int
692if_leave_ipv6_group(struct iface *iface, struct in6_addr *addr)
693{
694 struct ipv6_mreq mreq;
695
696 if (--iface->group_count_v6 != 0)
697 /* others still joined */
698 return (0);
699
700 log_debug("%s: interface %s addr %s", __func__, iface->name,
701 log_in6addr(addr));
702
703 mreq.ipv6mr_multiaddr = *addr;
704 mreq.ipv6mr_interface = iface->ifindex;
705
706 if (setsockopt(global.eigrp_socket_v6, IPPROTO_IPV641, IPV6_LEAVE_GROUP13,
707 (void *)&mreq, sizeof(mreq)) == -1) {
708 log_warn("%s: error IPV6_LEAVE_GROUP, interface %s address %s",
709 __func__, iface->name, log_in6addr(addr));
710 return (-1);
711 }
712
713 return (0);
714}
715
716int
717if_set_ipv6_mcast(struct iface *iface)
718{
719 if (setsockopt(global.eigrp_socket_v6, IPPROTO_IPV641, IPV6_MULTICAST_IF9,
720 &iface->ifindex, sizeof(iface->ifindex)) == -1) {
721 log_warn("%s: error setting IPV6_MULTICAST_IF, interface %s",
722 __func__, iface->name);
723 return (-1);
724 }
725
726 return (0);
727}
728
729int
730if_set_ipv6_mcast_loop(int fd)
731{
732 unsigned int loop = 0;
733
734 if (setsockopt(fd, IPPROTO_IPV641, IPV6_MULTICAST_LOOP11,
735 (unsigned int *)&loop, sizeof(loop)) == -1) {
736 log_warn("%s: error setting IPV6_MULTICAST_LOOP", __func__);
737 return (-1);
738 }
739
740 return (0);
741}
742
743int
744if_set_ipv6_pktinfo(int fd, int enable)
745{
746 if (setsockopt(fd, IPPROTO_IPV641, IPV6_RECVPKTINFO36, &enable,
747 sizeof(enable)) == -1) {
748 log_warn("%s: error setting IPV6_RECVPKTINFO", __func__);
749 return (-1);
750 }
751
752 return (0);
753}
754
755int
756if_set_ipv6_dscp(int fd, int dscp)
757{
758 if (setsockopt(fd, IPPROTO_IPV641, IPV6_TCLASS61, &dscp,
759 sizeof(dscp)) == -1) {
760 log_warn("%s: error setting IPV6_TCLASS", __func__);
761 return (-1);
762 }
763
764 return (0);
765}