1 /* 2 * Copyright (c) 1985 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)tables.c 5.7 (Berkeley) 09/20/88"; 20 #endif /* not lint */ 21 22 /* 23 * Routing Table Management Daemon 24 */ 25 #include "defs.h" 26 #include <sys/ioctl.h> 27 #include <errno.h> 28 29 #ifndef DEBUG 30 #define DEBUG 0 31 #endif 32 33 extern char *xns_ntoa(); 34 35 int install = !DEBUG; /* if 1 call kernel */ 36 int delete = 1; 37 /* 38 * Lookup dst in the tables for an exact match. 39 */ 40 struct rt_entry * 41 rtlookup(dst) 42 struct sockaddr *dst; 43 { 44 register struct rt_entry *rt; 45 register struct rthash *rh; 46 register u_int hash; 47 struct afhash h; 48 int doinghost = 1; 49 50 if (dst->sa_family >= AF_MAX) 51 return (0); 52 (*afswitch[dst->sa_family].af_hash)(dst, &h); 53 hash = h.afh_hosthash; 54 rh = &hosthash[hash & ROUTEHASHMASK]; 55 again: 56 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 57 if (rt->rt_hash != hash) 58 continue; 59 if (equal(&rt->rt_dst, dst)) 60 return (rt); 61 } 62 if (doinghost) { 63 doinghost = 0; 64 hash = h.afh_nethash; 65 rh = &nethash[hash & ROUTEHASHMASK]; 66 goto again; 67 } 68 return (0); 69 } 70 71 /* 72 * Find a route to dst as the kernel would. 73 */ 74 struct rt_entry * 75 rtfind(dst) 76 struct sockaddr *dst; 77 { 78 register struct rt_entry *rt; 79 register struct rthash *rh; 80 register u_int hash; 81 struct afhash h; 82 int af = dst->sa_family; 83 int doinghost = 1, (*match)(); 84 85 if (af >= AF_MAX) 86 return (0); 87 (*afswitch[af].af_hash)(dst, &h); 88 hash = h.afh_hosthash; 89 rh = &hosthash[hash & ROUTEHASHMASK]; 90 91 again: 92 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { 93 if (rt->rt_hash != hash) 94 continue; 95 if (doinghost) { 96 if (equal(&rt->rt_dst, dst)) 97 return (rt); 98 } else { 99 if (rt->rt_dst.sa_family == af && 100 (*match)(&rt->rt_dst, dst)) 101 return (rt); 102 } 103 } 104 if (doinghost) { 105 doinghost = 0; 106 hash = h.afh_nethash; 107 rh = &nethash[hash & ROUTEHASHMASK]; 108 match = afswitch[af].af_netmatch; 109 goto again; 110 } 111 return (0); 112 } 113 114 rtadd(dst, gate, metric, state) 115 struct sockaddr *dst, *gate; 116 int metric, state; 117 { 118 struct afhash h; 119 register struct rt_entry *rt; 120 struct rthash *rh; 121 int af = dst->sa_family, flags; 122 u_int hash; 123 124 if (af >= AF_MAX) 125 return; 126 (*afswitch[af].af_hash)(dst, &h); 127 flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; 128 if (flags & RTF_HOST) { 129 hash = h.afh_hosthash; 130 rh = &hosthash[hash & ROUTEHASHMASK]; 131 } else { 132 hash = h.afh_nethash; 133 rh = &nethash[hash & ROUTEHASHMASK]; 134 } 135 rt = (struct rt_entry *)malloc(sizeof (*rt)); 136 if (rt == 0) 137 return; 138 rt->rt_hash = hash; 139 rt->rt_dst = *dst; 140 rt->rt_router = *gate; 141 rt->rt_metric = metric; 142 rt->rt_timer = 0; 143 rt->rt_flags = RTF_UP | flags; 144 rt->rt_state = state | RTS_CHANGED; 145 rt->rt_ifp = if_ifwithnet(&rt->rt_router); 146 if (metric) 147 rt->rt_flags |= RTF_GATEWAY; 148 insque(rt, rh); 149 TRACE_ACTION(ADD, rt); 150 /* 151 * If the ioctl fails because the gateway is unreachable 152 * from this host, discard the entry. This should only 153 * occur because of an incorrect entry in /etc/gateways. 154 */ 155 if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) { 156 if (errno != EEXIST) 157 perror("SIOCADDRT"); 158 if (errno == ENETUNREACH) { 159 TRACE_ACTION(DELETE, rt); 160 remque(rt); 161 free((char *)rt); 162 } 163 } 164 } 165 166 rtchange(rt, gate, metric) 167 struct rt_entry *rt; 168 struct sockaddr *gate; 169 short metric; 170 { 171 int doioctl = 0, metricchanged = 0; 172 struct rtentry oldroute; 173 174 if (!equal(&rt->rt_router, gate)) 175 doioctl++; 176 if (metric != rt->rt_metric) 177 metricchanged++; 178 if (doioctl || metricchanged) { 179 TRACE_ACTION(CHANGE FROM, rt); 180 if (doioctl) { 181 oldroute = rt->rt_rt; 182 rt->rt_router = *gate; 183 } 184 rt->rt_metric = metric; 185 if ((rt->rt_state & RTS_INTERFACE) && metric) { 186 rt->rt_state &= ~RTS_INTERFACE; 187 syslog(LOG_ERR, 188 "changing route from interface %s (timed out)", 189 rt->rt_ifp->int_name); 190 } 191 if (metric) 192 rt->rt_flags |= RTF_GATEWAY; 193 else 194 rt->rt_flags &= ~RTF_GATEWAY; 195 rt->rt_state |= RTS_CHANGED; 196 TRACE_ACTION(CHANGE TO, rt); 197 } 198 if (doioctl && install) { 199 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) 200 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m", 201 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr), 202 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr)); 203 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) 204 perror("SIOCDELRT"); 205 } 206 } 207 208 rtdelete(rt) 209 struct rt_entry *rt; 210 { 211 212 if (rt->rt_state & RTS_INTERFACE) { 213 syslog(LOG_ERR, "deleting route to interface %s (timed out)", 214 rt->rt_ifp->int_name); 215 } 216 TRACE_ACTION(DELETE, rt); 217 if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) 218 perror("SIOCDELRT"); 219 remque(rt); 220 free((char *)rt); 221 } 222 223 rtinit() 224 { 225 register struct rthash *rh; 226 227 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) 228 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 229 for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) 230 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; 231 } 232