# 2.11BSD#431 - /usr/src/sys/net/route.c

##### Functions

    rtalloc           X
    rtfree            X
    rtinit            X
    rtioctl           X
    rtredirect        X
    rtrequest         X

##### Variables

    rthashsize        X
    rttrash           X
    wildcard          X

##### Macros

    equal             X

       1: /*
       2:  * Copyright (c) 1980, 1986 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 this notice is preserved and that due credit is given
       7:  * to the University of California at Berkeley. The name of the University
       8:  * may not be used to endorse or promote products derived from this
       9:  * software without specific prior written permission. This software
      10:  * is provided ``as is'' without express or implied warranty.
      11:  *
      12:  *	@(#)route.c	7.3 (Berkeley) 12/30/87
      13:  */
      14:
      15: #include "param.h"
      16: #include "systm.h"
      17: #include "mbuf.h"
      18: #include "protosw.h"
      19: #include "socket.h"
      20: #include "user.h"
      21: #include "ioctl.h"
      22: #include "errno.h"
      23:
      24: #include "if.h"
      25: #include "af.h"
      26: #include "route.h"
      27:
      28: int rttrash;        /* routes not in table but not freed */
      29: struct  sockaddr wildcard;  /* zero valued cookie for wildcard searches */
      30: int rthashsize = RTHASHSIZ; /* for netstat, etc. */
      31:
      32: /*
      33:  * Packet routing routines.
      34:  */
      35: rtalloc(ro)
      36:     register struct route *ro;
      37: {
      38:     register struct rtentry *rt;
      39:     register struct mbuf *m;
      40:     register u_int hash;
      41:     struct sockaddr *dst = &ro->ro_dst;
      42:     int (*match)(), doinghost, s;
      43:     struct afhash h;
      44:     u_int af = dst->sa_family;
      45:     struct mbuf **table;
      46:
      47:     if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
      48:         return;              /* XXX */
      49:     if (af >= AF_MAX)
      50:         return;
      51:     (*afswitch[af].af_hash)(dst, &h);
      52:     match = afswitch[af].af_netmatch;
      53:     hash = h.afh_hosthash, table = rthost, doinghost = 1;
      54:     s = splnet();
      55: again:
      56:     for (m = table[RTHASHMOD(hash)]; m; m = m->m_next) {
      57:         rt = mtod(m, struct rtentry *);
      58:         if (rt->rt_hash != hash)
      59:             continue;
      60:         if ((rt->rt_flags & RTF_UP) == 0 ||
      61:             (rt->rt_ifp->if_flags & IFF_UP) == 0)
      62:             continue;
      63:         if (doinghost) {
      64:             if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst,
      65:                 sizeof (*dst)))
      66:                 continue;
      67:         } else {
      68:             if (rt->rt_dst.sa_family != af ||
      69:                 !(*match)(&rt->rt_dst, dst))
      70:                 continue;
      71:         }
      72:         rt->rt_refcnt++;
      73:         splx(s);
      74:         if (dst == &wildcard)
      75:             rtstat.rts_wildcard++;
      76:         ro->ro_rt = rt;
      77:         return;
      78:     }
      79:     if (doinghost) {
      80:         doinghost = 0;
      81:         hash = h.afh_nethash, table = rtnet;
      82:         goto again;
      83:     }
      84:     /*
      85: 	 * Check for wildcard gateway, by convention network 0.
      86: 	 */
      87:     if (dst != &wildcard) {
      88:         dst = &wildcard, hash = 0;
      89:         goto again;
      90:     }
      91:     splx(s);
      92:     rtstat.rts_unreach++;
      93: }
      94:
      95: rtfree(rt)
      96:     register struct rtentry *rt;
      97: {
      98:
      99:     if (rt == 0)
     100:         panic("rtfree");
     101:     rt->rt_refcnt--;
     102:     if (rt->rt_refcnt == 0 && (rt->rt_flags&RTF_UP) == 0) {
     103:         rttrash--;
     104:         (void) m_free(dtom(rt));
     105:     }
     106: }
     107:
     108: /*
     109:  * Force a routing table entry to the specified
     110:  * destination to go through the given gateway.
     111:  * Normally called as a result of a routing redirect
     112:  * message from the network layer.
     113:  *
     114:  * N.B.: must be called at splnet or higher
     115:  *
     116:  */
     117: rtredirect(dst, gateway, flags, src)
     118:     struct sockaddr *dst, *gateway, *src;
     119:     int flags;
     120: {
     121:     struct route ro;
     122:     register struct rtentry *rt;
     123:
     124:     /* verify the gateway is directly reachable */
     125:     if (ifa_ifwithnet(gateway) == 0) {
     126:         rtstat.rts_badredirect++;
     127:         return;
     128:     }
     129:     ro.ro_dst = *dst;
     130:     ro.ro_rt = 0;
     131:     rtalloc(&ro);
     132:     rt = ro.ro_rt;
     133: #define equal(a1, a2) \
     134:     (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof(struct sockaddr)) == 0)
     135:     /*
     136: 	 * If the redirect isn't from our current router for this dst,
     137: 	 * it's either old or wrong.  If it redirects us to ourselves,
     138: 	 * we have a routing loop, perhaps as a result of an interface
     139: 	 * going down recently.
     140: 	 */
     141:     if ((rt && !equal(src, &rt->rt_gateway)) || ifa_ifwithaddr(gateway)) {
     142:         rtstat.rts_badredirect++;
     143:         if (rt)
     144:             rtfree(rt);
     145:         return;
     146:     }
     147:     /*
     148: 	 * Create a new entry if we just got back a wildcard entry
     149: 	 * or the the lookup failed.  This is necessary for hosts
     150: 	 * which use routing redirects generated by smart gateways
     151: 	 * to dynamically build the routing tables.
     152: 	 */
     153:     if (rt &&
     154:         (*afswitch[dst->sa_family].af_netmatch)(&wildcard, &rt->rt_dst)) {
     155:         rtfree(rt);
     156:         rt = 0;
     157:     }
     158:     if (rt == 0) {
     159:         rtinit(dst, gateway, (int)SIOCADDRT,
     160:             (flags & RTF_HOST) | RTF_GATEWAY | RTF_DYNAMIC);
     161:         rtstat.rts_dynamic++;
     162:         return;
     163:     }
     164:     /*
     165: 	 * Don't listen to the redirect if it's
     166: 	 * for a route to an interface.
     167: 	 */
     168:     if (rt->rt_flags & RTF_GATEWAY) {
     169:         if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
     170:             /*
     171: 			 * Changing from route to net => route to host.
     172: 			 * Create new route, rather than smashing route to net.
     173: 			 */
     174:             rtinit(dst, gateway, (int)SIOCADDRT,
     175:                 flags | RTF_DYNAMIC);
     176:             rtstat.rts_dynamic++;
     177:         } else {
     178:             /*
     179: 			 * Smash the current notion of the gateway to
     180: 			 * this destination.
     181: 			 */
     182:             rt->rt_gateway = *gateway;
     183:             rt->rt_flags |= RTF_MODIFIED;
     184:             rtstat.rts_newgateway++;
     185:         }
     186:     } else
     187:         rtstat.rts_badredirect++;
     188:     rtfree(rt);
     189: }
     190:
     191: /*
     192:  * Routing table ioctl interface.
     193:  */
     194: rtioctl(cmd, data)
     195:     int cmd;
     196:     caddr_t data;
     197: {
     198:
     199:     if (cmd != SIOCADDRT && cmd != SIOCDELRT)
     200:         return (EINVAL);
     201:     if (!suser())
     202:         return (u.u_error);
     203:     return (rtrequest(cmd, (struct rtentry *)data));
     204: }
     205:
     206: /*
     207:  * Carry out a request to change the routing table.  Called by
     208:  * interfaces at boot time to make their ``local routes'' known,
     209:  * for ioctl's, and as the result of routing redirects.
     210:  */
     211: rtrequest(req, entry)
     212:     int req;
     213:     register struct rtentry *entry;
     214: {
     215:     register struct mbuf *m, **mprev;
     216:     struct mbuf **mfirst;
     217:     register struct rtentry *rt;
     218:     struct afhash h;
     219:     int s, error = 0, (*match)();
     220:     u_int af;
     221:     u_int hash;
     222:     struct ifaddr *ifa;
     223:     struct ifaddr *ifa_ifwithdstaddr();
     224:
     225:     af = entry->rt_dst.sa_family;
     226:     if (af >= AF_MAX)
     227:         return (EAFNOSUPPORT);
     228:     (*afswitch[af].af_hash)(&entry->rt_dst, &h);
     229:     if (entry->rt_flags & RTF_HOST) {
     230:         hash = h.afh_hosthash;
     231:         mprev = &rthost[RTHASHMOD(hash)];
     232:     } else {
     233:         hash = h.afh_nethash;
     234:         mprev = &rtnet[RTHASHMOD(hash)];
     235:     }
     236:     match = afswitch[af].af_netmatch;
     237:     s = splimp();
     238:     for (mfirst = mprev; m = *mprev; mprev = &m->m_next) {
     239:         rt = mtod(m, struct rtentry *);
     240:         if (rt->rt_hash != hash)
     241:             continue;
     242:         if (entry->rt_flags & RTF_HOST) {
     243:             if (!equal(&rt->rt_dst, &entry->rt_dst))
     244:                 continue;
     245:         } else {
     246:             if (rt->rt_dst.sa_family != entry->rt_dst.sa_family ||
     247:                 (*match)(&rt->rt_dst, &entry->rt_dst) == 0)
     248:                 continue;
     249:         }
     250:         if (equal(&rt->rt_gateway, &entry->rt_gateway))
     251:             break;
     252:     }
     253:     switch (req) {
     254:
     255:     case SIOCDELRT:
     256:         if (m == 0) {
     257:             error = ESRCH;
     258:             goto bad;
     259:         }
     260:         *mprev = m->m_next;
     261:         if (rt->rt_refcnt > 0) {
     262:             rt->rt_flags &= ~RTF_UP;
     263:             rttrash++;
     264:             m->m_next = 0;
     265:         } else
     266:             (void) m_free(m);
     267:         break;
     268:
     269:     case SIOCADDRT:
     270:         if (m) {
     271:             error = EEXIST;
     272:             goto bad;
     273:         }
     274:         if ((entry->rt_flags & RTF_GATEWAY) == 0) {
     275:             /*
     276: 			 * If we are adding a route to an interface,
     277: 			 * and the interface is a pt to pt link
     278: 			 * we should search for the destination
     279: 			 * as our clue to the interface.  Otherwise
     280: 			 * we can use the local address.
     281: 			 */
     282:             ifa = 0;
     283:             if (entry->rt_flags & RTF_HOST)
     284:                 ifa = ifa_ifwithdstaddr(&entry->rt_dst);
     285:             if (ifa == 0)
     286:                 ifa = ifa_ifwithaddr(&entry->rt_gateway);
     287:         } else {
     288:             /*
     289: 			 * If we are adding a route to a remote net
     290: 			 * or host, the gateway may still be on the
     291: 			 * other end of a pt to pt link.
     292: 			 */
     293:             ifa = ifa_ifwithdstaddr(&entry->rt_gateway);
     294:         }
     295:         if (ifa == 0) {
     296:             ifa = ifa_ifwithnet(&entry->rt_gateway);
     297:             if (ifa == 0) {
     298:                 error = ENETUNREACH;
     299:                 goto bad;
     300:             }
     301:         }
     302:         m = m_get(M_DONTWAIT, MT_RTABLE);
     303:         if (m == 0) {
     304:             error = ENOBUFS;
     305:             goto bad;
     306:         }
     307:         m->m_next = *mfirst;
     308:         *mfirst = m;
     309:         m->m_off = MMINOFF;
     310:         m->m_len = sizeof (struct rtentry);
     311:         rt = mtod(m, struct rtentry *);
     312:         rt->rt_hash = hash;
     313:         rt->rt_dst = entry->rt_dst;
     314:         rt->rt_gateway = entry->rt_gateway;
     315:         rt->rt_flags = RTF_UP |
     316:             (entry->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_DYNAMIC));
     317:         rt->rt_refcnt = 0;
     318:         rt->rt_use = 0;
     319:         rt->rt_ifp = ifa->ifa_ifp;
     320:         break;
     321:     }
     322: bad:
     323:     splx(s);
     324:     return (error);
     325: }
     326:
     327: /*
     328:  * Set up a routing table entry, normally
     329:  * for an interface.
     330:  */
     331: rtinit(dst, gateway, cmd, flags)
     332:     struct sockaddr *dst, *gateway;
     333:     int cmd, flags;
     334: {
     335:     struct rtentry route;
     336:
     337:     bzero((caddr_t)&route, sizeof (route));
     338:     route.rt_dst = *dst;
     339:     route.rt_gateway = *gateway;
     340:     route.rt_flags = flags;
     341:     (void) rtrequest(cmd, &route);
     342: }

#### Defined functions

rtalloc defined in line 35; used 1 times

- in line 131

rtfree defined in line 95; used 3 times

- in line 144, 155, 188

rtinit defined in line 331; used 2 times

- in line 159, 174

rtioctl defined in line 194; never used
rtredirect defined in line 117; never used
rtrequest defined in line 211; used 2 times

- in line 203, 341

#### Defined variables

rthashsize defined in line 30; never used
rttrash defined in line 28; used 2 times

- in line 103, 263

wildcard defined in line 29; used 4 times

- in line 74, 87-88(2), 154

#### Defined macros

equal defined in line 133; used 3 times

- in line 141, 243, 250

Last modified: 1988-04-28 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1654 |