Annotation of lucent/sys/src/9/port/f002547, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "../port/error.h"
        !             7: #include       "arp.h"
        !             8: #include       "../port/ipdat.h"
        !             9: 
        !            10: #include       "devtab.h"
        !            11: 
        !            12: /*
        !            13:  *  All ip numbers and masks are stored as ulongs.
        !            14:  *  All interfaces to this code uses the standard byte
        !            15:  *  string representation.
        !            16:  */
        !            17: 
        !            18: typedef        struct Iproute  Iproute;
        !            19: typedef        struct Iprtab   Iprtab;
        !            20: 
        !            21: enum
        !            22: {
        !            23:        Nroutes=        1024,
        !            24: };
        !            25: 
        !            26: /*
        !            27:  *  routes
        !            28:  */
        !            29: struct Iproute {
        !            30:        ulong   dst;
        !            31:        ulong   gate;
        !            32:        ulong   mask;
        !            33:        Iproute *next;
        !            34:        int     inuse;
        !            35: };
        !            36: struct Iprtab {
        !            37:        Lock;
        !            38:        int     n;              /* number of valid routes */
        !            39:        Iproute *first;         /* list of valid routes */
        !            40:        Iproute r[Nroutes];     /* all routes */
        !            41: };
        !            42: Iprtab iprtab;
        !            43: 
        !            44: /*
        !            45:  *  The chosen route is the one obeys the constraint
        !            46:  *             r->mask & dst == r->dst
        !            47:  *
        !            48:  *  If there are several matches, the one whose mask has the most
        !            49:  *  leading ones (and hence is the most specific) wins.  This is
        !            50:  *  forced by storing the routes in decreasing number of ones order
        !            51:  *  and returning the first match.  The default gateway has no ones
        !            52:  *  in the mask and is thus the last matched.
        !            53:  */
        !            54: Ipdevice*
        !            55: iproute(uchar *dst, uchar *gate)
        !            56: {
        !            57:        Iproute *r;
        !            58:        Ipdevice *p;
        !            59:        ulong udst;
        !            60: 
        !            61:        udst = nhgetl(dst);
        !            62:        for(p = ipd; p < &ipd[Nipd]; p++){
        !            63:                if(p->q == 0)
        !            64:                        continue;
        !            65:                if((udst&p->Mynetmask) == p->Remip){
        !            66:                        memmove(gate, dst, 4);
        !            67:                        return p;
        !            68:                }
        !            69:        }
        !            70: 
        !            71:        /*
        !            72:         *  first check routes
        !            73:         */
        !            74:        for(r = iprtab.first; r; r = r->next){
        !            75:                if((r->mask&udst) == r->dst){
        !            76:                        hnputl(gate, r->gate);
        !            77:                        for(p = ipd; p < &ipd[Nipd]; p++){
        !            78:                                if(p->q == 0)
        !            79:                                        break;
        !            80:                                if((r->gate&p->Mynetmask) == p->Remip)
        !            81:                                        return p;
        !            82:                        }
        !            83:                        return ipd;
        !            84:                }
        !            85:        }
        !            86: 
        !            87:        /*
        !            88:         *  else just return the same address and first interface
        !            89:         */     
        !            90:        memmove(gate, dst, 4);
        !            91:        return ipd;
        !            92: }
        !            93: 
        !            94: /*
        !            95:  *  Add a route, create a mask if the first mask is 0.
        !            96:  *
        !            97:  *  All routes are stored sorted by the length of leading
        !            98:  *  ones in the mask.
        !            99:  *
        !           100:  *  NOTE: A default route has an all zeroes mask and dst.
        !           101:  */
        !           102: void
        !           103: ipaddroute(ulong dst, ulong mask, ulong gate)
        !           104: {
        !           105:        Iproute *r, *e, *free;
        !           106: 
        !           107:        /*
        !           108:         *  filter out impossible requests
        !           109:         */
        !           110:        if((dst&mask) != dst)
        !           111:                error(Enetaddr);
        !           112: 
        !           113:        /*
        !           114:         *  see if we already have a route for
        !           115:         *  the destination
        !           116:         */
        !           117:        lock(&iprtab);
        !           118:        free = 0;
        !           119:        for(r = iprtab.r; r < &iprtab.r[Nroutes]; r++){
        !           120:                if(r->inuse == 0){
        !           121:                        free = r;
        !           122:                        continue;
        !           123:                }
        !           124:                if(dst==r->dst && mask==r->mask){
        !           125:                        r->gate = gate;
        !           126:                        unlock(&iprtab);
        !           127:                        return;
        !           128:                }
        !           129:        }
        !           130:        if(free == 0){
        !           131:                unlock(&iprtab);
        !           132:                exhausted("routes");
        !           133:        }
        !           134: 
        !           135:        /*
        !           136:         *  add the new route in sorted order
        !           137:         */
        !           138:        free->dst = dst;
        !           139:        free->mask = mask;
        !           140:        free->gate = gate;
        !           141:        free->inuse = 1;
        !           142:        for(r = e = iprtab.first; r; r = r->next){
        !           143:                if(mask > r->mask)
        !           144:                        break;
        !           145:                e = r;
        !           146:        }
        !           147:        free->next = r;
        !           148:        if(r == iprtab.first)
        !           149:                iprtab.first = free;
        !           150:        else
        !           151:                e->next = free;
        !           152:        iprtab.n++;
        !           153:        unlock(&iprtab);
        !           154: }
        !           155: 
        !           156: /*
        !           157:  *  remove a route
        !           158:  */
        !           159: void
        !           160: ipremroute(ulong dst, ulong mask)
        !           161: {
        !           162:        Iproute *r, *e;
        !           163: 
        !           164:        lock(&iprtab);
        !           165:        for(r = e = iprtab.first; r; r = r->next){
        !           166:                if(dst==r->dst && (mask == 0 || mask==r->mask)){
        !           167:                        if(r == iprtab.first)
        !           168:                                iprtab.first = r->next;
        !           169:                        else
        !           170:                                e->next = r->next;
        !           171:                        r->inuse = 0;
        !           172:                        iprtab.n--;
        !           173:                        break;
        !           174:                }
        !           175:                e = r;
        !           176:        }
        !           177:        unlock(&iprtab);
        !           178: }
        !           179: 
        !           180: /*
        !           181:  *  remove all routes
        !           182:  */
        !           183: void
        !           184: ipflushroute(void)
        !           185: {
        !           186:        Iproute *r;
        !           187: 
        !           188:        lock(&iprtab);
        !           189:        for(r = iprtab.first; r; r = r->next)
        !           190:                r->inuse = 0;
        !           191:        iprtab.first = 0;
        !           192:        iprtab.n = 0;
        !           193:        unlock(&iprtab);
        !           194: }
        !           195: 
        !           196: /*
        !           197:  *  device interface
        !           198:  */
        !           199: enum{
        !           200:        Qdir,
        !           201:        Qdata,
        !           202:        Qipifc,
        !           203: };
        !           204: Dirtab iproutetab[]={
        !           205:        "iproute",              {Qdata},                0,      0666,
        !           206:        "ipifc",                {Qipifc},               0,      0666,
        !           207: };
        !           208: #define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab))
        !           209: 
        !           210: void
        !           211: iproutereset(void)
        !           212: {
        !           213: }
        !           214: 
        !           215: void
        !           216: iprouteinit(void)
        !           217: {
        !           218: }
        !           219: 
        !           220: Chan *
        !           221: iprouteattach(char *spec)
        !           222: {
        !           223:        return devattach('P', spec);
        !           224: }
        !           225: 
        !           226: Chan *
        !           227: iprouteclone(Chan *c, Chan *nc)
        !           228: {
        !           229:        return devclone(c, nc);
        !           230: }
        !           231: 
        !           232: int
        !           233: iproutewalk(Chan *c, char *name)
        !           234: {
        !           235:        return devwalk(c, name, iproutetab, (long)Niproutetab, devgen);
        !           236: }
        !           237: 
        !           238: void
        !           239: iproutestat(Chan *c, char *db)
        !           240: {
        !           241:        devstat(c, db, iproutetab, (long)Niproutetab, devgen);
        !           242: }
        !           243: 
        !           244: Chan *
        !           245: iprouteopen(Chan *c, int omode)
        !           246: {
        !           247:        if(c->qid.path == CHDIR){
        !           248:                if(omode != OREAD)
        !           249:                        error(Eperm);
        !           250:        }
        !           251:        c->mode = openmode(omode);
        !           252:        c->flag |= COPEN;
        !           253:        c->offset = 0;
        !           254:        return c;
        !           255: }
        !           256: 
        !           257: void
        !           258: iproutecreate(Chan *c, char *name, int omode, ulong perm)
        !           259: {
        !           260:        USED(c, name, omode, perm);
        !           261:        error(Eperm);
        !           262: }
        !           263: 
        !           264: void
        !           265: iprouteremove(Chan *c)
        !           266: {
        !           267:        USED(c);
        !           268:        error(Eperm);
        !           269: }
        !           270: 
        !           271: void
        !           272: iproutewstat(Chan *c, char *dp)
        !           273: {
        !           274:        USED(c, dp);
        !           275:        error(Eperm);
        !           276: }
        !           277: 
        !           278: void
        !           279: iprouteclose(Chan *c)
        !           280: {
        !           281:        USED(c);
        !           282: }
        !           283: 
        !           284: /* sprint an ip address right justified into a 16 char field */
        !           285: char*
        !           286: ipformat(char *to, ulong ip)
        !           287: {
        !           288:        uchar hip[4];
        !           289:        char buf[17];
        !           290:        int n;
        !           291: 
        !           292:        hnputl(hip, ip);
        !           293:        n = sprint(buf, "%d.%d.%d.%d", hip[0], hip[1], hip[2], hip[3]);
        !           294:        memset(to, ' ', 16 - n);
        !           295:        memmove(to+16-n, buf, n);
        !           296:        to[16] = 0;
        !           297:        return to;
        !           298: }
        !           299: 
        !           300: long
        !           301: iprouteread(Chan *c, void *a, long n, ulong offset)
        !           302: {
        !           303:        Iproute *r;
        !           304:        Ipdevice *p;
        !           305:        char     *va = a;
        !           306:        char     *e;
        !           307:        int     part, bytes, size;
        !           308:        char    dst[17], mask[17], gate[17];
        !           309:        char    buf[128];
        !           310: 
        !           311:        switch((int)(c->qid.path&~CHDIR)){
        !           312:        case Qdir:
        !           313:                return devdirread(c, a, n, iproutetab, Niproutetab, devgen);
        !           314:        case Qdata:
        !           315:                lock(&iprtab);
        !           316:                bytes = 0;
        !           317:                e = va + n;
        !           318:                for(r = iprtab.first; r && va < e; r = r->next){
        !           319:                        size = sprint(buf, "%s & %s -> %s\n", ipformat(dst, r->dst),
        !           320:                                ipformat(mask, r->mask), ipformat(gate, r->gate));
        !           321:                        if(bytes + size <= offset){
        !           322:                                bytes += size;
        !           323:                                continue;
        !           324:                        }
        !           325: 
        !           326:                        if(va == a){
        !           327:                                part = offset - bytes;
        !           328:                                size -= part;
        !           329:                        } else
        !           330:                                part = 0;
        !           331:                        if(size > n)
        !           332:                                size = n;
        !           333: 
        !           334:                        memmove(va, buf + part, size);
        !           335:                        va += size;
        !           336:                }
        !           337:                unlock(&iprtab);
        !           338:                n = va - (char*)a;
        !           339:                break;
        !           340:        case Qipifc:
        !           341:                bytes = 0;
        !           342:                e = va + n;
        !           343:                for(p = ipd; p < &ipd[Nipd] && va < e; p++){
        !           344:                        if(p->q == 0)
        !           345:                                continue;
        !           346:                        size = sprint(buf, "  #%C%d %5d %s %s %s\n",
        !           347:                                devchar[p->type], p->dev, p->maxmtu,
        !           348:                                ipformat(dst, p->Myip[0]),
        !           349:                                ipformat(mask, p->Mynetmask),
        !           350:                                ipformat(gate, p->Remip));
        !           351:                        if(bytes + size <= offset){
        !           352:                                bytes += size;
        !           353:                                continue;
        !           354:                        }
        !           355: 
        !           356:                        if(va == a){
        !           357:                                part = offset - bytes;
        !           358:                                size -= part;
        !           359:                        } else
        !           360:                                part = 0;
        !           361:                        if(size > n)
        !           362:                                size = n;
        !           363: 
        !           364:                        memmove(va, buf + part, size);
        !           365:                        va += size;
        !           366:                }
        !           367:                n = va - (char*)a;
        !           368:                break;
        !           369:        default:
        !           370:                n=0;
        !           371:                break;
        !           372:        }
        !           373:        return n;
        !           374: }
        !           375: 
        !           376: long
        !           377: iproutewrite(Chan *c, char *a, long n, ulong offset)
        !           378: {
        !           379:        char buf[128];
        !           380:        char *field[4];
        !           381:        Ipaddr mask, dst, gate;
        !           382:        int m;
        !           383: 
        !           384:        USED(offset);
        !           385: 
        !           386:        switch((int)(c->qid.path&~CHDIR)){
        !           387:        case Qdata:
        !           388:                strncpy(buf, a, sizeof buf);
        !           389:                m = getfields(buf, field, 4, " ");
        !           390: 
        !           391:                if(strncmp(field[0], "flush", 5) == 0)
        !           392:                        ipflushroute();
        !           393:                else if(strncmp(field[0], "add", 3) == 0){
        !           394:                        switch(m){
        !           395:                        case 4:
        !           396:                                dst = ipparse(field[1]);
        !           397:                                mask = ipparse(field[2]);
        !           398:                                gate = ipparse(field[3]);
        !           399:                                ipaddroute(dst, mask, gate);
        !           400:                                break;
        !           401:                        case 3:
        !           402:                                dst = ipparse(field[1]);
        !           403:                                gate = ipparse(field[2]);
        !           404:                                ipaddroute(dst, classmask[dst>>30], gate);
        !           405:                                break;
        !           406:                        default:
        !           407:                                error(Ebadarg);
        !           408:                        }
        !           409:                } else if(strncmp(field[0], "delete", 6) == 0){
        !           410:                        switch(m){
        !           411:                        case 3:
        !           412:                                dst = ipparse(field[1]);
        !           413:                                mask = ipparse(field[2]);
        !           414:                                ipremroute(dst, mask);
        !           415:                                break;
        !           416:                        case 2:
        !           417:                                dst = ipparse(field[1]);
        !           418:                                ipremroute(dst, 0);
        !           419:                                break;
        !           420:                        default:
        !           421:                                error(Ebadarg);
        !           422:                        }
        !           423:                }
        !           424:                else
        !           425:                        error(Ebadctl);
        !           426:                break;
        !           427:        default:
        !           428:                error(Ebadusefd);
        !           429:        }
        !           430:        return n;
        !           431: }

unix.superglobalmegacorp.com

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