|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)tables.c 4.4 (Berkeley) 9/25/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: /* ! 131: * If the ioctl fails because the gateway is unreachable ! 132: * from this host, discard the entry. This should only ! 133: * occur because of an incorrect entry in /etc/gateways. ! 134: */ ! 135: if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) { ! 136: perror("SIOCADDRT"); ! 137: if (errno == ENETUNREACH) { ! 138: TRACE_ACTION(DELETE, rt); ! 139: remque(rt); ! 140: free((char *)rt); ! 141: } ! 142: } ! 143: } ! 144: ! 145: rtchange(rt, gate, metric) ! 146: struct rt_entry *rt; ! 147: struct sockaddr *gate; ! 148: short metric; ! 149: { ! 150: int doioctl = 0, metricchanged = 0; ! 151: struct rtentry oldroute; ! 152: ! 153: if (!equal(&rt->rt_router, gate)) ! 154: doioctl++; ! 155: if (metric != rt->rt_metric) { ! 156: metricchanged++; ! 157: rt->rt_metric = metric; ! 158: } ! 159: if (doioctl || metricchanged) { ! 160: TRACE_ACTION(CHANGE, rt); ! 161: rt->rt_state |= RTS_CHANGED; ! 162: } ! 163: if (doioctl) { ! 164: oldroute = rt->rt_rt; ! 165: rt->rt_router = *gate; ! 166: if (install) { ! 167: if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) ! 168: perror("SIOCADDRT"); ! 169: if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) ! 170: perror("SIOCDELRT"); ! 171: } ! 172: } ! 173: } ! 174: ! 175: rtdelete(rt) ! 176: struct rt_entry *rt; ! 177: { ! 178: ! 179: TRACE_ACTION(DELETE, rt); ! 180: if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) ! 181: perror("SIOCDELRT"); ! 182: remque(rt); ! 183: free((char *)rt); ! 184: } ! 185: ! 186: rtinit() ! 187: { ! 188: register struct rthash *rh; ! 189: ! 190: for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) ! 191: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; ! 192: for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) ! 193: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; ! 194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.