Annotation of 43BSDReno/sbin/routed/input.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: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)input.c    5.22 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: /*
                     25:  * Routing Table Management Daemon
                     26:  */
                     27: #include "defs.h"
                     28: #include <sys/syslog.h>
                     29: 
                     30: /*
                     31:  * Process a newly received packet.
                     32:  */
                     33: rip_input(from, rip, size)
                     34:        struct sockaddr *from;
                     35:        register struct rip *rip;
                     36:        int size;
                     37: {
                     38:        register struct rt_entry *rt;
                     39:        register struct netinfo *n;
                     40:        register struct interface *ifp;
                     41:        struct interface *if_ifwithdstaddr();
                     42:        int count, changes = 0;
                     43:        register struct afswitch *afp;
                     44:        static struct sockaddr badfrom, badfrom2;
                     45: 
                     46:        ifp = 0;
                     47:        TRACE_INPUT(ifp, from, (char *)rip, size);
                     48:        if (from->sa_family >= af_max ||
                     49:            (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) {
                     50:                syslog(LOG_INFO,
                     51:         "\"from\" address in unsupported address family (%d), cmd %d\n",
                     52:                    from->sa_family, rip->rip_cmd);
                     53:                return;
                     54:        }
                     55:        if (rip->rip_vers == 0) {
                     56:                syslog(LOG_ERR,
                     57:                    "RIP version 0 packet received from %s! (cmd %d)",
                     58:                    (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd);
                     59:                return;
                     60:        }
                     61:        switch (rip->rip_cmd) {
                     62: 
                     63:        case RIPCMD_REQUEST:
                     64:                n = rip->rip_nets;
                     65:                count = size - ((char *)n - (char *)rip);
                     66:                if (count < sizeof (struct netinfo))
                     67:                        return;
                     68:                for (; count > 0; n++) {
                     69:                        if (count < sizeof (struct netinfo))
                     70:                                break;
                     71:                        count -= sizeof (struct netinfo);
                     72: 
                     73: #if BSD < 198810
                     74:                        if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
                     75:                            n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
                     76: #else
                     77: #define osa(x) ((struct osockaddr *)(&(x)))
                     78:                            n->rip_dst.sa_family =
                     79:                                        ntohs(osa(n->rip_dst)->sa_family);
                     80:                            n->rip_dst.sa_len = sizeof(n->rip_dst);
                     81: #endif
                     82:                        n->rip_metric = ntohl(n->rip_metric);
                     83:                        /* 
                     84:                         * A single entry with sa_family == AF_UNSPEC and
                     85:                         * metric ``infinity'' means ``all routes''.
                     86:                         * We respond to routers only if we are acting
                     87:                         * as a supplier, or to anyone other than a router
                     88:                         * (eg, query).
                     89:                         */
                     90:                        if (n->rip_dst.sa_family == AF_UNSPEC &&
                     91:                            n->rip_metric == HOPCNT_INFINITY && count == 0) {
                     92:                                if (supplier || (*afp->af_portmatch)(from) == 0)
                     93:                                        supply(from, 0, 0, 0);
                     94:                                return;
                     95:                        }
                     96:                        if (n->rip_dst.sa_family < af_max &&
                     97:                            afswitch[n->rip_dst.sa_family].af_hash)
                     98:                                rt = rtlookup(&n->rip_dst);
                     99:                        else
                    100:                                rt = 0;
                    101: #define min(a, b) (a < b ? a : b)
                    102:                        n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
                    103:                                min(rt->rt_metric + 1, HOPCNT_INFINITY);
                    104: #if BSD < 198810
                    105:                        if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
                    106:                            n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
                    107: #else
                    108:                            osa(n->rip_dst)->sa_family =
                    109:                                                htons(n->rip_dst.sa_family);
                    110: #endif
                    111:                        n->rip_metric = htonl(n->rip_metric);
                    112:                }
                    113:                rip->rip_cmd = RIPCMD_RESPONSE;
                    114:                bcopy((char *)rip, packet, size);
                    115:                (*afp->af_output)(s, 0, from, size);
                    116:                return;
                    117: 
                    118:        case RIPCMD_TRACEON:
                    119:        case RIPCMD_TRACEOFF:
                    120:                /* verify message came from a privileged port */
                    121:                if ((*afp->af_portcheck)(from) == 0)
                    122:                        return;
                    123:                if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
                    124:                    (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
                    125:                    ifp->int_flags & IFF_PASSIVE) {
                    126:                        syslog(LOG_ERR, "trace command from unknown router, %s",
                    127:                            (*afswitch[from->sa_family].af_format)(from));
                    128:                        return;
                    129:                }
                    130:                ((char *)rip)[size] = '\0';
                    131:                if (rip->rip_cmd == RIPCMD_TRACEON)
                    132:                        traceon(rip->rip_tracefile);
                    133:                else
                    134:                        traceoff();
                    135:                return;
                    136: 
                    137:        case RIPCMD_RESPONSE:
                    138:                /* verify message came from a router */
                    139:                if ((*afp->af_portmatch)(from) == 0)
                    140:                        return;
                    141:                (*afp->af_canon)(from);
                    142:                /* are we talking to ourselves? */
                    143:                ifp = if_ifwithaddr(from);
                    144:                if (ifp) {
                    145:                        if (ifp->int_flags & IFF_PASSIVE) {
                    146:                                syslog(LOG_ERR,
                    147:                                  "bogus input (from passive interface, %s)",
                    148:                                  (*afswitch[from->sa_family].af_format)(from));
                    149:                                return;
                    150:                        }
                    151:                        rt = rtfind(from);
                    152:                        if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
                    153:                            rt->rt_metric >= ifp->int_metric) 
                    154:                                addrouteforif(ifp);
                    155:                        else
                    156:                                rt->rt_timer = 0;
                    157:                        return;
                    158:                }
                    159:                /*
                    160:                 * Update timer for interface on which the packet arrived.
                    161:                 * If from other end of a point-to-point link that isn't
                    162:                 * in the routing tables, (re-)add the route.
                    163:                 */
                    164:                if ((rt = rtfind(from)) &&
                    165:                    (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
                    166:                        rt->rt_timer = 0;
                    167:                else if ((ifp = if_ifwithdstaddr(from)) &&
                    168:                    (rt == 0 || rt->rt_metric >= ifp->int_metric))
                    169:                        addrouteforif(ifp);
                    170:                /*
                    171:                 * "Authenticate" router from which message originated.
                    172:                 * We accept routing packets from routers directly connected
                    173:                 * via broadcast or point-to-point networks,
                    174:                 * and from those listed in /etc/gateways.
                    175:                 */
                    176:                if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags &
                    177:                    (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 ||
                    178:                    ifp->int_flags & IFF_PASSIVE) {
                    179:                        if (bcmp((char *)from, (char *)&badfrom,
                    180:                            sizeof(badfrom)) != 0) {
                    181:                                syslog(LOG_ERR,
                    182:                                  "packet from unknown router, %s",
                    183:                                  (*afswitch[from->sa_family].af_format)(from));
                    184:                                badfrom = *from;
                    185:                        }
                    186:                        return;
                    187:                }
                    188:                size -= 4 * sizeof (char);
                    189:                n = rip->rip_nets;
                    190:                for (; size > 0; size -= sizeof (struct netinfo), n++) {
                    191:                        if (size < sizeof (struct netinfo))
                    192:                                break;
                    193: #if BSD < 198810
                    194:                        if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
                    195:                                n->rip_dst.sa_family =
                    196:                                        ntohs(n->rip_dst.sa_family);
                    197: #else
                    198:                            n->rip_dst.sa_family =
                    199:                                        ntohs(osa(n->rip_dst)->sa_family);
                    200:                            n->rip_dst.sa_len = sizeof(n->rip_dst);
                    201: #endif
                    202:                        n->rip_metric = ntohl(n->rip_metric);
                    203:                        if (n->rip_dst.sa_family >= af_max ||
                    204:                            (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
                    205:                            (int (*)())0) {
                    206:                                syslog(LOG_INFO,
                    207:                "route in unsupported address family (%d), from %s (af %d)\n",
                    208:                                   n->rip_dst.sa_family,
                    209:                                   (*afswitch[from->sa_family].af_format)(from),
                    210:                                   from->sa_family);
                    211:                                continue;
                    212:                        }
                    213:                        if (((*afp->af_checkhost)(&n->rip_dst)) == 0) {
                    214:                                syslog(LOG_DEBUG,
                    215:                                    "bad host in route from %s (af %d)\n",
                    216:                                   (*afswitch[from->sa_family].af_format)(from),
                    217:                                   from->sa_family);
                    218:                                continue;
                    219:                        }
                    220:                        if (n->rip_metric == 0 ||
                    221:                            (unsigned) n->rip_metric > HOPCNT_INFINITY) {
                    222:                                if (bcmp((char *)from, (char *)&badfrom2,
                    223:                                    sizeof(badfrom2)) != 0) {
                    224:                                        syslog(LOG_ERR,
                    225:                                            "bad metric (%d) from %s\n",
                    226:                                            n->rip_metric,
                    227:                                  (*afswitch[from->sa_family].af_format)(from));
                    228:                                        badfrom2 = *from;
                    229:                                }
                    230:                                continue;
                    231:                        }
                    232:                        /*
                    233:                         * Adjust metric according to incoming interface.
                    234:                         */
                    235:                        if ((unsigned) n->rip_metric < HOPCNT_INFINITY)
                    236:                                n->rip_metric += ifp->int_metric;
                    237:                        if ((unsigned) n->rip_metric > HOPCNT_INFINITY)
                    238:                                n->rip_metric = HOPCNT_INFINITY;
                    239:                        rt = rtlookup(&n->rip_dst);
                    240:                        if (rt == 0 ||
                    241:                            (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
                    242:                            (RTS_INTERNAL|RTS_INTERFACE)) {
                    243:                                /*
                    244:                                 * If we're hearing a logical network route
                    245:                                 * back from a peer to which we sent it,
                    246:                                 * ignore it.
                    247:                                 */
                    248:                                if (rt && rt->rt_state & RTS_SUBNET &&
                    249:                                    (*afp->af_sendroute)(rt, from))
                    250:                                        continue;
                    251:                                if ((unsigned)n->rip_metric < HOPCNT_INFINITY) {
                    252:                                    /*
                    253:                                     * Look for an equivalent route that
                    254:                                     * includes this one before adding
                    255:                                     * this route.
                    256:                                     */
                    257:                                    rt = rtfind(&n->rip_dst);
                    258:                                    if (rt && equal(from, &rt->rt_router))
                    259:                                            continue;
                    260:                                    rtadd(&n->rip_dst, from, n->rip_metric, 0);
                    261:                                    changes++;
                    262:                                }
                    263:                                continue;
                    264:                        }
                    265: 
                    266:                        /*
                    267:                         * Update if from gateway and different,
                    268:                         * shorter, or equivalent but old route
                    269:                         * is getting stale.
                    270:                         */
                    271:                        if (equal(from, &rt->rt_router)) {
                    272:                                if (n->rip_metric != rt->rt_metric) {
                    273:                                        rtchange(rt, from, n->rip_metric);
                    274:                                        changes++;
                    275:                                        rt->rt_timer = 0;
                    276:                                        if (rt->rt_metric >= HOPCNT_INFINITY)
                    277:                                                rt->rt_timer =
                    278:                                                    GARBAGE_TIME - EXPIRE_TIME;
                    279:                                } else if (rt->rt_metric < HOPCNT_INFINITY)
                    280:                                        rt->rt_timer = 0;
                    281:                        } else if ((unsigned) n->rip_metric < rt->rt_metric ||
                    282:                            (rt->rt_metric == n->rip_metric &&
                    283:                            rt->rt_timer > (EXPIRE_TIME/2) &&
                    284:                            (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
                    285:                                rtchange(rt, from, n->rip_metric);
                    286:                                changes++;
                    287:                                rt->rt_timer = 0;
                    288:                        }
                    289:                }
                    290:                break;
                    291:        }
                    292: 
                    293:        /*
                    294:         * If changes have occurred, and if we have not sent a broadcast
                    295:         * recently, send a dynamic update.  This update is sent only
                    296:         * on interfaces other than the one on which we received notice
                    297:         * of the change.  If we are within MIN_WAITTIME of a full update,
                    298:         * don't bother sending; if we just sent a dynamic update
                    299:         * and set a timer (nextbcast), delay until that time.
                    300:         * If we just sent a full update, delay the dynamic update.
                    301:         * Set a timer for a randomized value to suppress additional
                    302:         * dynamic updates until it expires; if we delayed sending
                    303:         * the current changes, set needupdate.
                    304:         */
                    305:        if (changes && supplier &&
                    306:           now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
                    307:                u_long delay;
                    308:                extern long random();
                    309: 
                    310:                if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
                    311:                    timercmp(&nextbcast, &now, <)) {
                    312:                        if (traceactions)
                    313:                                fprintf(ftrace, "send dynamic update\n");
                    314:                        toall(supply, RTS_CHANGED, ifp);
                    315:                        lastbcast = now;
                    316:                        needupdate = 0;
                    317:                        nextbcast.tv_sec = 0;
                    318:                } else {
                    319:                        needupdate++;
                    320:                        if (traceactions)
                    321:                                fprintf(ftrace, "delay dynamic update\n");
                    322:                }
                    323: #define RANDOMDELAY()  (MIN_WAITTIME * 1000000 + \
                    324:                (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
                    325: 
                    326:                if (nextbcast.tv_sec == 0) {
                    327:                        delay = RANDOMDELAY();
                    328:                        if (traceactions)
                    329:                                fprintf(ftrace,
                    330:                                    "inhibit dynamic update for %d usec\n",
                    331:                                    delay);
                    332:                        nextbcast.tv_sec = delay / 1000000;
                    333:                        nextbcast.tv_usec = delay % 1000000;
                    334:                        timevaladd(&nextbcast, &now);
                    335:                        /*
                    336:                         * If the next possibly dynamic update
                    337:                         * is within MIN_WAITTIME of the next full update,
                    338:                         * force the delay past the full update,
                    339:                         * or we might send a dynamic update just before
                    340:                         * the full update.
                    341:                         */
                    342:                        if (nextbcast.tv_sec > lastfullupdate.tv_sec +
                    343:                            SUPPLY_INTERVAL - MIN_WAITTIME)
                    344:                                nextbcast.tv_sec = lastfullupdate.tv_sec +
                    345:                                    SUPPLY_INTERVAL + 1;
                    346:                }
                    347:        }
                    348: }

unix.superglobalmegacorp.com

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