Annotation of lucent/sys/src/9/port/f002547, revision 1.1.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.