Annotation of researchv10no/ipc/internet/routed.c, revision 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 720
        !           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.