Annotation of researchv10dc/ipc/internet/routed.c, revision 1.1.1.1

1.1       root        1: #include <sys/param.h>
                      2: #include <fio.h>
                      3: #include <signal.h>
                      4: #include <errno.h>
                      5: #include <sys/filio.h>
                      6: #include <sys/inet/in.h>
                      7: #include <sys/inet/ip_var.h>
                      8: #include <sys/inet/udp_user.h>
                      9: #include "config.h"
                     10: 
                     11: #define IPDEVICE "/dev/ip16"   /* device for getting ip info from */
                     12: #define RPORT 520
                     13: 
                     14: int udpfd, ipfd, verbose, trace, quiet, traceinput, hopoffset;
                     15: extern errno;
                     16: extern int buf_ld;
                     17: extern char *in_ntoa();
                     18: extern u_short cksum();
                     19: 
                     20: struct udppacket {
                     21:        struct udpaddr addr;
                     22:        char buf[4096];
                     23: };
                     24: 
                     25: main(argc, argv)
                     26: char *argv[];
                     27: {
                     28:        int n, i;
                     29:        struct udppacket packet;
                     30:        char *cp;
                     31: 
                     32:        for(i = 1; i < argc; i++){
                     33:                if(argv[i][0] == '-'){
                     34:                        for(cp = argv[i]+1; *cp; cp++){
                     35:                                switch(*cp){
                     36:                                case 'v':
                     37:                                        verbose++;
                     38:                                        break;
                     39:                                case 'q':
                     40:                                        quiet++;
                     41:                                        break;
                     42:                                case 't':
                     43:                                        trace++;
                     44:                                        break;
                     45:                                case 'T':
                     46:                                        traceinput++;
                     47:                                        break;
                     48:                                default:
                     49:                                        if((*cp >= '0' && *cp <= '9') || *cp == '-') {
                     50:                                                hopoffset = atoi(cp);
                     51:                                                while(*cp >= '0' && *cp <= '9')
                     52:                                                        cp++;
                     53:                                                cp--;
                     54:                                        } else {
                     55:                                                fprint(2, "usage: routed [-qtvT#]\n");                                                          exit(1);
                     56:                                        }
                     57:                                        break;
                     58:                                }
                     59:                        }
                     60:                } else
                     61:                        recsafe(argv[i]);
                     62:        }
                     63: 
                     64:        if(verbose || traceinput || trace) {
                     65:                if(hopoffset)
                     66:                        fprint(2, "%s: adding %d to each metric\n", argv[0], hopoffset);
                     67:        }
                     68: 
                     69:        if((udpfd = udp_datagram(RPORT)) < 0) {
                     70:                perror("udp route daemon: no connection");
                     71:                exit(1);
                     72:        }
                     73: 
                     74:        /*
                     75:         *  try pushing bufld, complain but don't exit if unable
                     76:         */
                     77: /*
                     78:        if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){
                     79:                perror("pushing buf_ld");
                     80:        }
                     81:        if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){
                     82:                perror("pushing buf_ld");
                     83:        }
                     84:        if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){
                     85:                perror("pushing buf_ld");
                     86:        }
                     87: */
                     88: 
                     89:        if((ipfd = open(IPDEVICE, 2)) < 0) {
                     90:                perror(IPDEVICE);
                     91:                exit(1);
                     92:        }
                     93: 
                     94:        readgateways();
                     95:        if(!(verbose || traceinput || trace)) {
                     96:                detach("routed");
                     97:                nice(-20);
                     98:        }
                     99:        timer();
                    100: 
                    101: again:
                    102:        while((n = read(udpfd, &packet, sizeof(struct udppacket))) > 0) {
                    103:                routed(&packet, n - sizeof(struct udpaddr));
                    104:        }
                    105:        if(n < 0 && errno == EINTR)
                    106:                goto again;
                    107: }
                    108: 
                    109: 
                    110: /*     protocol.h      4.10    83/08/11        */
                    111: /*
                    112:  * Routing Information Protocol
                    113:  *
                    114:  * Derived from Xerox NS Routing Information Protocol
                    115:  * by changing 32-bit net numbers to sockaddr's and
                    116:  * padding stuff to 32-bit boundaries.
                    117:  */
                    118: #define        RIPVERSION      1
                    119: #define AF_INET                2
                    120: #define AF_UNSPEC      0
                    121: 
                    122: struct sockaddr{
                    123:        short sin_family;
                    124:        u_short sin_port;
                    125:        u_long sin_addr;
                    126:        char sin_zero[8];
                    127: };
                    128: struct netinfo {
                    129:        struct  sockaddr rip_dst;       /* destination net/host */
                    130:        int     rip_metric;             /* cost of route */
                    131: };
                    132: 
                    133: struct rip {
                    134:        u_char  rip_cmd;                /* request/response */
                    135:        u_char  rip_vers;               /* protocol version # */
                    136:        u_char  rip_res1[2];            /* pad to 32-bit boundary */
                    137:        union {
                    138:                struct  netinfo ru_nets[1];     /* variable length... */
                    139:                char    ru_tracefile[1];        /* ditto ... */
                    140:        } ripun;
                    141: #define        rip_nets        ripun.ru_nets
                    142: #define        rip_tracefile   ripun.ru_tracefile
                    143: };
                    144:  
                    145: /*
                    146:  * Packet types.
                    147:  */
                    148: #define        RIPCMD_REQUEST          1       /* want info */
                    149: #define        RIPCMD_RESPONSE         2       /* responding to request */
                    150: #define        RIPCMD_TRACEON          3       /* turn tracing on */
                    151: #define        RIPCMD_TRACEOFF         4       /* turn it off */
                    152: 
                    153: #define        RIPCMD_MAX              5
                    154: #ifdef RIPCMDS
                    155: char *ripcmds[RIPCMD_MAX] =
                    156:   { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" };
                    157: #endif
                    158: 
                    159: #define        HOPCNT_INFINITY         16      /* per Xerox NS */
                    160: #define        MAXPACKETSIZE           488     /* max broadcast size */
                    161: #define MAXROUTESPERPACKET     (MAXPACKETSIZE-4)/sizeof(struct netinfo)
                    162: 
                    163: /*
                    164:  * Timer values used in managing the routing table.
                    165:  * Every update forces an entry's timer to be reset.  After
                    166:  * EXPIRE_TIME without updates, the entry is marked invalid,
                    167:  * but held onto until GARBAGE_TIME so that others may
                    168:  * see it "be deleted".
                    169:  */
                    170: #define        TIMER_RATE              60      /* interval in seconds over which we bcast to all
                    171:                                         * directly connected interfaces */
                    172: 
                    173: #define        EXPIRE_TIME             180     /* time to mark entry invalid */
                    174: #define        GARBAGE_TIME            240     /* time to garbage collect */
                    175: 
                    176: #define NIFS TIMER_RATE
                    177: struct ipif ifs[NIFS];
                    178: int nextifs;                   /* next interface to broadcast to */
                    179: int nifs;                      /* number of functioning interfaces */
                    180: 
                    181: routed(up, len)
                    182:        struct udppacket *up;
                    183:        u_int len;
                    184: {
                    185:        struct rip *rip;
                    186: 
                    187:        if(traceinput)
                    188:                logevent("from %s\n", in_ntoa(up->addr.host));
                    189:        rip = (struct rip *)(up->buf);
                    190:        if(rip->rip_vers != RIPVERSION)
                    191:                return;
                    192:        switch(rip->rip_cmd){
                    193:        case RIPCMD_RESPONSE:
                    194:                if(up->addr.port != RPORT)
                    195:                        logevent("routed: %s %d masquerading as routed\n",
                    196:                                in_host(up->addr.host), up->addr.port);
                    197:                else
                    198:                        response(up, len);
                    199:                break;
                    200:        case RIPCMD_REQUEST:
                    201:                request(up, len);
                    202:                break;
                    203:        default:
                    204:                logevent("routed: %s %d sent strange command %d\n",
                    205:                        in_host(up->addr.host), up->addr.port, rip->rip_cmd);
                    206:                return;
                    207:        }
                    208: }
                    209: 
                    210: /*
                    211:  *  don't believe responses from this host.  no use infinitely
                    212:  *  recursing.
                    213:  */
                    214: response(up, len)
                    215:        struct udppacket *up;
                    216:        u_int len;
                    217: {
                    218:        struct rip *rip;
                    219:        struct sockaddr *sin;
                    220:        struct netinfo *np;
                    221: 
                    222:        rip = (struct rip *)(up->buf);
                    223:        if(myaddr(up->addr.host))
                    224:                return;
                    225:        np = rip->rip_nets;
                    226:        while(np < (struct netinfo *)(&(up->buf[len]))){
                    227:                sin = &(np->rip_dst);
                    228:                np->rip_metric = ntohl(np->rip_metric);
                    229:                sin->sin_port = ntohs(sin->sin_port);
                    230:                sin->sin_addr = ntohl(sin->sin_addr);
                    231:                if(traceinput) {
                    232:                        logevent(" %s %d\n", in_ntoa(sin->sin_addr), np->rip_metric);
                    233:                }
                    234:                if (np->rip_metric > 0 && saferoute(sin->sin_addr) == 0)
                    235:                        rtinstall(sin->sin_addr, up->addr.host, np->rip_metric, 0, -1);
                    236:                np++;
                    237:        }
                    238: }
                    239: 
                    240: /*
                    241:  *  Only accept requests for all routes or for internet routes.
                    242:  *  In all cases send back everything.
                    243:  */
                    244: request(up, len)
                    245:        struct udppacket *up;
                    246:        u_int len;
                    247: {
                    248:        struct rip *rip;
                    249:        struct sockaddr *sin;
                    250:        struct netinfo *np;
                    251: 
                    252:        rip = (struct rip *)(up->buf);
                    253:        np = rip->rip_nets;
                    254:        if(traceinput)
                    255:                logevent("request from %s\n", in_ntoa(up->addr.host));
                    256: 
                    257:        sin = &(np->rip_dst);
                    258:        np->rip_metric = ntohl(np->rip_metric);
                    259:        sin->sin_family = ntohs(sin->sin_family);
                    260:        if((sin->sin_family == AF_UNSPEC && np->rip_metric == HOPCNT_INFINITY)
                    261:        || sin->sin_family == AF_INET)
                    262:                send(up);
                    263: }
                    264: 
                    265: struct route{
                    266:        u_long dst;
                    267:        u_long gate;
                    268:        int metric;
                    269:        int age;
                    270:        int nif;
                    271: };
                    272: #define NROUTES 360
                    273: struct route routes[NROUTES];
                    274: 
                    275: rtinstall(dst, gate, metric, age, nif)
                    276: u_long dst, gate;
                    277: {
                    278:        struct route *rp, *save = 0;
                    279:        char hname[128];
                    280: 
                    281:        /*
                    282:         *  don't let a default route get set unless we are quiet
                    283:         */
                    284:        if(dst==0 && !quiet)
                    285:                return;
                    286: 
                    287:        /*
                    288:         *  ignore any route with inifinite hop counts
                    289:         */
                    290:        if(metric >= HOPCNT_INFINITY)
                    291:                return;
                    292: 
                    293:        /*
                    294:         *  look up the route in our local tables (not the kernel's)
                    295:         */
                    296:        for(rp = routes; rp < &routes[NROUTES]; rp++){
                    297:                if(rp->dst == dst)
                    298:                        break;
                    299:                if(rp->dst == 0 && save == 0)
                    300:                        save = rp;
                    301:        }
                    302:        if(rp >= &routes[NROUTES] && (rp = save) == 0){
                    303:                logevent("routed: out of routes?\n");
                    304:                return;
                    305:        }
                    306: 
                    307:        /*
                    308:         *  if this is a new route, make sure the new count is smaller
                    309:         */
                    310:        if(rp->dst == 0)
                    311:                rp->metric = HOPCNT_INFINITY + 1;
                    312: 
                    313:        /*
                    314:         *  if new route is closer than the old route
                    315:         *  or the gate is the same but the distance has changed
                    316:         *  or the gate is the same but the age has changed,
                    317:         *  then use the new gate
                    318:         */
                    319:        if(metric < rp->metric
                    320:           || (gate == rp->gate && metric != rp->metric)
                    321:           || (gate == rp->gate && age != rp->age)){
                    322:                rp->metric = metric;
                    323:                rp->age = age;
                    324:                if(rp->dst != dst || rp->gate != gate){
                    325:                        if(verbose){
                    326:                                strcpy(hname, in_host(gate));
                    327:                                logevent("%s installing as route to %s, metric %d\n",
                    328:                                        hname, in_host(dst), metric);
                    329:                        }
                    330:                        rp->dst = dst;
                    331:                        rp->gate = gate;
                    332:                        rp->nif = nif;
                    333:                        if(ioctl(ipfd, IPIOROUTE, rp) < 0)
                    334:                                logevent("can't install routed %s\n", in_ntoa(rp->gate));
                    335:                } else {
                    336:                        if(verbose > 1){
                    337:                                strcpy(hname, in_host(gate));
                    338:                                logevent("%s confirmed as route to %s, metric %d\n",
                    339:                                        hname, in_host(dst), metric);
                    340:                        }
                    341:                        rp->dst = dst;
                    342:                        rp->gate = gate;
                    343:                }
                    344:        }
                    345: }
                    346: 
                    347: /*
                    348:  * keep a list of routes
                    349:  * that belong to us;
                    350:  * don't let anyone claim them
                    351:  */
                    352: 
                    353: #define        NSAFE   20
                    354: 
                    355: u_long safer[NSAFE];
                    356: int nsafe = 0;
                    357: 
                    358: recsafe(s)
                    359: char *s;
                    360: {
                    361:        if (nsafe < NSAFE)
                    362:                safer[nsafe++] = in_address(s);
                    363: }
                    364: 
                    365: saferoute(dst)
                    366: u_long dst;
                    367: {
                    368:        register int i;
                    369: 
                    370:        for (i = 0; i < nsafe; i++)
                    371:                if (dst == safer[i])
                    372:                        return (1);
                    373:        return (0);
                    374: }
                    375: 
                    376: readgateways()
                    377: {
                    378:        int fd;
                    379:        char *cp;
                    380:        char net[32], gateway[32], which[32];
                    381:        u_long dst, gate;
                    382:        int metric;
                    383: 
                    384:        if((fd = open(GATEWAYS, 0)) == 0)
                    385:                return;
                    386:        Finit(fd, 0);
                    387:        while(cp=Frdline(fd)){
                    388:                if(sscanf(cp, "%s %s gateway %s metric %d",
                    389:                          which, net, gateway, &metric) != 4)
                    390:                        continue;
                    391:                dst = in_address(net);
                    392:                gate = in_address(gateway);
                    393:                rtinstall(dst, gate, metric, -1, -1);
                    394:        }
                    395: }
                    396: 
                    397: timer()
                    398: {
                    399:        int i;
                    400:        struct route *rp;
                    401:        struct ipif ipif;
                    402:        u_long net;
                    403:        char haddr1[32], haddr2[322];
                    404: 
                    405:        if(nextifs == 0){
                    406:                /*
                    407:                 *  get interfaces from kernel.  ignore interfaces that are down,
                    408:                 *  interfaces that are loop place holders (this==that), and the
                    409:                 *  loop-back network
                    410:                 */
                    411:                for(i = nifs = 0; nifs < NIFS; i++){
                    412:                        *(int *)&ipif = i;
                    413:                        if(ioctl(ipfd, IPIOGETIFS, &ipif) < 0)
                    414:                                break;
                    415:                        if((ipif.flags&IFF_UP) && ipif.thishost != ipif.that &&
                    416:                           ipif.that != 0x7f000000) {
                    417:                                if(ipif.bcast[0] == 0)
                    418:                                        ipif.bcast[0] = ipif.that;
                    419:                                ifs[nifs++] = ipif;
                    420:                                if(trace){
                    421:                                        strcpy(haddr1, in_ntoa(ipif.that));
                    422:                                        strcpy(haddr2, in_ntoa(ipif.thishost));
                    423:                                        logevent("ifs[%d] %s %s %s\n", nifs, haddr1,
                    424:                                                haddr2, in_ntoa(ipif.bcast[0]));
                    425:                                }
                    426:                                rtinstall(ipif.that, ipif.that, 0, 0, nifs - 1);
                    427:                        }
                    428:                }
                    429:        }
                    430:        
                    431:        if(!quiet)
                    432:                broadcast();
                    433: 
                    434:        /*
                    435:         *  age routes && get rid of too old routes
                    436:         */
                    437:        if(nextifs == 0)
                    438:                for(rp = routes; rp < &routes[NROUTES]; rp++){
                    439:                        if(rp->dst == 0)
                    440:                                continue;
                    441:                        if(rp->age > 10){
                    442:                                rtdelete(rp);
                    443:                        } else if(rp->age >= 0){
                    444:                                rp->age++;
                    445:                        }
                    446:                }
                    447: 
                    448:        /*
                    449:         *  post alarm for broadcast to next interface
                    450:         */
                    451:        signal(SIGALRM, timer);
                    452:        i = nifs>0 ? TIMER_RATE/nifs : TIMER_RATE;
                    453:        alarm(i+1);
                    454: }
                    455: 
                    456: /*
                    457:  *  Send a broadcast to the next interface.  This happens once every TIMER_RATE/nifs
                    458:  *  seconds so that n TIMER_RATE seconds we shoulc hit every interface.
                    459:  */
                    460: broadcast()
                    461: {
                    462:        static long last;
                    463:        long now;
                    464:        int reps;
                    465:        struct udppacket p;
                    466: 
                    467:        /*
                    468:         *  broadcast to interfaces.  approximate one broadcast every
                    469:         *  TIMER_RATE/nifs seconds.
                    470:         */
                    471:        now = time((long *)0);
                    472:        reps = nifs ? (now-last)/(TIMER_RATE/nifs) : 0;
                    473:        if(reps > nifs)
                    474:                reps = nifs;
                    475:        for(; reps>0; reps--){
                    476:                if(++nextifs >= nifs)
                    477:                        nextifs = 0;
                    478: 
                    479:                p.addr.host = ifs[nextifs].bcast[0];
                    480:                p.addr.port = RPORT;
                    481:                send(&p);
                    482:        }
                    483:        last = now;
                    484: }
                    485: 
                    486: /*
                    487:  *  put an entry into the bradcast message
                    488:  */
                    489: struct netinfo *
                    490: insert(rp, up, np, rip)
                    491:        struct udppacket *up;
                    492:        struct route *rp;
                    493:        struct netinfo *np;
                    494:        struct rip *rip;
                    495: {
                    496:        struct sockaddr *sin;
                    497:        char haddr[32];
                    498: 
                    499:        /*
                    500:         *  don't send routes back onto the network from which they
                    501:         *  came
                    502:         */
                    503:        if((rp->gate & ifs[nextifs].mask) == ifs[nextifs].that)
                    504:                return np;
                    505: 
                    506:        /*
                    507:         *  put the routing entry into the message.
                    508:         */
                    509:        bzero(np, sizeof(struct netinfo));
                    510:        sin = &(np->rip_dst);
                    511:        np->rip_metric = htonl(rp->metric + 1 + hopoffset);
                    512:        sin->sin_port = 0;
                    513: 
                    514:        /*
                    515:         *  don't send information about one network's subnets to other networks
                    516:         */
                    517:        if(in_netof(rp->dst) == in_netof(ifs[nextifs].that))
                    518:                sin->sin_addr = htonl(rp->dst);
                    519:        else
                    520:                sin->sin_addr = htonl(in_netof(rp->dst));
                    521: 
                    522:        sin->sin_family = htons((u_short)AF_INET);
                    523:        if(trace){
                    524:                strcpy(haddr, in_ntoa(ntohl(sin->sin_addr)));
                    525:                logevent(" %s %s %d\n",
                    526:                        haddr,
                    527:                        in_ntoa(rp->dst),
                    528:                        ntohl(np->rip_metric));
                    529:        }
                    530:        np++;
                    531: 
                    532:        /*
                    533:         *  if the message is at maximum size, send it and start a new one
                    534:         */
                    535:        if (np-rip->rip_nets == MAXROUTESPERPACKET) {
                    536:                psend(up, (char *)np);
                    537:                np = rip->rip_nets;
                    538:        }
                    539:        return np;
                    540: }
                    541: 
                    542: /*
                    543:  *  send info about all routes
                    544:  */
                    545: send(up)
                    546:        struct udppacket *up;
                    547: {
                    548:        struct route *rp;
                    549:        struct rip *rip;
                    550:        struct netinfo *np;
                    551:        long net;
                    552: 
                    553:        net = in_netof(ifs[nextifs].bcast[0]);
                    554:        rip = (struct rip *)up->buf;
                    555:        rip->rip_cmd = RIPCMD_RESPONSE;
                    556:        rip->rip_vers = RIPVERSION;
                    557:        np = rip->rip_nets;
                    558:        if(trace)
                    559:                logevent("BROADCAST:\n");
                    560: 
                    561:        /*
                    562:         *  first send info about directly connected networks
                    563:         */
                    564:        for(rp = routes; rp < &routes[NROUTES]; rp++){
                    565:                if(rp->dst == 0 || rp->metric > 0)
                    566:                        continue;
                    567:                if(rp->metric + hopoffset + 1 >= HOPCNT_INFINITY)
                    568:                        continue;
                    569:                np = insert(rp, up, np, rip);
                    570:        }
                    571: 
                    572:        /* 
                    573:         *  now send info about the rest
                    574:         */
                    575:        for(rp = routes; rp < &routes[NROUTES]; rp++){
                    576:                if(rp->dst==0 || rp->metric<=0)
                    577:                        continue;
                    578:                if(rp->metric + hopoffset + 1 >= HOPCNT_INFINITY)
                    579:                        continue;
                    580:                np = insert(rp, up, np, rip);
                    581:        }
                    582:        if (np > rip->rip_nets)
                    583:                psend(up, (char *)np);
                    584: }
                    585: 
                    586: /* send one routing packet to one network */
                    587: psend(pp, cp)
                    588:        struct udppacket *pp;
                    589:        char *cp;
                    590: {
                    591:        int len=cp-(char *)pp;
                    592:        int i;
                    593: 
                    594:        if(trace)
                    595:                logevent("to %s %d\n", in_ntoa(pp->addr.host), len);
                    596:        if (write(udpfd, pp, len) !=len)
                    597:                logevent("udp write error\n");
                    598: }
                    599: 
                    600: myaddr(x)
                    601: u_long x;
                    602: {
                    603:        int i;
                    604: 
                    605:        for(i = 0; i < nifs; i ++)
                    606:                if(ifs[i].thishost == x)
                    607:                        return(1);
                    608:        return(0);
                    609: }
                    610: 
                    611: rtdelete(rp)
                    612: struct route *rp;
                    613: {
                    614:        if(verbose) {
                    615:                logevent("deleting %s %d\n", in_ntoa(rp->dst), rp->metric);
                    616:        }
                    617:        if(rp->gate != rp->dst){
                    618:                rp->gate = 0;
                    619:                if(ioctl(ipfd, IPIOROUTE, rp) < 0)
                    620:                        logevent("can't remove route %s\n", in_ntoa(rp->gate));
                    621:        }
                    622:        rp->gate = rp->dst = 0;
                    623:        rp->age = rp->metric = 0;
                    624: }

unix.superglobalmegacorp.com

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