GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ripd/rde_rib.c Lines: 0 98 0.0 %
Date: 2017-11-13 Branches: 0 210 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rde_rib.c,v 1.5 2007/10/24 20:38:03 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/ioctl.h>
21
#include <sys/time.h>
22
#include <sys/socket.h>
23
#include <netinet/in.h>
24
#include <arpa/inet.h>
25
#include <net/if.h>
26
#include <net/if_types.h>
27
#include <ctype.h>
28
#include <err.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <event.h>
34
35
#include "ripd.h"
36
#include "rip.h"
37
#include "log.h"
38
#include "rde.h"
39
40
extern struct ripd_conf		*rdeconf;
41
RB_HEAD(rt_tree, rt_node)	 rt;
42
RB_PROTOTYPE(rt_tree, rt_node, entry, rt_compare)
43
RB_GENERATE(rt_tree, rt_node, entry, rt_compare)
44
45
void	 route_action_timeout(int, short, void *);
46
void	 route_action_garbage(int, short, void *);
47
48
/* timers */
49
int
50
route_start_timeout(struct rt_node *rn)
51
{
52
	struct timeval	 tv;
53
54
	timerclear(&tv);
55
	tv.tv_sec = ROUTE_TIMEOUT;
56
57
	return (evtimer_add(&rn->timeout_timer, &tv));
58
}
59
60
void
61
route_start_garbage(struct rt_node *rn)
62
{
63
	struct timeval	 tv;
64
65
	timerclear(&tv);
66
	tv.tv_sec = ROUTE_GARBAGE;
67
68
	if (evtimer_pending(&rn->timeout_timer, NULL)) {
69
		if (evtimer_del(&rn->timeout_timer) == -1)
70
			fatal("route_start_garbage");
71
		evtimer_add(&rn->garbage_timer, &tv);
72
	}
73
}
74
75
/* ARGSUSED */
76
void
77
route_action_timeout(int fd, short event, void *arg)
78
{
79
	struct rt_node	*r = arg;
80
	struct timeval	 tv;
81
82
	timerclear(&tv);
83
	r->metric = INFINITY;
84
	tv.tv_sec = ROUTE_GARBAGE;
85
86
	if (evtimer_add(&r->garbage_timer, &tv) == -1)
87
		fatal("route_action_timeout");
88
89
	rde_send_change_kroute(r);
90
}
91
92
/* ARGSUSED */
93
void
94
route_action_garbage(int fd, short event, void *arg)
95
{
96
	struct rt_node	*r = arg;
97
98
	rde_send_delete_kroute(r);
99
	rt_remove(r);
100
}
101
102
void
103
route_reset_timers(struct rt_node *r)
104
{
105
	struct timeval	 tv;
106
107
	timerclear(&tv);
108
	tv.tv_sec = ROUTE_TIMEOUT;
109
	evtimer_del(&r->timeout_timer);
110
	evtimer_del(&r->garbage_timer);
111
112
	evtimer_add(&r->timeout_timer, &tv);
113
}
114
115
/* route table */
116
void
117
rt_init(void)
118
{
119
	RB_INIT(&rt);
120
}
121
122
int
123
rt_compare(struct rt_node *a, struct rt_node *b)
124
{
125
	if (ntohl(a->prefix.s_addr) < ntohl(b->prefix.s_addr))
126
		return (-1);
127
	if (ntohl(a->prefix.s_addr) > ntohl(b->prefix.s_addr))
128
		return (1);
129
	if (ntohl(a->netmask.s_addr) < ntohl(b->netmask.s_addr))
130
		return (-1);
131
	if (ntohl(a->netmask.s_addr) > ntohl(b->netmask.s_addr))
132
		return (1);
133
134
	return (0);
135
}
136
137
struct rt_node *
138
rt_find(in_addr_t prefix, in_addr_t netmask)
139
{
140
	struct rt_node	 s;
141
142
	s.prefix.s_addr = prefix;
143
	s.netmask.s_addr = netmask;
144
145
	return (RB_FIND(rt_tree, &rt, &s));
146
}
147
148
struct rt_node *
149
rt_new_kr(struct kroute *kr)
150
{
151
	struct rt_node	*rn;
152
153
	if ((rn = calloc(1, sizeof(*rn))) == NULL)
154
		fatal("rt_new_kr");
155
156
	evtimer_set(&rn->timeout_timer, route_action_timeout, rn);
157
	evtimer_set(&rn->garbage_timer, route_action_garbage, rn);
158
159
	rn->prefix.s_addr = kr->prefix.s_addr;
160
	rn->netmask.s_addr = kr->netmask.s_addr;
161
	rn->nexthop.s_addr = kr->nexthop.s_addr;
162
	rn->metric = kr->metric;
163
	rn->ifindex = kr->ifindex;
164
	rn->flags = F_KERNEL;
165
166
	return (rn);
167
}
168
169
struct rt_node *
170
rt_new_rr(struct rip_route *e, u_int8_t metric)
171
{
172
	struct rt_node	*rn;
173
174
	if ((rn = calloc(1, sizeof(*rn))) == NULL)
175
		fatal("rt_new_rr");
176
177
	evtimer_set(&rn->timeout_timer, route_action_timeout, rn);
178
	evtimer_set(&rn->garbage_timer, route_action_garbage, rn);
179
180
	rn->prefix.s_addr = e->address.s_addr;
181
	rn->netmask.s_addr = e->mask.s_addr;
182
	rn->nexthop.s_addr = e->nexthop.s_addr;
183
	rn->metric = metric;
184
	rn->ifindex = e->ifindex;
185
	rn->flags = F_RIPD_INSERTED;
186
187
	return (rn);
188
}
189
190
int
191
rt_insert(struct rt_node *r)
192
{
193
	if (RB_INSERT(rt_tree, &rt, r) != NULL) {
194
		log_warnx("rt_insert failed for %s/%u",
195
		    inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr));
196
		free(r);
197
		return (-1);
198
	}
