xref: /openbsd/usr.sbin/ripd/rde_rib.c (revision 5b133f3f)
1*5b133f3fSguenther /*	$OpenBSD: rde_rib.c,v 1.6 2023/03/08 04:43:14 guenther 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
route_start_timeout(struct rt_node * rn)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 
60960f8542Smichele void
route_start_garbage(struct rt_node * rn)61960f8542Smichele route_start_garbage(struct rt_node *rn)
62960f8542Smichele {
63960f8542Smichele 	struct timeval	 tv;
64960f8542Smichele 
65960f8542Smichele 	timerclear(&tv);
66960f8542Smichele 	tv.tv_sec = ROUTE_GARBAGE;
67960f8542Smichele 
68960f8542Smichele 	if (evtimer_pending(&rn->timeout_timer, NULL)) {
69960f8542Smichele 		if (evtimer_del(&rn->timeout_timer) == -1)
70960f8542Smichele 			fatal("route_start_garbage");
71960f8542Smichele 		evtimer_add(&rn->garbage_timer, &tv);
72960f8542Smichele 	}
73960f8542Smichele }
74960f8542Smichele 
75ddeeec14Snorby void
route_action_timeout(int fd,short event,void * arg)76ddeeec14Snorby route_action_timeout(int fd, short event, void *arg)
77ddeeec14Snorby {
78ddeeec14Snorby 	struct rt_node	*r = arg;
79ddeeec14Snorby 	struct timeval	 tv;
80ddeeec14Snorby 
81ddeeec14Snorby 	timerclear(&tv);
82ddeeec14Snorby 	r->metric = INFINITY;
83ddeeec14Snorby 	tv.tv_sec = ROUTE_GARBAGE;
84ddeeec14Snorby 
85ddeeec14Snorby 	if (evtimer_add(&r->garbage_timer, &tv) == -1)
86ddeeec14Snorby 		fatal("route_action_timeout");
87ddeeec14Snorby 
88ddeeec14Snorby 	rde_send_change_kroute(r);
89ddeeec14Snorby }
90ddeeec14Snorby 
91ddeeec14Snorby void
route_action_garbage(int fd,short event,void * arg)92ddeeec14Snorby route_action_garbage(int fd, short event, void *arg)
93ddeeec14Snorby {
94ddeeec14Snorby 	struct rt_node	*r = arg;
95ddeeec14Snorby 
96ddeeec14Snorby 	rde_send_delete_kroute(r);
97ddeeec14Snorby 	rt_remove(r);
98ddeeec14Snorby }
99ddeeec14Snorby 
100ddeeec14Snorby void
route_reset_timers(struct rt_node * r)101ddeeec14Snorby route_reset_timers(struct rt_node *r)
102ddeeec14Snorby {
103ddeeec14Snorby 	struct timeval	 tv;
104ddeeec14Snorby 
105ddeeec14Snorby 	timerclear(&tv);
106ddeeec14Snorby 	tv.tv_sec = ROUTE_TIMEOUT;
107ddeeec14Snorby 	evtimer_del(&r->timeout_timer);
108ddeeec14Snorby 	evtimer_del(&r->garbage_timer);
109ddeeec14Snorby 
110960f8542Smichele 	evtimer_add(&r->timeout_timer, &tv);
111ddeeec14Snorby }
112ddeeec14Snorby 
113ddeeec14Snorby /* route table */
114ddeeec14Snorby void
rt_init(void)115ddeeec14Snorby rt_init(void)
116ddeeec14Snorby {
117ddeeec14Snorby 	RB_INIT(&rt);
118ddeeec14Snorby }
119ddeeec14Snorby 
120ddeeec14Snorby int
rt_compare(struct rt_node * a,struct rt_node * b)121ddeeec14Snorby rt_compare(struct rt_node *a, struct rt_node *b)
122ddeeec14Snorby {
123ddeeec14Snorby 	if (ntohl(a->prefix.s_addr) < ntohl(b->prefix.s_addr))
124ddeeec14Snorby 		return (-1);
125ddeeec14Snorby 	if (ntohl(a->prefix.s_addr) > ntohl(b->prefix.s_addr))
126ddeeec14Snorby 		return (1);
127ddeeec14Snorby 	if (ntohl(a->netmask.s_addr) < ntohl(b->netmask.s_addr))
128ddeeec14Snorby 		return (-1);
129ddeeec14Snorby 	if (ntohl(a->netmask.s_addr) > ntohl(b->netmask.s_addr))
130ddeeec14Snorby 		return (1);
131ddeeec14Snorby 
132ddeeec14Snorby 	return (0);
133ddeeec14Snorby }
134ddeeec14Snorby 
135ddeeec14Snorby struct rt_node *
rt_find(in_addr_t prefix,in_addr_t netmask)136ddeeec14Snorby rt_find(in_addr_t prefix, in_addr_t netmask)
137ddeeec14Snorby {
138ddeeec14Snorby 	struct rt_node	 s;
139ddeeec14Snorby 
140ddeeec14Snorby 	s.prefix.s_addr = prefix;
141ddeeec14Snorby 	s.netmask.s_addr = netmask;
142ddeeec14Snorby 
143ddeeec14Snorby 	return (RB_FIND(rt_tree, &rt, &s));
144ddeeec14Snorby }
145ddeeec14Snorby 
146ddeeec14Snorby struct rt_node *
rt_new_kr(struct kroute * kr)147ddeeec14Snorby rt_new_kr(struct kroute *kr)
148ddeeec14Snorby {
149ddeeec14Snorby 	struct rt_node	*rn;
150ddeeec14Snorby 
151ddeeec14Snorby 	if ((rn = calloc(1, sizeof(*rn))) == NULL)
152ddeeec14Snorby 		fatal("rt_new_kr");
153ddeeec14Snorby 
154ddeeec14Snorby 	evtimer_set(&rn->timeout_timer, route_action_timeout, rn);
155ddeeec14Snorby 	evtimer_set(&rn->garbage_timer, route_action_garbage, rn);
156ddeeec14Snorby 
157ddeeec14Snorby 	rn->prefix.s_addr = kr->prefix.s_addr;
158ddeeec14Snorby 	rn->netmask.s_addr = kr->netmask.s_addr;
159ddeeec14Snorby 	rn->nexthop.s_addr = kr->nexthop.s_addr;
160ddeeec14Snorby 	rn->metric = kr->metric;
161ddeeec14Snorby 	rn->ifindex = kr->ifindex;
162ddeeec14Snorby 	rn->flags = F_KERNEL;
163ddeeec14Snorby 
164ddeeec14Snorby 	return (rn);
165ddeeec14Snorby }
166ddeeec14Snorby 
167ddeeec14Snorby struct rt_node *
rt_new_rr(struct rip_route * e,u_int8_t metric)1681d57a832Sclaudio rt_new_rr(struct rip_route *e, u_int8_t metric)
169ddeeec14Snorby {
170ddeeec14Snorby 	struct rt_node	*rn;
171ddeeec14Snorby 
172ddeeec14Snorby 	if ((rn = calloc(1, sizeof(*rn))) == NULL)
173ddeeec14Snorby 		fatal("rt_new_rr");
174ddeeec14Snorby 
175ddeeec14Snorby 	evtimer_set(&rn->timeout_timer, route_action_timeout, rn);
176ddeeec14Snorby 	evtimer_set(&rn->garbage_timer, route_action_garbage, rn);
177ddeeec14Snorby 
178ddeeec14Snorby 	rn->prefix.s_addr = e->address.s_addr;
179ddeeec14Snorby 	rn->netmask.s_addr = e->mask.s_addr;
180ddeeec14Snorby 	rn->nexthop.s_addr = e->nexthop.s_addr;
181ddeeec14Snorby 	rn->metric = metric;
182ddeeec14Snorby 	rn->ifindex = e->ifindex;
183ddeeec14Snorby 	rn->flags = F_RIPD_INSERTED;
184ddeeec14Snorby 
185ddeeec14Snorby 	return (rn);
186ddeeec14Snorby }
187ddeeec14Snorby 
188ddeeec14Snorby int
rt_insert(struct rt_node * r)189ddeeec14Snorby rt_insert(struct rt_node *r)
190ddeeec14Snorby {
191ddeeec14Snorby 	if (RB_INSERT(rt_tree, &rt, r) != NULL) {
192ec49f504Sclaudio 		log_warnx("rt_insert failed for %s/%u",
193ec49f504Sclaudio 		    inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr));
194ddeeec14Snorby 		free(r);
195ddeeec14Snorby 		return (-1);
196ddeeec14Snorby 	}
197ddeeec14Snorby 
198ddeeec14Snorby 	return (0);
199ddeeec14Snorby }
200ddeeec14Snorby 
201ddeeec14Snorby int
rt_remove(struct rt_node * r)202ddeeec14Snorby rt_remove(struct rt_node *r)
203ddeeec14Snorby {
204ddeeec14Snorby 	if (RB_REMOVE(rt_tree, &rt, r) == NULL) {
205ec49f504Sclaudio 		log_warnx("rt_remove failed for %s/%u",
206ec49f504Sclaudio 		    inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr));
207ddeeec14Snorby 		return (-1);
208ddeeec14Snorby 	}
209ddeeec14Snorby 
210ddeeec14Snorby 	free(r);
211ddeeec14Snorby 	return (0);
212ddeeec14Snorby }
213ddeeec14Snorby 
214ddeeec14Snorby void
rt_snap(u_int32_t peerid)215ddeeec14Snorby rt_snap(u_int32_t peerid)
216ddeeec14Snorby {
217ddeeec14Snorby 	struct rt_node		*r;
218ddeeec14Snorby 	struct rip_route	 rr;
219ddeeec14Snorby 
220ddeeec14Snorby 	bzero(&rr, sizeof(rr));
221ddeeec14Snorby 
222ddeeec14Snorby 	RB_FOREACH(r, rt_tree, &rt) {
223ddeeec14Snorby 		rr.address = r->prefix;
224ddeeec14Snorby 		rr.mask = r->netmask;
225ddeeec14Snorby 		rr.nexthop = r->nexthop;
226ddeeec14Snorby 		rr.metric = r->metric;
227ddeeec14Snorby 		rr.ifindex = r->ifindex;
228ddeeec14Snorby 
229ddeeec14Snorby 		rde_imsg_compose_ripe(IMSG_RESPONSE_ADD, peerid, 0, &rr,
230ddeeec14Snorby 		    sizeof(rr));
231ddeeec14Snorby 	}
232ddeeec14Snorby }
233ddeeec14Snorby 
234ddeeec14Snorby void
rt_dump(pid_t pid)235ddeeec14Snorby rt_dump(pid_t pid)
236ddeeec14Snorby {
237ddeeec14Snorby 	struct rt_node		*r;
238ddeeec14Snorby 	static struct ctl_rt	 rtctl;
239ddeeec14Snorby 
240ddeeec14Snorby 	RB_FOREACH(r, rt_tree, &rt) {
241ddeeec14Snorby 		rtctl.prefix.s_addr = r->prefix.s_addr;
242ddeeec14Snorby 		rtctl.netmask.s_addr = r->netmask.s_addr;
243ddeeec14Snorby 		rtctl.nexthop.s_addr = r->nexthop.s_addr;
244ddeeec14Snorby 		rtctl.metric = r->metric;
245ddeeec14Snorby 		rtctl.flags = r->flags;
246ddeeec14Snorby 
247ddeeec14Snorby 		rde_imsg_compose_ripe(IMSG_CTL_SHOW_RIB, 0, pid, &rtctl,
248ddeeec14Snorby 		    sizeof(rtctl));
249ddeeec14Snorby 	}
250ddeeec14Snorby }
251ddeeec14Snorby 
252ddeeec14Snorby void
rt_complete(struct rip_route * rr)253ddeeec14Snorby rt_complete(struct rip_route *rr)
254ddeeec14Snorby {
255ddeeec14Snorby 	struct rt_node	*rn;
256ddeeec14Snorby 
257ddeeec14Snorby 	if ((rn = rt_find(rr->address.s_addr, rr->mask.s_addr)) == NULL)
258ddeeec14Snorby 		rr->metric = INFINITY;
259ddeeec14Snorby 	else
260ddeeec14Snorby 		rr->metric = rn->metric;
261ddeeec14Snorby }
262ddeeec14Snorby 
263ddeeec14Snorby void
rt_clear(void)264ddeeec14Snorby rt_clear(void)
265ddeeec14Snorby {
266ddeeec14Snorby 	struct rt_node	*r;
267ddeeec14Snorby 
268ddeeec14Snorby 	while ((r = RB_MIN(rt_tree, &rt)) != NULL)
269ddeeec14Snorby 		rt_remove(r);
270ddeeec14Snorby }
271