1 #ifndef lint 2 static char sccsid[] = "@(#)tables.c 4.2 01/11/83"; 3 #endif 4 5 /* 6 * Routing Table Management Daemon 7 */ 8 #include "defs.h" 9 #include <sys/ioctl.h> 10 #include <errno.h> 11 12 #ifndef DEBUG 13 #define DEBUG 0 14 #endif 15 16 int install = !DEBUG; /* if 1 call kernel */ 17 18 /* 19 * Lookup dst in the tables for an exact match. 20 */ 21 struct rt_entry * 22 rtlookup(dst) 23 struct sockaddr *dst; 24 { 25 register struct rt_entry *rt; 26 register struct rthash *rh; 27 register int hash; 28 struct afhash h; 29 int doinghost = 1; 30 31 if (dst->sa_family >= AF_MAX) 32 return (0); 33 (*afswitch[dst->sa_family].af_hash)(dst, &h); 34 hash = h.afh_hosthash; 35 rh = &hosthash[hash % ROUTEHASHSIZ]; 36 again: 37 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 38 if (rt->rt_hash != hash) 39 continue; 40 if (equal(&rt->rt_dst, dst)) 41 return (rt); 42 } 43 if (doinghost) { 44 doinghost = 0; 45 hash = h.afh_nethash; 46 rh = &nethash[hash % ROUTEHASHSIZ]; 47 goto again; 48 } 49 return (0); 50 } 51 52 /* 53 * Find a route to dst as the kernel would. 54 */ 55 struct rt_entry * 56 rtfind(dst) 57 struct sockaddr *dst; 58 { 59 register struct rt_entry *rt; 60 register struct rthash *rh; 61 register int hash; 62 struct afhash h; 63 int af = dst->sa_family; 64 int doinghost = 1, (*match)(); 65 66 if (af >= AF_MAX) 67 return (0); 68 (*afswitch[af].af_hash)(dst, &h); 69 hash = h.afh_hosthash; 70 rh = &hosthash[hash % ROUTEHASHSIZ]; 71 72 again: 73 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 74 if (rt->rt_hash != hash) 75 continue; 76 if (doinghost) { 77 if (equal(&rt->rt_dst, dst)) 78 return (rt); 79 } else { 80 if (rt->rt_dst.sa_family == af && 81 (*match)(&rt->rt_dst, dst)) 82 return (rt); 83 } 84 } 85 if (doinghost) { 86 doinghost = 0; 87 hash = h.afh_nethash; 88 rh = &nethash[hash % ROUTEHASHSIZ]; 89 match = afswitch[af].af_netmatch; 90 goto again; 91 } 92 return (0); 93 } 94 95 rtadd(dst, gate, metric, state) 96 struct sockaddr *dst, *gate; 97 int metric, state; 98 { 99 struct afhash h; 100 register struct rt_entry *rt; 101 struct rthash *rh; 102 int af = dst->sa_family, flags, hash; 103 104 if (af >= AF_MAX) 105 return; 106 (*afswitch[af].af_hash)(dst, &h); 107 flags = (*afswitch[af].af_checkhost)(dst) ? RTF_HOST : 0; 108 if (flags & RTF_HOST) { 109 hash = h.afh_hosthash; 110 rh = &hosthash[hash % ROUTEHASHSIZ]; 111 } else { 112 hash = h.afh_nethash; 113 rh = &nethash[hash % ROUTEHASHSIZ]; 114 } 115 rt = (struct rt_entry *)malloc(sizeof (*rt)); 116 if (rt == 0) 117 return; 118 rt->rt_hash = hash; 119 rt->rt_dst = *dst; 120 rt->rt_router = *gate; 121 rt->rt_metric = metric; 122 rt->rt_timer = 0; 123 rt->rt_flags = RTF_UP | flags; 124 rt->rt_state = state | RTS_CHANGED; 125 rt->rt_ifp = if_ifwithnet(&rt->rt_router); 126 if (metric) 127 rt->rt_flags |= RTF_GATEWAY; 128 insque(rt, rh); 129 TRACE_ACTION(ADD, rt); 130 if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) 131 perror("SIOCADDRT"); 132 } 133 134 rtchange(rt, gate, metric) 135 struct rt_entry *rt; 136 struct sockaddr *gate; 137 short metric; 138 { 139 int doioctl = 0, metricchanged = 0; 140 struct rtentry oldroute; 141 142 if (!equal(&rt->rt_router, gate)) 143 doioctl++; 144 if (metric != rt->rt_metric) { 145 metricchanged++; 146 rt->rt_metric = metric; 147 } 148 if (doioctl || metricchanged) { 149 TRACE_ACTION(CHANGE, rt); 150 rt->rt_state |= RTS_CHANGED; 151 } 152 if (doioctl) { 153 oldroute = rt->rt_rt; 154 rt->rt_router = *gate; 155 if (install) { 156 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) 157 perror("SIOCADDRT"); 158 if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) 159 perror("SIOCDELRT"); 160 } 161 } 162 } 163 164 rtdelete(rt) 165 struct rt_entry *rt; 166 { 167 TRACE_ACTION(DELETE, rt); 168 if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) 169 perror("SIOCDELRT"); 170 remque(rt); 171 free((char *)rt); 172 } 173 174 rtinit() 175 { 176 register struct rthash *rh; 177 178 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) 179 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 180 for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) 181 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 182 } 183