199
200
	return (0);
201
}
202
203
int
204
rt_remove(struct rt_node *r)
205
{
206
	if (RB_REMOVE(rt_tree, &rt, r) == NULL) {
207
		log_warnx("rt_remove failed for %s/%u",
208
		    inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr));
209
		return (-1);
210
	}
211
212
	free(r);
213
	return (0);
214
}
215
216
void
217
rt_snap(u_int32_t peerid)
218
{
219
	struct rt_node		*r;
220
	struct rip_route	 rr;
221
222
	bzero(&rr, sizeof(rr));
223
224
	RB_FOREACH(r, rt_tree, &rt) {
225
		rr.address = r->prefix;
226
		rr.mask = r->netmask;
227
		rr.nexthop = r->nexthop;
228
		rr.metric = r->metric;
229
		rr.ifindex = r->ifindex;
230
231
		rde_imsg_compose_ripe(IMSG_RESPONSE_ADD, peerid, 0, &rr,
232
		    sizeof(rr));
233
	}
234
}
235
236
void
237
rt_dump(pid_t pid)
238
{
239
	struct rt_node		*r;
240
	static struct ctl_rt	 rtctl;
241
242
	RB_FOREACH(r, rt_tree, &rt) {
243
		rtctl.prefix.s_addr = r->prefix.s_addr;
244
		rtctl.netmask.s_addr = r->netmask.s_addr;
245
		rtctl.nexthop.s_addr = r->nexthop.s_addr;
246
		rtctl.metric = r->metric;
247
		rtctl.flags = r->flags;
248
249
		rde_imsg_compose_ripe(IMSG_CTL_SHOW_RIB, 0, pid, &rtctl,
250
		    sizeof(rtctl));
251
	}
252
}
253
254
void
255
rt_complete(struct rip_route *rr)
256
{
257
	struct rt_node	*rn;
258
259
	if ((rn = rt_find(rr->address.s_addr, rr->mask.s_addr)) == NULL)
260
		rr->metric = INFINITY;
261
	else
262
		rr->metric = rn->metric;
263
}
264
265
void
266
rt_clear(void)
267
{
268
	struct rt_node	*r;
269
270
	while ((r = RB_MIN(rt_tree, &rt)) != NULL)
271
		rt_remove(r);
272
}