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

Defined functions

rtadd defined in line 106; used 5 times
rtchange defined in line 167; used 2 times
rtdefault defined in line 232; used 1 times
rtinit defined in line 240; used 1 times
rtlookup defined in line 32; used 3 times

Defined variables

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

Defined macros

DEBUG defined in line 20; used 2 times
Last modified: 1987-07-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2489
Valid CSS Valid XHTML 1.0 Strict