Annotation of 43BSD/etc/routed/tables.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.