|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: */ ! 7: ! 8: ! 9: #ifndef lint ! 10: static char sccsid[] = "@(#)tables.c 5.5 (Berkeley) 2/14/86"; ! 11: #endif not lint ! 12: ! 13: /* ! 14: * Routing Table Management Daemon ! 15: */ ! 16: #include "defs.h" ! 17: #include <sys/ioctl.h> ! 18: #include <errno.h> ! 19: ! 20: #ifndef DEBUG ! 21: #define DEBUG 0 ! 22: #endif ! 23: ! 24: int install = !DEBUG; /* if 1 call kernel */ ! 25: int delete = 1; ! 26: /* ! 27: * Lookup dst in the tables for an exact match. ! 28: */ ! 29: struct rt_entry * ! 30: rtlookup(dst) ! 31: struct sockaddr *dst; ! 32: { ! 33: register struct rt_entry *rt; ! 34: register struct rthash *rh; ! 35: register u_int hash; ! 36: struct afhash h; ! 37: int doinghost = 1; ! 38: ! 39: if (dst->sa_family >= AF_MAX) ! 40: return (0); ! 41: (*afswitch[dst->sa_family].af_hash)(dst, &h); ! 42: hash = h.afh_hosthash; ! 43: rh = &hosthash[hash & ROUTEHASHMASK]; ! 44: again: ! 45: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { ! 46: if (rt->rt_hash != hash) ! 47: continue; ! 48: if (equal(&rt->rt_dst, dst)) ! 49: return (rt); ! 50: } ! 51: if (doinghost) { ! 52: doinghost = 0; ! 53: hash = h.afh_nethash; ! 54: rh = &nethash[hash & ROUTEHASHMASK]; ! 55: goto again; ! 56: } ! 57: return (0); ! 58: } ! 59: ! 60: /* ! 61: * Find a route to dst as the kernel would. ! 62: */ ! 63: struct rt_entry * ! 64: rtfind(dst) ! 65: struct sockaddr *dst; ! 66: { ! 67: register struct rt_entry *rt; ! 68: register struct rthash *rh; ! 69: register u_int hash; ! 70: struct afhash h; ! 71: int af = dst->sa_family; ! 72: int doinghost = 1, (*match)(); ! 73: ! 74: if (af >= AF_MAX) ! 75: return (0); ! 76: (*afswitch[af].af_hash)(dst, &h); ! 77: hash = h.afh_hosthash; ! 78: rh = &hosthash[hash & ROUTEHASHMASK]; ! 79: ! 80: again: ! 81: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { ! 82: if (rt->rt_hash != hash) ! 83: continue; ! 84: if (doinghost) { ! 85: if (equal(&rt->rt_dst, dst)) ! 86: return (rt); ! 87: } else { ! 88: if (rt->rt_dst.sa_family == af && ! 89: (*match)(&rt->rt_dst, dst)) ! 90: return (rt); ! 91: } ! 92: } ! 93: if (doinghost) { ! 94: doinghost = 0; ! 95: hash = h.afh_nethash; ! 96: rh = &nethash[hash & ROUTEHASHMASK]; ! 97: match = afswitch[af].af_netmatch; ! 98: goto again; ! 99: } ! 100: return (0); ! 101: } ! 102: ! 103: rtadd(dst, gate, metric, state) ! 104: struct sockaddr *dst, *gate; ! 105: int metric, state; ! 106: { ! 107: struct afhash h; ! 108: register struct rt_entry *rt; ! 109: struct rthash *rh; ! 110: int af = dst->sa_family, flags; ! 111: u_int hash; ! 112: ! 113: if (af >= AF_MAX) ! 114: return; ! 115: (*afswitch[af].af_hash)(dst, &h); ! 116: flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; ! 117: if (flags & RTF_HOST) { ! 118: hash = h.afh_hosthash; ! 119: rh = &hosthash[hash & ROUTEHASHMASK]; ! 120: } else { ! 121: hash = h.afh_nethash; ! 122: rh = &nethash[hash & ROUTEHASHMASK]; ! 123: } ! 124: rt = (struct rt_entry *)malloc(sizeof (*rt)); ! 125: if (rt == 0) ! 126: return; ! 127: rt->rt_hash = hash; ! 128: rt->rt_dst = *dst; ! 129: rt->rt_router = *gate; ! 130: rt->rt_metric = metric; ! 131: rt->rt_timer = 0; ! 132: rt->rt_flags = RTF_UP | flags; ! 133: rt->rt_state = state | RTS_CHANGED; ! 134: rt->rt_ifp = if_ifwithnet(&rt->rt_router); ! 135: if (metric) ! 136: rt->rt_flags |= RTF_GATEWAY; ! 137: insque(rt, rh); ! 138: TRACE_ACTION(ADD, rt); ! 139: /* ! 140: * If the ioctl fails because the gateway is unreachable ! 141: * from this host, discard the entry. This should only ! 142: * occur because of an incorrect entry in /etc/gateways. ! 143: */ ! 144: if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) { ! 145: syslog(LOG_ERR,"SIOCADDRT: %m"); ! 146: if (errno == ENETUNREACH) { ! 147: TRACE_ACTION(DELETE, rt); ! 148: remque(rt); ! 149: free((char *)rt); ! 150: } ! 151: } ! 152: } ! 153: ! 154: rtchange(rt, gate, metric) ! 155: struct rt_entry *rt; ! 156: struct sockaddr *gate; ! 157: short metric; ! 158: { ! 159: int doioctl = 0, metricchanged = 0; ! 160: struct rtentry oldroute; ! 161: ! 162: if (!equal(&rt->rt_router, gate)) ! 163: doioctl++; ! 164: if (metric != rt->rt_metric) ! 165: metricchanged++; ! 166: if (doioctl || metricchanged) { ! 167: TRACE_ACTION(CHANGE FROM, rt); ! 168: if (doioctl) { ! 169: oldroute = rt->rt_rt; ! 170: rt->rt_router = *gate; ! 171: } ! 172: rt->rt_metric = metric; ! 173: if ((rt->rt_state & RTS_INTERFACE) && metric) { ! 174: rt->rt_state &= ~RTS_INTERFACE; ! 175: syslog(LOG_ERR, ! 176: "changing route from interface %s (timed out)", ! 177: rt->rt_ifp->int_name); ! 178: } ! 179: if (metric) ! 180: rt->rt_flags |= RTF_GATEWAY; ! 181: else ! 182: rt->rt_flags &= ~RTF_GATEWAY; ! 183: rt->rt_state |= RTS_CHANGED; ! 184: TRACE_ACTION(CHANGE TO, rt); ! 185: } ! 186: if (doioctl && install) { ! 187: if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) ! 188: syslog(LOG_ERR,"SIOCADDRT %m"); ! 189: if (delete) ! 190: if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) ! 191: syslog(LOG_ERR,"SIOCDELRT %m"); ! 192: } ! 193: } ! 194: ! 195: rtdelete(rt) ! 196: struct rt_entry *rt; ! 197: { ! 198: ! 199: if (rt->rt_state & RTS_INTERFACE) { ! 200: syslog(LOG_ERR, "deleting route to interface %s (timed out)", ! 201: rt->rt_ifp->int_name); ! 202: } ! 203: TRACE_ACTION(DELETE, rt); ! 204: if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) ! 205: perror("SIOCDELRT"); ! 206: remque(rt); ! 207: free((char *)rt); ! 208: } ! 209: ! 210: rtinit() ! 211: { ! 212: register struct rthash *rh; ! 213: ! 214: for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) ! 215: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; ! 216: for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) ! 217: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; ! 218: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.