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