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

1.1       root        1: /*
                      2:  * Copyright (c) 1983, 1988 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: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)tables.c   5.13 (Berkeley) 6/6/88";
                     15: #endif /* not lint */
                     16: 
                     17: /*
                     18:  * Routing Table Management Daemon
                     19:  */
                     20: #include "defs.h"
                     21: #include <sys/ioctl.h>
                     22: #include <errno.h>
                     23: #include <sys/syslog.h>
                     24: 
                     25: #ifndef DEBUG
                     26: #define        DEBUG   0
                     27: #endif
                     28: 
                     29: int    install = !DEBUG;               /* if 1 call kernel */
                     30: 
                     31: /*
                     32:  * Lookup dst in the tables for an exact match.
                     33:  */
                     34: struct rt_entry *
                     35: rtlookup(dst)
                     36:        struct sockaddr *dst;
                     37: {
                     38:        register struct rt_entry *rt;
                     39:        register struct rthash *rh;
                     40:        register u_int hash;
                     41:        struct afhash h;
                     42:        int doinghost = 1;
                     43: 
                     44:        if (dst->sa_family >= af_max)
                     45:                return (0);
                     46:        (*afswitch[dst->sa_family].af_hash)(dst, &h);
                     47:        hash = h.afh_hosthash;
                     48:        rh = &hosthash[hash & ROUTEHASHMASK];
                     49: again:
                     50:        for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
                     51:                if (rt->rt_hash != hash)
                     52:                        continue;
                     53:                if (equal(&rt->rt_dst, dst))
                     54:                        return (rt);
                     55:        }
                     56:        if (doinghost) {
                     57:                doinghost = 0;
                     58:                hash = h.afh_nethash;
                     59:                rh = &nethash[hash & ROUTEHASHMASK];
                     60:                goto again;
                     61:        }
                     62:        return (0);
                     63: }
                     64: 
                     65: struct sockaddr wildcard;      /* zero valued cookie for wildcard searches */
                     66: 
                     67: /*
                     68:  * Find a route to dst as the kernel would.
                     69:  */
                     70: struct rt_entry *
                     71: rtfind(dst)
                     72:        struct sockaddr *dst;
                     73: {
                     74:        register struct rt_entry *rt;
                     75:        register struct rthash *rh;
                     76:        register u_int hash;
                     77:        struct afhash h;
                     78:        int af = dst->sa_family;
                     79:        int doinghost = 1, (*match)();
                     80: 
                     81:        if (af >= af_max)
                     82:                return (0);
                     83:        (*afswitch[af].af_hash)(dst, &h);
                     84:        hash = h.afh_hosthash;
                     85:        rh = &hosthash[hash & ROUTEHASHMASK];
                     86: 
                     87: again:
                     88:        for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
                     89:                if (rt->rt_hash != hash)
                     90:                        continue;
                     91:                if (doinghost) {
                     92:                        if (equal(&rt->rt_dst, dst))
                     93:                                return (rt);
                     94:                } else {
                     95:                        if (rt->rt_dst.sa_family == af &&
                     96:                            (*match)(&rt->rt_dst, dst))
                     97:                                return (rt);
                     98:                }
                     99:        }
                    100:        if (doinghost) {
                    101:                doinghost = 0;
                    102:                hash = h.afh_nethash;
                    103:                rh = &nethash[hash & ROUTEHASHMASK];
                    104:                match = afswitch[af].af_netmatch;
                    105:                goto again;
                    106:        }
                    107: #ifdef notyet
                    108:        /*
                    109:         * Check for wildcard gateway, by convention network 0.
                    110:         */
                    111:        if (dst != &wildcard) {
                    112:                dst = &wildcard, hash = 0;
                    113:                goto again;
                    114:        }
                    115: #endif
                    116:        return (0);
                    117: }
                    118: 
                    119: rtadd(dst, gate, metric, state)
                    120:        struct sockaddr *dst, *gate;
                    121:        int metric, state;
                    122: {
                    123:        struct afhash h;
                    124:        register struct rt_entry *rt;
                    125:        struct rthash *rh;
                    126:        int af = dst->sa_family, flags;
                    127:        u_int hash;
                    128: 
                    129:        if (af >= af_max)
                    130:                return;
                    131:        (*afswitch[af].af_hash)(dst, &h);
                    132:        flags = (*afswitch[af].af_rtflags)(dst);
                    133:        /*
                    134:         * Subnet flag isn't visible to kernel, move to state.  XXX
                    135:         */
                    136:        if (flags & RTF_SUBNET) {
                    137:                state |= RTS_SUBNET;
                    138:                flags &= ~RTF_SUBNET;
                    139:        }
                    140:        if (flags & RTF_HOST) {
                    141:                hash = h.afh_hosthash;
                    142:                rh = &hosthash[hash & ROUTEHASHMASK];
                    143:        } else {
                    144:                hash = h.afh_nethash;
                    145:                rh = &nethash[hash & ROUTEHASHMASK];
                    146:        }
                    147:        rt = (struct rt_entry *)malloc(sizeof (*rt));
                    148:        if (rt == 0)
                    149:                return;
                    150:        rt->rt_hash = hash;
                    151:        rt->rt_dst = *dst;
                    152:        rt->rt_router = *gate;
                    153:        rt->rt_timer = 0;
                    154:        rt->rt_flags = RTF_UP | flags;
                    155:        rt->rt_state = state | RTS_CHANGED;
                    156:        rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
                    157:        if (rt->rt_ifp == 0)
                    158:                rt->rt_ifp = if_ifwithnet(&rt->rt_router);
                    159:        if ((state & RTS_INTERFACE) == 0)
                    160:                rt->rt_flags |= RTF_GATEWAY;
                    161:        rt->rt_metric = metric;
                    162:        insque(rt, rh);
                    163:        TRACE_ACTION("ADD", rt);
                    164:        /*
                    165:         * If the ioctl fails because the gateway is unreachable
                    166:         * from this host, discard the entry.  This should only
                    167:         * occur because of an incorrect entry in /etc/gateways.
                    168:         */
                    169:        if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
                    170:            ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
                    171:                if (errno != EEXIST && gate->sa_family < af_max)
                    172:                        syslog(LOG_ERR,
                    173:                        "adding route to net/host %s through gateway %s: %m\n",
                    174:                           (*afswitch[dst->sa_family].af_format)(dst),
                    175:                           (*afswitch[gate->sa_family].af_format)(gate));
                    176:                perror("SIOCADDRT");
                    177:                if (errno == ENETUNREACH) {
                    178:                        TRACE_ACTION("DELETE", rt);
                    179:                        remque(rt);
                    180:                        free((char *)rt);
                    181:                }
                    182:        }
                    183: }
                    184: 
                    185: rtchange(rt, gate, metric)
                    186:        struct rt_entry *rt;
                    187:        struct sockaddr *gate;
                    188:        short metric;
                    189: {
                    190:        int add = 0, delete = 0;
                    191:        struct rtentry oldroute;
                    192: 
                    193:        if ((rt->rt_state & RTS_INTERNAL) == 0) {
                    194:                /*
                    195:                 * If changing to different router, we need to add
                    196:                 * new route and delete old one if in the kernel.
                    197:                 * If the router is the same, we need to delete
                    198:                 * the route if has become unreachable, or re-add
                    199:                 * it if it had been unreachable.
                    200:                 */
                    201:                if (!equal(&rt->rt_router, gate)) {
                    202:                        add++;
                    203:                        if (rt->rt_metric != HOPCNT_INFINITY)
                    204:                                delete++;
                    205:                } else if (metric == HOPCNT_INFINITY)
                    206:                        delete++;
                    207:                else if (rt->rt_metric == HOPCNT_INFINITY)
                    208:                        add++;
                    209:        }
                    210:        if (!equal(&rt->rt_router, gate)) {
                    211:                TRACE_ACTION("CHANGE FROM ", rt);
                    212:        } else if (metric != rt->rt_metric)
                    213:                TRACE_NEWMETRIC(rt, metric);
                    214:        if (delete)
                    215:                oldroute = rt->rt_rt;
                    216:        if ((rt->rt_state & RTS_INTERFACE) && delete) {
                    217:                rt->rt_state &= ~RTS_INTERFACE;
                    218:                rt->rt_flags |= RTF_GATEWAY;
                    219:                if (metric > rt->rt_metric && delete)
                    220:                        syslog(LOG_ERR, "%s route to interface %s (timed out)",
                    221:                            add? "changing" : "deleting",
                    222:                            rt->rt_ifp->int_name);
                    223:        }
                    224:        if (add) {
                    225:                rt->rt_router = *gate;
                    226:                rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
                    227:                if (rt->rt_ifp == 0)
                    228:                        rt->rt_ifp = if_ifwithnet(&rt->rt_router);
                    229:        }
                    230:        rt->rt_metric = metric;
                    231:        rt->rt_state |= RTS_CHANGED;
                    232:        if (add)
                    233:                TRACE_ACTION("CHANGE TO   ", rt);
                    234:        if (add && install)
                    235:                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                    236:                        perror("SIOCADDRT");
                    237:        if (delete && install)
                    238:                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                    239:                        perror("SIOCDELRT");
                    240: }
                    241: 
                    242: rtdelete(rt)
                    243:        struct rt_entry *rt;
                    244: {
                    245: 
                    246:        TRACE_ACTION("DELETE", rt);
                    247:        if (rt->rt_metric < HOPCNT_INFINITY) {
                    248:            if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
                    249:                syslog(LOG_ERR,
                    250:                    "deleting route to interface %s? (timed out?)",
                    251:                    rt->rt_ifp->int_name);
                    252:            if (install &&
                    253:                (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
                    254:                ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
                    255:                    perror("SIOCDELRT");
                    256:        }
                    257:        remque(rt);
                    258:        free((char *)rt);
                    259: }
                    260: 
                    261: rtdeleteall(s)
                    262:        int s;
                    263: {
                    264:        register struct rthash *rh;
                    265:        register struct rt_entry *rt;
                    266:        struct rthash *base = hosthash;
                    267:        int doinghost = 1;
                    268: 
                    269: again:
                    270:        for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
                    271:                rt = rh->rt_forw;
                    272:                for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
                    273:                        if (rt->rt_state & RTS_INTERFACE ||
                    274:                            rt->rt_metric >= HOPCNT_INFINITY)
                    275:                                continue;
                    276:                        TRACE_ACTION("DELETE", rt);
                    277:                        if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 &&
                    278:                            ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
                    279:                                perror("SIOCDELRT");
                    280:                }
                    281:        }
                    282:        if (doinghost) {
                    283:                doinghost = 0;
                    284:                base = nethash;
                    285:                goto again;
                    286:        }
                    287:        exit(s);
                    288: }
                    289: 
                    290: /*
                    291:  * If we have an interface to the wide, wide world,
                    292:  * add an entry for an Internet default route (wildcard) to the internal
                    293:  * tables and advertise it.  This route is not added to the kernel routes,
                    294:  * but this entry prevents us from listening to other people's defaults
                    295:  * and installing them in the kernel here.
                    296:  */
                    297: rtdefault()
                    298: {
                    299:        extern struct sockaddr inet_default;
                    300: 
                    301:        rtadd(&inet_default, &inet_default, 1,
                    302:                RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
                    303: }
                    304: 
                    305: rtinit()
                    306: {
                    307:        register struct rthash *rh;
                    308: 
                    309:        for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
                    310:                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
                    311:        for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
                    312:                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
                    313: }

unix.superglobalmegacorp.com

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