Annotation of 43BSDTahoe/etc/routed/tables.c, revision 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.