1: /*
   2:  * Copyright (c) 1983 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: #ifndef lint
   8: static char sccsid[] = "@(#)tables.c	5.5 (Berkeley) 5/28/86";
   9: #endif not lint
  10: 
  11: /*
  12:  * Routing Table Management Daemon
  13:  */
  14: #include "defs.h"
  15: #include <sys/ioctl.h>
  16: #include <errno.h>
  17: #include <syslog.h>
  18: 
  19: #ifndef DEBUG
  20: #define DEBUG   0
  21: #endif
  22: 
  23: int install = !DEBUG;       /* if 1 call kernel */
  24: 
  25: /*
  26:  * Lookup dst in the tables for an exact match.
  27:  */
  28: struct rt_entry *
  29: rtlookup(dst)
  30:     struct sockaddr *dst;
  31: {
  32:     register struct rt_entry *rt;
  33:     register struct rthash *rh;
  34:     register u_int hash;
  35:     struct afhash h;
  36:     int doinghost = 1;
  37: 
  38:     if (dst->sa_family >= af_max)
  39:         return (0);
  40:     (*afswitch[dst->sa_family].af_hash)(dst, &h);
  41:     hash = h.afh_hosthash;
  42:     rh = &hosthash[hash & ROUTEHASHMASK];
  43: again:
  44:     for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
  45:         if (rt->rt_hash != hash)
  46:             continue;
  47:         if (equal(&rt->rt_dst, dst))
  48:             return (rt);
  49:     }
  50:     if (doinghost) {
  51:         doinghost = 0;
  52:         hash = h.afh_nethash;
  53:         rh = &nethash[hash & ROUTEHASHMASK];
  54:         goto again;
  55:     }
  56:     return (0);
  57: }
  58: 
  59: /*
  60:  * Find a route to dst as the kernel would.
  61:  */
  62: struct rt_entry *
  63: rtfind(dst)
  64:     struct sockaddr *dst;
  65: {
  66:     register struct rt_entry *rt;
  67:     register struct rthash *rh;
  68:     register u_int hash;
  69:     struct afhash h;
  70:     int af = dst->sa_family;
  71:     int doinghost = 1, (*match)();
  72: 
  73:     if (af >= af_max)
  74:         return (0);
  75:     (*afswitch[af].af_hash)(dst, &h);
  76:     hash = h.afh_hosthash;
  77:     rh = &hosthash[hash & ROUTEHASHMASK];
  78: 
  79: again:
  80:     for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
  81:         if (rt->rt_hash != hash)
  82:             continue;
  83:         if (doinghost) {
  84:             if (equal(&rt->rt_dst, dst))
  85:                 return (rt);
  86:         } else {
  87:             if (rt->rt_dst.sa_family == af &&
  88:                 (*match)(&rt->rt_dst, dst))
  89:                 return (rt);
  90:         }
  91:     }
  92:     if (doinghost) {
  93:         doinghost = 0;
  94:         hash = h.afh_nethash;
  95:         rh = &nethash[hash & ROUTEHASHMASK];
  96:         match = afswitch[af].af_netmatch;
  97:         goto again;
  98:     }
  99:     return (0);
 100: }
 101: 
 102: rtadd(dst, gate, metric, state)
 103:     struct sockaddr *dst, *gate;
 104:     int metric, state;
 105: {
 106:     struct afhash h;
 107:     register struct rt_entry *rt;
 108:     struct rthash *rh;
 109:     int af = dst->sa_family, flags;
 110:     u_int hash;
 111: 
 112:     if (af >= af_max)
 113:         return;
 114:     (*afswitch[af].af_hash)(dst, &h);
 115:     flags = (*afswitch[af].af_rtflags)(dst);
 116:     /*
 117: 	 * Subnet flag isn't visible to kernel, move to state.	XXX
 118: 	 */
 119:     if (flags & RTF_SUBNET) {
 120:         state |= RTS_SUBNET;
 121:         flags &= ~RTF_SUBNET;
 122:     }
 123:     if (flags & RTF_HOST) {
 124:         hash = h.afh_hosthash;
 125:         rh = &hosthash[hash & ROUTEHASHMASK];
 126:     } else {
 127:         hash = h.afh_nethash;
 128:         rh = &nethash[hash & ROUTEHASHMASK];
 129:     }
 130:     rt = (struct rt_entry *)malloc(sizeof (*rt));
 131:     if (rt == 0)
 132:         return;
 133:     rt->rt_hash = hash;
 134:     rt->rt_dst = *dst;
 135:     rt->rt_router = *gate;
 136:     rt->rt_metric = metric;
 137:     rt->rt_timer = 0;
 138:     rt->rt_flags = RTF_UP | flags;
 139:     rt->rt_state = state | RTS_CHANGED;
 140:     rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
 141:     if (rt->rt_ifp == 0)
 142:         rt->rt_ifp = if_ifwithnet(&rt->rt_router);
 143:     if (metric)
 144:         rt->rt_flags |= RTF_GATEWAY;
 145:     insque(rt, rh);
 146:     TRACE_ACTION(ADD, rt);
 147:     /*
 148: 	 * If the ioctl fails because the gateway is unreachable
 149: 	 * from this host, discard the entry.  This should only
 150: 	 * occur because of an incorrect entry in /etc/gateways.
 151: 	 */
 152:     if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
 153:         ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
 154:         perror("SIOCADDRT");
 155:         if (errno == ENETUNREACH) {
 156:             TRACE_ACTION(DELETE, rt);
 157:             remque(rt);
 158:             free((char *)rt);
 159:         }
 160:     }
 161: }
 162: 
 163: rtchange(rt, gate, metric)
 164:     struct rt_entry *rt;
 165:     struct sockaddr *gate;
 166:     short metric;
 167: {
 168:     int doioctl = 0, metricchanged = 0;
 169:     struct rtentry oldroute;
 170: 
 171:     if (!equal(&rt->rt_router, gate) && (rt->rt_state & RTS_INTERNAL) == 0)
 172:         doioctl++;
 173:     if (metric != rt->rt_metric)
 174:         metricchanged++;
 175:     if (doioctl || metricchanged) {
 176:         TRACE_ACTION(CHANGE FROM, rt);
 177:         if ((rt->rt_state & RTS_INTERFACE) && metric) {
 178:             rt->rt_state &= ~RTS_INTERFACE;
 179:             syslog(LOG_ERR,
 180:                 "changing route from interface %s (timed out)",
 181:                 rt->rt_ifp->int_name);
 182:         }
 183:         if (doioctl) {
 184:             oldroute = rt->rt_rt;
 185:             rt->rt_router = *gate;
 186:             rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
 187:             if (rt->rt_ifp == 0)
 188:                 rt->rt_ifp = if_ifwithnet(&rt->rt_router);
 189:         }
 190:         rt->rt_metric = metric;
 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:             perror("SIOCADDRT");
 201:         if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
 202:             perror("SIOCDELRT");
 203:     }
 204: }
 205: 
 206: rtdelete(rt)
 207:     struct rt_entry *rt;
 208: {
 209: 
 210:     if (rt->rt_state & RTS_INTERFACE)
 211:         syslog(LOG_ERR, "deleting route to interface %s (timed out)",
 212:             rt->rt_ifp->int_name);
 213:     TRACE_ACTION(DELETE, rt);
 214:     if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
 215:         ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
 216:         perror("SIOCDELRT");
 217:     remque(rt);
 218:     free((char *)rt);
 219: }
 220: 
 221: /*
 222:  * If we have an interface to the wide, wide world,
 223:  * add an entry for an Internet default route (wildcard) to the internal
 224:  * tables and advertise it.  This route is not added to the kernel routes,
 225:  * but this entry prevents us from listening to other people's defaults
 226:  * and installing them in the kernel here.
 227:  */
 228: rtdefault()
 229: {
 230:     extern struct sockaddr inet_default;
 231: 
 232:     rtadd(&inet_default, &inet_default, 0,
 233:         RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
 234: }
 235: 
 236: rtinit()
 237: {
 238:     register struct rthash *rh;
 239: 
 240:     for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
 241:         rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 242:     for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
 243:         rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 244: }

Defined functions

rtadd defined in line 102; used 5 times
rtchange defined in line 163; used 2 times
rtdefault defined in line 228; used 1 times
rtinit defined in line 236; used 1 times
rtlookup defined in line 28; used 3 times

Defined variables

install defined in line 23; used 3 times
sccsid defined in line 8; never used

Defined macros

DEBUG defined in line 20; used 2 times
Last modified: 1986-05-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1498
Valid CSS Valid XHTML 1.0 Strict