Bug Summary

File:src/usr.sbin/dvmrpd/rde_mfc.c
Warning:line 440, column 7
Result of 'calloc' is converted to a pointer of type 'struct prune_node', which is incompatible with sizeof operand type 'struct prune'

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 rde_mfc.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/dvmrpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/dvmrpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/dvmrpd/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/dvmrpd/rde_mfc.c
1/* $OpenBSD: rde_mfc.c,v 1.10 2015/12/07 19:14:49 mmcc Exp $ */
2
3/*
4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
5 * Copyright (c) 2006 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/socket.h>
22#include <sys/tree.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <err.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "igmp.h"
30#include "dvmrp.h"
31#include "dvmrpd.h"
32#include "log.h"
33#include "dvmrpe.h"
34#include "rde.h"
35
36/* multicast forwarding cache */
37
38void mfc_send_prune(struct rt_node *, struct mfc_node *);
39void mfc_add_prune(struct mfc_node *, struct prune *);
40struct prune_node *mfc_find_prune(struct mfc_node *, struct prune *);
41void mfc_delete_prune(struct mfc_node *,
42 struct prune_node *);
43
44int prune_compare(struct mfc_node *, struct rt_node *, int);
45void prune_expire_timer(int, short, void *);
46int mfc_reset_prune_expire_timer(struct prune_node *);
47
48
49void mfc_expire_timer(int, short, void *);
50int mfc_start_expire_timer(struct mfc_node *);
51int mfc_reset_expire_timer(struct mfc_node *);
52void mfc_prune_timer(int, short, void *);
53int mfc_start_prune_timer(struct mfc_node *);
54int mfc_reset_prune_timer(struct mfc_node *);
55
56int mfc_compare(struct mfc_node *, struct mfc_node *);
57void mfc_invalidate(void);
58
59RB_HEAD(mfc_tree, mfc_node)struct mfc_tree { struct mfc_node *rbh_root; } mfc;
60RB_PROTOTYPE(mfc_tree, mfc_node, entry, mfc_compare)void mfc_tree_RB_INSERT_COLOR(struct mfc_tree *, struct mfc_node
*); void mfc_tree_RB_REMOVE_COLOR(struct mfc_tree *, struct mfc_node
*, struct mfc_node *); struct mfc_node *mfc_tree_RB_REMOVE(struct
mfc_tree *, struct mfc_node *); struct mfc_node *mfc_tree_RB_INSERT
(struct mfc_tree *, struct mfc_node *); struct mfc_node *mfc_tree_RB_FIND
(struct mfc_tree *, struct mfc_node *); struct mfc_node *mfc_tree_RB_NFIND
(struct mfc_tree *, struct mfc_node *); struct mfc_node *mfc_tree_RB_NEXT
(struct mfc_node *); struct mfc_node *mfc_tree_RB_PREV(struct
mfc_node *); struct mfc_node *mfc_tree_RB_MINMAX(struct mfc_tree
*, int);
61RB_GENERATE(mfc_tree, mfc_node, entry, mfc_compare)void mfc_tree_RB_INSERT_COLOR(struct mfc_tree *head, struct mfc_node
*elm) { struct mfc_node *parent, *gparent, *tmp; while ((parent
= (elm)->entry.rbe_parent) && (parent)->entry.
rbe_color == 1) { gparent = (parent)->entry.rbe_parent; if
(parent == (gparent)->entry.rbe_left) { tmp = (gparent)->
entry.rbe_right; if (tmp && (tmp)->entry.rbe_color
== 1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry
.rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0
); elm = gparent; continue; } if ((parent)->entry.rbe_right
== elm) { do { (tmp) = (parent)->entry.rbe_right; if (((parent
)->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (parent); (parent)->entry.rbe_parent = (tmp); do
{} while (0); if (((tmp)->entry.rbe_parent)) do {} while (
0); } while (0); tmp = parent; parent = elm; elm = tmp; } do {
(parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_left;
if (((gparent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } else { tmp = (gparent)->
entry.rbe_left; if (tmp && (tmp)->entry.rbe_color ==
1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry.
rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->entry.rbe_left ==
elm) { do { (tmp) = (parent)->entry.rbe_left; if (((parent
)->entry.rbe_left = (tmp)->entry.rbe_right)) { ((tmp)->
entry.rbe_right)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_right = (parent); (parent)->entry.rbe_parent = (tmp);
do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = parent; parent = elm; elm = tmp; } do
{ (parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_right
; if (((gparent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } } (head->rbh_root)->
entry.rbe_color = 0; } void mfc_tree_RB_REMOVE_COLOR(struct mfc_tree
*head, struct mfc_node *parent, struct mfc_node *elm) { struct
mfc_node *tmp; while ((elm == ((void *)0) || (elm)->entry
.rbe_color == 0) && elm != (head)->rbh_root) { if (
(parent)->entry.rbe_left == elm) { tmp = (parent)->entry
.rbe_right; if ((tmp)->entry.rbe_color == 1) { do { (tmp)->
entry.rbe_color = 0; (parent)->entry.rbe_color = 1; } while
(0); do { (tmp) = (parent)->entry.rbe_right; if (((parent
)->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (parent); (parent)->entry.rbe_parent = (tmp); do
{} while (0); if (((tmp)->entry.rbe_parent)) do {} while (
0); } while (0); tmp = (parent)->entry.rbe_right; } if (((
tmp)->entry.rbe_left == ((void *)0) || ((tmp)->entry.rbe_left
)->entry.rbe_color == 0) && ((tmp)->entry.rbe_right
== ((void *)0) || ((tmp)->entry.rbe_right)->entry.rbe_color
== 0)) { (tmp)->entry.rbe_color = 1; elm = parent; parent
= (elm)->entry.rbe_parent; } else { if ((tmp)->entry.rbe_right
== ((void *)0) || ((tmp)->entry.rbe_right)->entry.rbe_color
== 0) { struct mfc_node *oleft; if ((oleft = (tmp)->entry
.rbe_left)) (oleft)->entry.rbe_color = 0; (tmp)->entry.
rbe_color = 1; do { (oleft) = (tmp)->entry.rbe_left; if ((
(tmp)->entry.rbe_left = (oleft)->entry.rbe_right)) { ((
oleft)->entry.rbe_right)->entry.rbe_parent = (tmp); } do
{} while (0); if (((oleft)->entry.rbe_parent = (tmp)->
entry.rbe_parent)) { if ((tmp) == ((tmp)->entry.rbe_parent
)->entry.rbe_left) ((tmp)->entry.rbe_parent)->entry.
rbe_left = (oleft); else ((tmp)->entry.rbe_parent)->entry
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->entry.rbe_right = (tmp); (tmp)->entry.rbe_parent
= (oleft); do {} while (0); if (((oleft)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->entry.rbe_right
; } (tmp)->entry.rbe_color = (parent)->entry.rbe_color;
(parent)->entry.rbe_color = 0; if ((tmp)->entry.rbe_right
) ((tmp)->entry.rbe_right)->entry.rbe_color = 0; do { (
tmp) = (parent)->entry.rbe_right; if (((parent)->entry.
rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->entry.rbe_left
)->entry.rbe_parent = (parent); } do {} while (0); if (((tmp
)->entry.rbe_parent = (parent)->entry.rbe_parent)) { if
((parent) == ((parent)->entry.rbe_parent)->entry.rbe_left
) ((parent)->entry.rbe_parent)->entry.rbe_left = (tmp);
else ((parent)->entry.rbe_parent)->entry.rbe_right = (
tmp); } else (head)->rbh_root = (tmp); (tmp)->entry.rbe_left
= (parent); (parent)->entry.rbe_parent = (tmp); do {} while
(0); if (((tmp)->entry.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->entry.rbe_left; if ((tmp)->entry.rbe_color == 1) { do
{ (tmp)->entry.rbe_color = 0; (parent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (parent)->entry.rbe_left; if
(((parent)->entry.rbe_left = (tmp)->entry.rbe_right)) {
((tmp)->entry.rbe_right)->entry.rbe_parent = (parent);
} do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->entry.rbe_left
; } if (((tmp)->entry.rbe_left == ((void *)0) || ((tmp)->
entry.rbe_left)->entry.rbe_color == 0) && ((tmp)->
entry.rbe_right == ((void *)0) || ((tmp)->entry.rbe_right)
->entry.rbe_color == 0)) { (tmp)->entry.rbe_color = 1; elm
= parent; parent = (elm)->entry.rbe_parent; } else { if (
(tmp)->entry.rbe_left == ((void *)0) || ((tmp)->entry.rbe_left
)->entry.rbe_color == 0) { struct mfc_node *oright; if ((oright
= (tmp)->entry.rbe_right)) (oright)->entry.rbe_color =
0; (tmp)->entry.rbe_color = 1; do { (oright) = (tmp)->
entry.rbe_right; if (((tmp)->entry.rbe_right = (oright)->
entry.rbe_left)) { ((oright)->entry.rbe_left)->entry.rbe_parent
= (tmp); } do {} while (0); if (((oright)->entry.rbe_parent
= (tmp)->entry.rbe_parent)) { if ((tmp) == ((tmp)->entry
.rbe_parent)->entry.rbe_left) ((tmp)->entry.rbe_parent)
->entry.rbe_left = (oright); else ((tmp)->entry.rbe_parent
)->entry.rbe_right = (oright); } else (head)->rbh_root =
(oright); (oright)->entry.rbe_left = (tmp); (tmp)->entry
.rbe_parent = (oright); do {} while (0); if (((oright)->entry
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
entry.rbe_left; } (tmp)->entry.rbe_color = (parent)->entry
.rbe_color; (parent)->entry.rbe_color = 0; if ((tmp)->entry
.rbe_left) ((tmp)->entry.rbe_left)->entry.rbe_color = 0
; do { (tmp) = (parent)->entry.rbe_left; if (((parent)->
entry.rbe_left = (tmp)->entry.rbe_right)) { ((tmp)->entry
.rbe_right)->entry.rbe_parent = (parent); } do {} while (0
); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_right = (parent); (parent)->entry.rbe_parent = (tmp);
do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); elm = (head)->rbh_root; break; } } } if
(elm) (elm)->entry.rbe_color = 0; } struct mfc_node * mfc_tree_RB_REMOVE
(struct mfc_tree *head, struct mfc_node *elm) { struct mfc_node
*child, *parent, *old = elm; int color; if ((elm)->entry.
rbe_left == ((void *)0)) child = (elm)->entry.rbe_right; else
if ((elm)->entry.rbe_right == ((void *)0)) child = (elm)->
entry.rbe_left; else { struct mfc_node *left; elm = (elm)->
entry.rbe_right; while ((left = (elm)->entry.rbe_left)) elm
= left; child = (elm)->entry.rbe_right; parent = (elm)->
entry.rbe_parent; color = (elm)->entry.rbe_color; if (child
) (child)->entry.rbe_parent = parent; if (parent) { if ((parent
)->entry.rbe_left == elm) (parent)->entry.rbe_left = child
; else (parent)->entry.rbe_right = child; do {} while (0);
} else (head)->rbh_root = child; if ((elm)->entry.rbe_parent
== old) parent = elm; (elm)->entry = (old)->entry; if (
(old)->entry.rbe_parent) { if (((old)->entry.rbe_parent
)->entry.rbe_left == old) ((old)->entry.rbe_parent)->
entry.rbe_left = elm; else ((old)->entry.rbe_parent)->entry
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; ((old)->entry.rbe_left)->entry.rbe_parent = elm
; if ((old)->entry.rbe_right) ((old)->entry.rbe_right)->
entry.rbe_parent = elm; if (parent) { left = parent; do { do {
} while (0); } while ((left = (left)->entry.rbe_parent)); }
goto color; } parent = (elm)->entry.rbe_parent; color = (
elm)->entry.rbe_color; if (child) (child)->entry.rbe_parent
= parent; if (parent) { if ((parent)->entry.rbe_left == elm
) (parent)->entry.rbe_left = child; else (parent)->entry
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; color: if (color == 0) mfc_tree_RB_REMOVE_COLOR(head
, parent, child); return (old); } struct mfc_node * mfc_tree_RB_INSERT
(struct mfc_tree *head, struct mfc_node *elm) { struct mfc_node
*tmp; struct mfc_node *parent = ((void *)0); int comp = 0; tmp
= (head)->rbh_root; while (tmp) { parent = tmp; comp = (mfc_compare
)(elm, parent); if (comp < 0) tmp = (tmp)->entry.rbe_left
; else if (comp > 0) tmp = (tmp)->entry.rbe_right; else
return (tmp); } do { (elm)->entry.rbe_parent = parent; (elm
)->entry.rbe_left = (elm)->entry.rbe_right = ((void *)0
); (elm)->entry.rbe_color = 1; } while (0); if (parent != (
(void *)0)) { if (comp < 0) (parent)->entry.rbe_left = elm
; else (parent)->entry.rbe_right = elm; do {} while (0); }
else (head)->rbh_root = elm; mfc_tree_RB_INSERT_COLOR(head
, elm); return (((void *)0)); } struct mfc_node * mfc_tree_RB_FIND
(struct mfc_tree *head, struct mfc_node *elm) { struct mfc_node
*tmp = (head)->rbh_root; int comp; while (tmp) { comp = mfc_compare
(elm, tmp); if (comp < 0) tmp = (tmp)->entry.rbe_left; else
if (comp > 0) tmp = (tmp)->entry.rbe_right; else return
(tmp); } return (((void *)0)); } struct mfc_node * mfc_tree_RB_NFIND
(struct mfc_tree *head, struct mfc_node *elm) { struct mfc_node
*tmp = (head)->rbh_root; struct mfc_node *res = ((void *)
0); int comp; while (tmp) { comp = mfc_compare(elm, tmp); if (
comp < 0) { res = tmp; tmp = (tmp)->entry.rbe_left; } else
if (comp > 0) tmp = (tmp)->entry.rbe_right; else return
(tmp); } return (res); } struct mfc_node * mfc_tree_RB_NEXT(
struct mfc_node *elm) { if ((elm)->entry.rbe_right) { elm =
(elm)->entry.rbe_right; while ((elm)->entry.rbe_left) elm
= (elm)->entry.rbe_left; } else { if ((elm)->entry.rbe_parent
&& (elm == ((elm)->entry.rbe_parent)->entry.rbe_left
)) elm = (elm)->entry.rbe_parent; else { while ((elm)->
entry.rbe_parent && (elm == ((elm)->entry.rbe_parent
)->entry.rbe_right)) elm = (elm)->entry.rbe_parent; elm
= (elm)->entry.rbe_parent; } } return (elm); } struct mfc_node
* mfc_tree_RB_PREV(struct mfc_node *elm) { if ((elm)->entry
.rbe_left) { elm = (elm)->entry.rbe_left; while ((elm)->
entry.rbe_right) elm = (elm)->entry.rbe_right; } else { if
((elm)->entry.rbe_parent && (elm == ((elm)->entry
.rbe_parent)->entry.rbe_right)) elm = (elm)->entry.rbe_parent
; else { while ((elm)->entry.rbe_parent && (elm ==
((elm)->entry.rbe_parent)->entry.rbe_left)) elm = (elm
)->entry.rbe_parent; elm = (elm)->entry.rbe_parent; } }
return (elm); } struct mfc_node * mfc_tree_RB_MINMAX(struct mfc_tree
*head, int val) { struct mfc_node *tmp = (head)->rbh_root
; struct mfc_node *parent = ((void *)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->entry.rbe_left; else tmp
= (tmp)->entry.rbe_right; } return (parent); }
62
63extern struct dvmrpd_conf *rdeconf;
64
65/* timers */
66void
67mfc_expire_timer(int fd, short event, void *arg)
68{
69 struct mfc_node *mn = arg;
70 struct mfc nmfc;
71
72 log_debug("mfc_expire_timer: group %s", inet_ntoa(mn->group));
73
74 /* remove route entry */
75 nmfc.origin = mn->origin;
76 nmfc.group = mn->group;
77 rde_imsg_compose_parent(IMSG_MFC_DEL, 0, &nmfc, sizeof(nmfc));
78
79 event_del(&mn->expiration_timer);
80 mfc_remove(mn);
81}
82
83int
84mfc_reset_expire_timer(struct mfc_node *mn)
85{
86 struct timeval tv;
87
88 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
89 tv.tv_sec = ROUTE_EXPIRATION_TIME140;
90 return (evtimer_add(&mn->expiration_timer, &tv)event_add(&mn->expiration_timer, &tv));
91}
92
93int
94mfc_start_expire_timer(struct mfc_node *mn)
95{
96 struct timeval tv;
97
98 log_debug("mfc_start_expire_timer: group %s", inet_ntoa(mn->group));
99
100 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
101 tv.tv_sec = ROUTE_EXPIRATION_TIME140;
102 return (evtimer_add(&mn->expiration_timer, &tv)event_add(&mn->expiration_timer, &tv));
103}
104
105void
106mfc_prune_timer(int fd, short event, void *arg)
107{
108 struct mfc_node *mn = arg;
109
110 log_debug("mfc_prune_timer: group %s", inet_ntoa(mn->group));
111
112 event_del(&mn->prune_timer);
113}
114
115int
116mfc_start_prune_timer(struct mfc_node *mn)
117{
118 struct timeval tv;
119
120 log_debug("mfc_start_prune_timer: group %s", inet_ntoa(mn->group));
121
122 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
123 tv.tv_sec = MAX_PRUNE_LIFETIME2 * 3600;
124 return (evtimer_add(&mn->prune_timer, &tv)event_add(&mn->prune_timer, &tv));
125}
126
127int
128mfc_reset_prune_timer(struct mfc_node *mn)
129{
130 struct timeval tv;
131
132 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
133 tv.tv_sec = MAX_PRUNE_LIFETIME2 * 3600;
134 return (evtimer_add(&mn->prune_timer, &tv)event_add(&mn->prune_timer, &tv));
135}
136
137/* route table */
138void
139mfc_init(void)
140{
141 RB_INIT(&mfc)do { (&mfc)->rbh_root = ((void *)0); } while (0);
142}
143
144int
145mfc_compare(struct mfc_node *a, struct mfc_node *b)
146{
147 if (ntohl(a->origin.s_addr)(__uint32_t)(__builtin_constant_p(a->origin.s_addr) ? (__uint32_t
)(((__uint32_t)(a->origin.s_addr) & 0xff) << 24 |
((__uint32_t)(a->origin.s_addr) & 0xff00) << 8 |
((__uint32_t)(a->origin.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(a->origin.s_addr) & 0xff000000) >>
24) : __swap32md(a->origin.s_addr))
< ntohl(b->origin.s_addr)(__uint32_t)(__builtin_constant_p(b->origin.s_addr) ? (__uint32_t
)(((__uint32_t)(b->origin.s_addr) & 0xff) << 24 |
((__uint32_t)(b->origin.s_addr) & 0xff00) << 8 |
((__uint32_t)(b->origin.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(b->origin.s_addr) & 0xff000000) >>
24) : __swap32md(b->origin.s_addr))
)
148 return (-1);
149 if (ntohl(a->origin.s_addr)(__uint32_t)(__builtin_constant_p(a->origin.s_addr) ? (__uint32_t
)(((__uint32_t)(a->origin.s_addr) & 0xff) << 24 |
((__uint32_t)(a->origin.s_addr) & 0xff00) << 8 |
((__uint32_t)(a->origin.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(a->origin.s_addr) & 0xff000000) >>
24) : __swap32md(a->origin.s_addr))
> ntohl(b->origin.s_addr)(__uint32_t)(__builtin_constant_p(b->origin.s_addr) ? (__uint32_t
)(((__uint32_t)(b->origin.s_addr) & 0xff) << 24 |
((__uint32_t)(b->origin.s_addr) & 0xff00) << 8 |
((__uint32_t)(b->origin.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(b->origin.s_addr) & 0xff000000) >>
24) : __swap32md(b->origin.s_addr))
)
150 return (1);
151 if (ntohl(a->group.s_addr)(__uint32_t)(__builtin_constant_p(a->group.s_addr) ? (__uint32_t
)(((__uint32_t)(a->group.s_addr) & 0xff) << 24 |
((__uint32_t)(a->group.s_addr) & 0xff00) << 8 |
((__uint32_t)(a->group.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(a->group.s_addr) & 0xff000000) >>
24) : __swap32md(a->group.s_addr))
< ntohl(b->group.s_addr)(__uint32_t)(__builtin_constant_p(b->group.s_addr) ? (__uint32_t
)(((__uint32_t)(b->group.s_addr) & 0xff) << 24 |
((__uint32_t)(b->group.s_addr) & 0xff00) << 8 |
((__uint32_t)(b->group.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(b->group.s_addr) & 0xff000000) >>
24) : __swap32md(b->group.s_addr))
)
152 return (-1);
153 if (ntohl(a->group.s_addr)(__uint32_t)(__builtin_constant_p(a->group.s_addr) ? (__uint32_t
)(((__uint32_t)(a->group.s_addr) & 0xff) << 24 |
((__uint32_t)(a->group.s_addr) & 0xff00) << 8 |
((__uint32_t)(a->group.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(a->group.s_addr) & 0xff000000) >>
24) : __swap32md(a->group.s_addr))
> ntohl(b->group.s_addr)(__uint32_t)(__builtin_constant_p(b->group.s_addr) ? (__uint32_t
)(((__uint32_t)(b->group.s_addr) & 0xff) << 24 |
((__uint32_t)(b->group.s_addr) & 0xff00) << 8 |
((__uint32_t)(b->group.s_addr) & 0xff0000) >> 8
| ((__uint32_t)(b->group.s_addr) & 0xff000000) >>
24) : __swap32md(b->group.s_addr))
)
154 return (1);
155 return (0);
156}
157
158struct mfc_node *
159mfc_find(in_addr_t origin, in_addr_t group)
160{
161 struct mfc_node s;
162
163 s.origin.s_addr = origin;
164 s.group.s_addr = group;
165
166 return (RB_FIND(mfc_tree, &mfc, &s)mfc_tree_RB_FIND(&mfc, &s));
167}
168
169int
170mfc_insert(struct mfc_node *m)
171{
172 if (RB_INSERT(mfc_tree, &mfc, m)mfc_tree_RB_INSERT(&mfc, m) != NULL((void *)0)) {
173 log_warnx("mfc_insert failed for group %s",
174 inet_ntoa(m->group));
175 free(m);
176 return (-1);
177 }
178
179 return (0);
180}
181
182int
183mfc_remove(struct mfc_node *m)
184{
185 if (RB_REMOVE(mfc_tree, &mfc, m)mfc_tree_RB_REMOVE(&mfc, m) == NULL((void *)0)) {
186 log_warnx("mfc_remove failed for group %s",
187 inet_ntoa(m->group));
188 return (-1);
189 }
190
191 free(m);
192 return (0);
193}
194
195void
196mfc_clear(void)
197{
198 struct mfc_node *m;
199
200 while ((m = RB_MIN(mfc_tree, &mfc)mfc_tree_RB_MINMAX(&mfc, -1)) != NULL((void *)0))
201 mfc_remove(m);
202}
203
204void
205mfc_dump(pid_t pid)
206{
207 static struct ctl_mfc mfcctl;
208 struct timespec now;
209 struct timeval tv, now2, res;
210 struct mfc_node *mn;
211 int i;
212
213 clock_gettime(CLOCK_MONOTONIC3, &now);
214
215 RB_FOREACH(mn, mfc_tree, &mfc)for ((mn) = mfc_tree_RB_MINMAX(&mfc, -1); (mn) != ((void *
)0); (mn) = mfc_tree_RB_NEXT(mn))
{
216 mfcctl.origin.s_addr = mn->origin.s_addr;
217 mfcctl.group.s_addr = mn->group.s_addr;
218 mfcctl.uptime = now.tv_sec - mn->uptime;
219 mfcctl.ifindex = mn->ifindex;
220
221 for (i = 0; i < MAXVIFS32; i ++) {
222 mfcctl.ttls[i] = mn->ttls[i];
223 }
224
225 gettimeofday(&now2, NULL((void *)0));
226 if (evtimer_pending(&mn->expiration_timer, &tv)event_pending(&mn->expiration_timer, 0x01, &tv)) {
227 timersub(&tv, &now2, &res)do { (&res)->tv_sec = (&tv)->tv_sec - (&now2
)->tv_sec; (&res)->tv_usec = (&tv)->tv_usec -
(&now2)->tv_usec; if ((&res)->tv_usec < 0) {
(&res)->tv_sec--; (&res)->tv_usec += 1000000; }
} while (0)
;
228 mfcctl.expire = res.tv_sec;
229 } else
230 mfcctl.expire = -1;
231
232 rde_imsg_compose_dvmrpe(IMSG_CTL_SHOW_MFC, 0, pid, &mfcctl,
233 sizeof(mfcctl));
234 }
235}
236
237struct rt_node *
238mfc_find_origin(struct in_addr group)
239{
240 struct mfc_node *mn;
241
242 RB_FOREACH(mn, mfc_tree, &mfc)for ((mn) = mfc_tree_RB_MINMAX(&mfc, -1); (mn) != ((void *
)0); (mn) = mfc_tree_RB_NEXT(mn))
243 if (group.s_addr == mn->group.s_addr)
244 return (rt_match_origin(mn->origin.s_addr));
245
246 return (NULL((void *)0));
247}
248
249void
250mfc_send_prune(struct rt_node *rn, struct mfc_node *mn)
251{
252 struct prune p;
253
254 memset(&p, 0, sizeof(p));
255
256 p.origin.s_addr = (mn->origin.s_addr &
257 htonl(prefixlen2mask(rn->prefixlen))(__uint32_t)(__builtin_constant_p(prefixlen2mask(rn->prefixlen
)) ? (__uint32_t)(((__uint32_t)(prefixlen2mask(rn->prefixlen
)) & 0xff) << 24 | ((__uint32_t)(prefixlen2mask(rn->
prefixlen)) & 0xff00) << 8 | ((__uint32_t)(prefixlen2mask
(rn->prefixlen)) & 0xff0000) >> 8 | ((__uint32_t
)(prefixlen2mask(rn->prefixlen)) & 0xff000000) >>
24) : __swap32md(prefixlen2mask(rn->prefixlen)))
);
258 p.netmask.s_addr = htonl(prefixlen2mask(rn->prefixlen))(__uint32_t)(__builtin_constant_p(prefixlen2mask(rn->prefixlen
)) ? (__uint32_t)(((__uint32_t)(prefixlen2mask(rn->prefixlen
)) & 0xff) << 24 | ((__uint32_t)(prefixlen2mask(rn->
prefixlen)) & 0xff00) << 8 | ((__uint32_t)(prefixlen2mask
(rn->prefixlen)) & 0xff0000) >> 8 | ((__uint32_t
)(prefixlen2mask(rn->prefixlen)) & 0xff000000) >>
24) : __swap32md(prefixlen2mask(rn->prefixlen)))
;
259 p.group.s_addr = mn->group.s_addr;
260 p.nexthop.s_addr = rn->nexthop.s_addr;
261 p.ifindex = mn->ifindex;
262
263 rde_imsg_compose_dvmrpe(IMSG_SEND_PRUNE, 0, 0, &p, sizeof(p));
264
265 mfc_start_prune_timer(mn);
266}
267
268void
269mfc_update_source(struct rt_node *rn)
270{
271 struct mfc_node *mn;
272 struct mfc m;
273 int i;
274 u_int8_t found;
275
276 RB_FOREACH(mn, mfc_tree, &mfc)for ((mn) = mfc_tree_RB_MINMAX(&mfc, -1); (mn) != ((void *
)0); (mn) = mfc_tree_RB_NEXT(mn))
{
277 if (rn->prefix.s_addr == (mn->origin.s_addr &
278 htonl(prefixlen2mask(rn->prefixlen))(__uint32_t)(__builtin_constant_p(prefixlen2mask(rn->prefixlen
)) ? (__uint32_t)(((__uint32_t)(prefixlen2mask(rn->prefixlen
)) & 0xff) << 24 | ((__uint32_t)(prefixlen2mask(rn->
prefixlen)) & 0xff00) << 8 | ((__uint32_t)(prefixlen2mask
(rn->prefixlen)) & 0xff0000) >> 8 | ((__uint32_t
)(prefixlen2mask(rn->prefixlen)) & 0xff000000) >>
24) : __swap32md(prefixlen2mask(rn->prefixlen)))
)) {
279 mn->ifindex = rn->ifindex;
280
281 found = 0;
282
283 for (i = 0; i < MAXVIFS32; i++) {
284 mn->ttls[i] = rn->ttls[i];
285 if (mn->ttls[i] != 0)
286 found = 1;
287 }
288
289 m.origin.s_addr = mn->origin.s_addr;
290 m.group.s_addr = mn->group.s_addr;
291 m.ifindex = mn->ifindex;
292
293 for (i = 0; i < MAXVIFS32; i++)
294 m.ttls[i] = mn->ttls[i];
295
296 rde_imsg_compose_parent(IMSG_MFC_ADD, 0, &m, sizeof(m));
297
298 mfc_reset_expire_timer(mn);
299
300 if (!found && !rn->connected)
301 mfc_send_prune(rn, mn);
302 }
303 }
304}
305
306void
307mfc_update(struct mfc *nmfc)
308{
309 struct mfc_node *mn;
310 struct rt_node *rn;
311 struct timespec now;
312 int i;
313 u_int8_t found = 0;
314
315 clock_gettime(CLOCK_MONOTONIC3, &now);
316
317 if ((mn = mfc_find(nmfc->origin.s_addr, nmfc->group.s_addr)) == NULL((void *)0)) {
318 if ((mn = calloc(1, sizeof(struct mfc_node))) == NULL((void *)0))
319 fatalx("mfc_update");
320
321 mn->origin.s_addr = nmfc->origin.s_addr;
322 mn->group.s_addr = nmfc->group.s_addr;
323 mn->ifindex = nmfc->ifindex;
324 mn->uptime = now.tv_sec;
325 for (i = 0; i < MAXVIFS32; i++) {
326 mn->ttls[i] = nmfc->ttls[i];
327 if (mn->ttls[i] != 0)
328 found = 1;
329 }
330
331 if (mfc_insert(mn) == 0) {
332 rde_imsg_compose_parent(IMSG_MFC_ADD, 0, nmfc,
333 sizeof(*nmfc));
334 }
335
336 evtimer_set(&mn->expiration_timer, mfc_expire_timer, mn)event_set(&mn->expiration_timer, -1, 0, mfc_expire_timer
, mn)
;
337 evtimer_set(&mn->prune_timer, mfc_expire_timer, mn)event_set(&mn->prune_timer, -1, 0, mfc_expire_timer, mn
)
;
338 mfc_start_expire_timer(mn);
339
340 if (!found) {
341 /* We removed all downstream interfaces,
342 start the pruning process */
343 rn = rt_match_origin(mn->origin.s_addr);
344 if (rn == NULL((void *)0)) {
345 fatal("mfc_update: cannot find information "
346 " about source");
347 }
348
349 mfc_send_prune(rn, mn);
350 }
351 }
352}
353
354void
355mfc_delete(struct mfc *nmfc)
356{
357 struct mfc_node *mn;
358
359 if ((mn = mfc_find(nmfc->origin.s_addr, nmfc->group.s_addr)) == NULL((void *)0))
360 return;
361
362 /* XXX decide if it should really be removed */
363 mfc_remove(mn);
364
365 /* XXX notify parent */
366}
367
368int
369mfc_check_members(struct rt_node *rn, struct iface *iface)
370{
371 struct mfc_node *mn;
372
373 RB_FOREACH(mn, mfc_tree, &mfc)for ((mn) = mfc_tree_RB_MINMAX(&mfc, -1); (mn) != ((void *
)0); (mn) = mfc_tree_RB_NEXT(mn))
{
374 if (mn->origin.s_addr == rn->prefix.s_addr) {
375 if (rde_group_list_find(iface, mn->group) != 0)
376 return (1);
377 }
378 }
379
380 return (0);
381}
382
383void
384mfc_recv_prune(struct prune *p)
385{
386 struct rt_node *rn;
387 struct mfc_node *mn;
388 struct prune_node *pn;
389 struct iface *iface;
390 struct mfc m;
391
392 iface = if_find_index(p->ifindex);
393 if (iface == NULL((void *)0)) {
394 log_debug("mfc_recv_prune: unknown interface");
395 return;
396 }
397
398 rn = rt_match_origin(p->origin.s_addr);
399 if (rn == NULL((void *)0)) {
400 log_debug("mfc_recv_prune: no information for %s\n",
401 inet_ntoa(p->origin));
402 return;
403 }
404
405 if (srt_find_ds(rn, p->nexthop.s_addr) == NULL((void *)0)) {
406 log_debug("mfc_recv_prune: prune received from a "
407 "non downstream neighbor\n");
408 return;
409 }
410
411 mn = mfc_find(p->origin.s_addr, p->group.s_addr);
412 if (mn) {
413 log_debug("mfc_recv_prune: no information for %s\n",
414 inet_ntoa(p->origin));
415 return;
416 }
417
418 pn = mfc_find_prune(mn, p);
419 if (pn == NULL((void *)0)) {
420 mfc_add_prune(mn, p);
421 if (prune_compare(mn, rn, p->ifindex) &&
422 !rde_group_list_find(iface, p->group)) {
423 mn->ttls[p->ifindex] = 0;
424
425 m.ifindex = p->ifindex;
426 m.origin.s_addr = p->origin.s_addr;
427 m.group.s_addr = p->group.s_addr;
428 mfc_update(&m);
429 }
430 } else
431 mfc_reset_prune_expire_timer(pn);
432}
433
434void
435mfc_add_prune(struct mfc_node *mn, struct prune *p)
436{
437 struct prune_node *pn;
438 struct timeval tv;
439
440 pn = calloc(1, sizeof(struct prune));
Result of 'calloc' is converted to a pointer of type 'struct prune_node', which is incompatible with sizeof operand type 'struct prune'
441 if (pn == NULL((void *)0))
442 fatal("prune_add");
443
444 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
445 tv.tv_sec = MAX_PRUNE_LIFETIME2 * 3600;
446
447 pn->nbr.s_addr = p->nexthop.s_addr;
448 pn->ifindex = p->ifindex;
449 pn->parent = mn;
450
451 evtimer_set(&pn->lifetime_timer, prune_expire_timer, pn)event_set(&pn->lifetime_timer, -1, 0, prune_expire_timer
, pn)
;
452 evtimer_add(&pn->lifetime_timer, &tv)event_add(&pn->lifetime_timer, &tv);
453
454 LIST_INSERT_HEAD(&mn->prune_list, pn, entry)do { if (((pn)->entry.le_next = (&mn->prune_list)->
lh_first) != ((void *)0)) (&mn->prune_list)->lh_first
->entry.le_prev = &(pn)->entry.le_next; (&mn->
prune_list)->lh_first = (pn); (pn)->entry.le_prev = &
(&mn->prune_list)->lh_first; } while (0)
;
455
456 mn->prune_cnt[p->ifindex]++;
457}
458
459struct prune_node *
460mfc_find_prune(struct mfc_node *mn, struct prune *p)
461{
462 struct prune_node *pn;
463
464 LIST_FOREACH(pn, &mn->prune_list, entry)for((pn) = ((&mn->prune_list)->lh_first); (pn)!= ((
void *)0); (pn) = ((pn)->entry.le_next))
{
465 if (p->nexthop.s_addr == pn->nbr.s_addr)
466 return (pn);
467 }
468
469 return (NULL((void *)0));
470}
471
472void
473mfc_delete_prune(struct mfc_node *mn, struct prune_node *pn)
474{
475 unsigned int ifindex = pn->ifindex;
476
477 if (evtimer_pending(&pn->lifetime_timer, NULL)event_pending(&pn->lifetime_timer, 0x01, ((void *)0)))
478 if (evtimer_del(&pn->lifetime_timer)event_del(&pn->lifetime_timer) == -1)
479 fatal("mfc_delete_prune");
480
481 LIST_REMOVE(pn, entry)do { if ((pn)->entry.le_next != ((void *)0)) (pn)->entry
.le_next->entry.le_prev = (pn)->entry.le_prev; *(pn)->
entry.le_prev = (pn)->entry.le_next; ; ; } while (0)
;
482 free(pn);
483 mn->prune_cnt[ifindex]--;
484}
485
486int
487prune_compare(struct mfc_node *mn, struct rt_node *rn, int ifindex)
488{
489 if (mn->prune_cnt[ifindex] == rn->ds_cnt[ifindex])
490 return (1);
491
492 return (0);
493}
494
495int
496mfc_reset_prune_expire_timer(struct prune_node *pn)
497{
498 struct timeval tv;
499
500 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
501 tv.tv_sec = MAX_PRUNE_LIFETIME2 * 3600;
502
503 return (evtimer_add(&pn->lifetime_timer, &tv)event_add(&pn->lifetime_timer, &tv));
504}
505
506void
507prune_expire_timer(int fd, short event, void *arg)
508{
509 struct prune_node *pn = arg;
510
511 LIST_REMOVE(pn, entry)do { if ((pn)->entry.le_next != ((void *)0)) (pn)->entry
.le_next->entry.le_prev = (pn)->entry.le_prev; *(pn)->
entry.le_prev = (pn)->entry.le_next; ; ; } while (0)
;
512
513 pn->parent->prune_cnt[pn->ifindex]--;
514 pn->parent->ttls[pn->ifindex] = 1;
515
516 free(pn);
517}