19020Ssam #ifndef lint 2*16128Skarels static char sccsid[] = "@(#)tables.c 4.5 (Berkeley) 03/07/84"; 39020Ssam #endif 49020Ssam 59020Ssam /* 69020Ssam * Routing Table Management Daemon 79020Ssam */ 810245Ssam #include "defs.h" 99020Ssam #include <sys/ioctl.h> 109020Ssam #include <errno.h> 119020Ssam 129020Ssam #ifndef DEBUG 139020Ssam #define DEBUG 0 149020Ssam #endif 159020Ssam 169020Ssam int install = !DEBUG; /* if 1 call kernel */ 179020Ssam 189020Ssam /* 199020Ssam * Lookup dst in the tables for an exact match. 209020Ssam */ 219020Ssam struct rt_entry * 229020Ssam rtlookup(dst) 239020Ssam struct sockaddr *dst; 249020Ssam { 259020Ssam register struct rt_entry *rt; 269020Ssam register struct rthash *rh; 27*16128Skarels register u_int hash; 289020Ssam struct afhash h; 299020Ssam int doinghost = 1; 309020Ssam 319020Ssam if (dst->sa_family >= AF_MAX) 329020Ssam return (0); 339020Ssam (*afswitch[dst->sa_family].af_hash)(dst, &h); 349020Ssam hash = h.afh_hosthash; 359020Ssam rh = &hosthash[hash % ROUTEHASHSIZ]; 369020Ssam again: 379020Ssam for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 389020Ssam if (rt->rt_hash != hash) 399020Ssam continue; 409020Ssam if (equal(&rt->rt_dst, dst)) 419020Ssam return (rt); 429020Ssam } 439020Ssam if (doinghost) { 449020Ssam doinghost = 0; 459020Ssam hash = h.afh_nethash; 469020Ssam rh = &nethash[hash % ROUTEHASHSIZ]; 479020Ssam goto again; 489020Ssam } 499020Ssam return (0); 509020Ssam } 519020Ssam 529020Ssam /* 539020Ssam * Find a route to dst as the kernel would. 549020Ssam */ 559020Ssam struct rt_entry * 569020Ssam rtfind(dst) 579020Ssam struct sockaddr *dst; 589020Ssam { 599020Ssam register struct rt_entry *rt; 609020Ssam register struct rthash *rh; 61*16128Skarels register u_int hash; 629020Ssam struct afhash h; 639020Ssam int af = dst->sa_family; 649020Ssam int doinghost = 1, (*match)(); 659020Ssam 669020Ssam if (af >= AF_MAX) 679020Ssam return (0); 689020Ssam (*afswitch[af].af_hash)(dst, &h); 699020Ssam hash = h.afh_hosthash; 709020Ssam rh = &hosthash[hash % ROUTEHASHSIZ]; 719020Ssam 729020Ssam again: 739020Ssam for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 749020Ssam if (rt->rt_hash != hash) 759020Ssam continue; 769020Ssam if (doinghost) { 779020Ssam if (equal(&rt->rt_dst, dst)) 789020Ssam return (rt); 799020Ssam } else { 809020Ssam if (rt->rt_dst.sa_family == af && 819020Ssam (*match)(&rt->rt_dst, dst)) 829020Ssam return (rt); 839020Ssam } 849020Ssam } 859020Ssam if (doinghost) { 869020Ssam doinghost = 0; 879020Ssam hash = h.afh_nethash; 889020Ssam rh = &nethash[hash % ROUTEHASHSIZ]; 899020Ssam match = afswitch[af].af_netmatch; 909020Ssam goto again; 919020Ssam } 929020Ssam return (0); 939020Ssam } 949020Ssam 959020Ssam rtadd(dst, gate, metric, state) 969020Ssam struct sockaddr *dst, *gate; 979020Ssam int metric, state; 989020Ssam { 999020Ssam struct afhash h; 1009020Ssam register struct rt_entry *rt; 1019020Ssam struct rthash *rh; 102*16128Skarels int af = dst->sa_family, flags; 103*16128Skarels u_int hash; 1049020Ssam 1059020Ssam if (af >= AF_MAX) 1069020Ssam return; 1079020Ssam (*afswitch[af].af_hash)(dst, &h); 108*16128Skarels flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; 1099020Ssam if (flags & RTF_HOST) { 1109020Ssam hash = h.afh_hosthash; 1119020Ssam rh = &hosthash[hash % ROUTEHASHSIZ]; 1129020Ssam } else { 1139020Ssam hash = h.afh_nethash; 1149020Ssam rh = &nethash[hash % ROUTEHASHSIZ]; 1159020Ssam } 1169020Ssam rt = (struct rt_entry *)malloc(sizeof (*rt)); 1179020Ssam if (rt == 0) 1189020Ssam return; 1199020Ssam rt->rt_hash = hash; 1209020Ssam rt->rt_dst = *dst; 1219020Ssam rt->rt_router = *gate; 1229020Ssam rt->rt_metric = metric; 1239020Ssam rt->rt_timer = 0; 1249020Ssam rt->rt_flags = RTF_UP | flags; 1259020Ssam rt->rt_state = state | RTS_CHANGED; 1269020Ssam rt->rt_ifp = if_ifwithnet(&rt->rt_router); 1279020Ssam if (metric) 1289020Ssam rt->rt_flags |= RTF_GATEWAY; 1299020Ssam insque(rt, rh); 1309020Ssam TRACE_ACTION(ADD, rt); 13115098Ssam /* 13215098Ssam * If the ioctl fails because the gateway is unreachable 13315098Ssam * from this host, discard the entry. This should only 13415098Ssam * occur because of an incorrect entry in /etc/gateways. 13515098Ssam */ 13615098Ssam if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) { 1379020Ssam perror("SIOCADDRT"); 13815098Ssam if (errno == ENETUNREACH) { 13915098Ssam TRACE_ACTION(DELETE, rt); 14015098Ssam remque(rt); 14115098Ssam free((char *)rt); 14215098Ssam } 14315098Ssam } 1449020Ssam } 1459020Ssam 1469020Ssam rtchange(rt, gate, metric) 1479020Ssam struct rt_entry *rt; 1489020Ssam struct sockaddr *gate; 1499020Ssam short metric; 1509020Ssam { 1519020Ssam int doioctl = 0, metricchanged = 0; 1529020Ssam struct rtentry oldroute; 1539020Ssam 1549020Ssam if (!equal(&rt->rt_router, gate)) 1559020Ssam doioctl++; 1569020Ssam if (metric != rt->rt_metric) { 1579020Ssam metricchanged++; 1589020Ssam rt->rt_metric = metric; 1599020Ssam } 1609020Ssam if (doioctl || metricchanged) { 1619020Ssam TRACE_ACTION(CHANGE, rt); 1629020Ssam rt->rt_state |= RTS_CHANGED; 1639020Ssam } 1649020Ssam if (doioctl) { 1659020Ssam oldroute = rt->rt_rt; 1669020Ssam rt->rt_router = *gate; 1679020Ssam if (install) { 1689020Ssam if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) 1699020Ssam perror("SIOCADDRT"); 1709020Ssam if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) 1719020Ssam perror("SIOCDELRT"); 1729020Ssam } 1739020Ssam } 1749020Ssam } 1759020Ssam 1769020Ssam rtdelete(rt) 1779020Ssam struct rt_entry *rt; 1789020Ssam { 17915098Ssam 1809020Ssam TRACE_ACTION(DELETE, rt); 1819020Ssam if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) 1829020Ssam perror("SIOCDELRT"); 1839020Ssam remque(rt); 1849020Ssam free((char *)rt); 1859020Ssam } 1869020Ssam 1879020Ssam rtinit() 1889020Ssam { 1899020Ssam register struct rthash *rh; 1909020Ssam 1919020Ssam for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) 1929020Ssam rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 1939020Ssam for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) 1949020Ssam rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 1959020Ssam } 196