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