1*ec49f504Sclaudio /* $OpenBSD: rde_rib.c,v 1.4 2007/10/24 11:47:59 claudio 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 60960f8542Smichele void 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 /* 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 112960f8542Smichele 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) { 194*ec49f504Sclaudio log_warnx("rt_insert failed for %s/%u", 195*ec49f504Sclaudio inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr)); 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) { 207*ec49f504Sclaudio log_warnx("rt_remove failed for %s/%u", 208*ec49f504Sclaudio inet_ntoa(r->prefix), mask2prefixlen(r->netmask.s_addr)); 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