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