Annotation of lucent/sys/src/9/boot/ip.c, revision 1.1.1.1

1.1       root        1: #include <u.h>
                      2: #include <libc.h>
                      3: #include "../port/bootp.h"
                      4: #include "../port/arp.h"
                      5: #include "../boot/boot.h"
                      6: 
                      7: /*
                      8:  *  il 
                      9:  */
                     10: uchar  fsip[4];
                     11: uchar  auip[4];
                     12: uchar  gwip[4];
                     13: uchar  ipmask[4];
                     14: uchar  ipaddr[4];      /* our ip address */
                     15: uchar  eaddr[6];       /* our ether address */
                     16: uchar  bcast[6];       /* our ether broadcast address */
                     17: uchar  ipnet[4];       /* our ip network number */
                     18: 
                     19: static void    arp(uchar*);
                     20: static int     arplisten(void);
                     21: static ushort  nhgets(uchar*);
                     22: static void    hnputs(uchar*, ushort);
                     23: static void    parseip(uchar*, char*);
                     24: static int     myetheraddr(uchar*, char*);
                     25: static int     parseether(uchar*, char*);
                     26: static int     mygetfields(char*, char**, int);
                     27: static char*   fmtaddr(uchar*);
                     28: static void    maskip(uchar*, uchar*, uchar*);
                     29: static int     equivip(uchar*, uchar*);
                     30: static void    etheripconfig(Method*);
                     31: static int     ipdial(int*, char*, uchar*, int);
                     32: static void    catchint(void*, char*);
                     33: 
                     34: uchar classmask[4][4] = {
                     35:        0xff, 0x00, 0x00, 0x00,
                     36:        0xff, 0x00, 0x00, 0x00,
                     37:        0xff, 0xff, 0x00, 0x00,
                     38:        0xff, 0xff, 0xff, 0x00,
                     39: };
                     40: 
                     41: void
                     42: configtcp(Method *mp)
                     43: {
                     44:        etheripconfig(mp);
                     45: }
                     46: 
                     47: int
                     48: authtcp(void)
                     49: {
                     50:        return -1;
                     51: }
                     52: 
                     53: int
                     54: connecttcp(void)
                     55: {
                     56:        int fd[2], rv;
                     57: 
                     58:        rv = ipdial(fd, "#Itcp/tcp", fsip, 564);
                     59:        if(cpuflag)
                     60:                sendmsg(fd[0], "push reboot");
                     61:        sendmsg(fd[0], "push fcall");
                     62:        if(rv >= 0)
                     63:                close(fd[0]);
                     64:        return fd[1];
                     65: }
                     66: 
                     67: void
                     68: configil(Method *mp)
                     69: {
                     70:        etheripconfig(mp);
                     71: }
                     72: 
                     73: int
                     74: authil(void)
                     75: {
                     76:        int fd[2]; 
                     77: 
                     78:        if(auip[0] == 0 || ipdial(fd, "#Iil/il", auip, 566) < 0)
                     79:                return -1;
                     80:        close(fd[0]);
                     81:        return fd[1];
                     82: }
                     83: 
                     84: int
                     85: connectil(void)
                     86: {
                     87:        int fd[2], rv;
                     88: 
                     89:        rv = ipdial(fd, "#Iil/il", fsip, 17008);
                     90:        if(cpuflag)
                     91:                sendmsg(fd[0], "push reboot");
                     92:        if(rv >= 0)
                     93:                close(fd[0]);
                     94:        return fd[1];
                     95: }
                     96: 
                     97: static void
                     98: etheripconfig(Method *mp)
                     99: {
                    100:        int efd[2];
                    101: 
                    102:        /* configure/open ip */
                    103:        myetheraddr(eaddr, "#l/ether");
                    104: /*print("my etheraddr is %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n", eaddr[0], eaddr[1],
                    105: eaddr[2], eaddr[3], eaddr[4], eaddr[5]);/**/
                    106:        if(plumb("#l/ether", "0x800", efd, 0) < 0)
                    107:                fatal("opening ip ether");
                    108: 
                    109:        sendmsg(efd[0], "push arp");
                    110:        sendmsg(efd[0], "push internet");
                    111:        sendmsg(efd[0], "push permanent");
                    112: 
                    113:        /* do a bootp to find fs, auth server, & gateway */
                    114:        bootp(mp, efd[0], 0);
                    115: 
                    116:        /* done with the mux */
                    117:        close(efd[0]);
                    118:        close(efd[1]);
                    119: }
                    120: 
                    121: /*
                    122:  *  configure ip. use bootp to get ip address, net mask, file server ip address,
                    123:  *  authentication server ip address and gateway ip address.
                    124:  */
                    125: void
                    126: bootp(Method *mp, int muxctlfd, uchar *useipaddr)
                    127: {
                    128:        int fd;
                    129:        int ufd[2];
                    130:        int n;
                    131:        int tries;
                    132:        Bootp req, *rp;
                    133:        char *field[4];
                    134:        char buf[1600];
                    135:        char buf2[64];
                    136:        uchar ipbcast[4];       /* ip broadcast address for bootp */
                    137: 
                    138:        /* determine bootp broadcast address from specified file system address */
                    139:        if(*sys){
                    140:                parseip(fsip, sys);
                    141:                parseip(gwip, sys);
                    142:                memmove(ipmask, classmask[fsip[0]>>6], sizeof(ipmask));
                    143:                for(n = 0; n < sizeof(ipbcast); n++)
                    144:                        ipbcast[n] = (ipmask[n] & fsip[n]) | ((~ipmask[n])&0xff);
                    145:                sprint(buf2, "%s!67", fmtaddr(ipbcast));
                    146:        } else {
                    147:                memmove(ipmask, classmask[3], sizeof(ipmask));
                    148:                strcpy(buf2, "255.255.255.255!67");
                    149:        }
                    150: 
                    151:        memset(bcast, 0xff, sizeof(bcast));     /* ether broadcast address */
                    152: 
                    153:        /* open a udp connection for bootp and fill in a packet */
                    154:        if(plumb("#Iudp/udp", buf2, ufd, "68") < 0)
                    155:                fatal("opening bootp udp");
                    156:        close(ufd[0]);
                    157:        memset(&req, 0, sizeof(req));
                    158:        req.op = Bootrequest;
                    159:        req.htype = 1;          /* ethernet */
                    160:        req.hlen = 6;           /* ethernet */
                    161:        memmove(req.chaddr, eaddr, sizeof(req.chaddr));
                    162:        if(useipaddr != 0)
                    163:                memmove(req.ciaddr, useipaddr, sizeof(req.ciaddr));
                    164:        memset(req.file, 0, sizeof(req.file));
                    165:        strcpy(req.vend, "p9  ");
                    166: 
                    167:        /* broadcast bootp's till we get a reply, or 3 times around the loop */
                    168:        notify(catchint);
                    169:        tries = 0;
                    170:        field[0] = 0;
                    171:        for(rp = 0; rp == 0 && tries++ < 10;){
                    172:                alarm(1000);
                    173:                if(write(ufd[1], &req, sizeof(req)) < 0)
                    174:                        fatal("sending bootp");
                    175:                for(;;){
                    176:                        rp = 0;
                    177:                        memset(buf, 0, sizeof(buf));
                    178:                        n = read(ufd[1], buf, sizeof(buf));
                    179:                        if(n <= 0)
                    180:                                break;
                    181:                        rp = (Bootp*)buf;
                    182:                        memset(field, 0, sizeof field);
                    183:                        if(memcmp(req.chaddr, rp->chaddr, 6) == 0
                    184:                        && rp->htype == 1
                    185:                        && rp->hlen == 6
                    186:                        && mygetfields(rp->vend+4, field, 4) == 4){
                    187:                                if(strncmp(rp->vend, "p9  ", 4) == 0){
                    188:                                        memmove(ipaddr, rp->yiaddr, sizeof(ipaddr));
                    189:                                        parseip(ipmask, field[0]);
                    190:                                        if(*sys == 0){
                    191:                                                strcpy(sys, field[1]);
                    192:                                                parseip(fsip, field[1]);
                    193:                                        }
                    194:                                        parseip(auip, field[2]);
                    195:                                        parseip(gwip, field[3]);
                    196:                                        maskip(ipaddr, ipmask, ipnet);
                    197:                                        if(bootfile[0] == 0){
                    198:                                                strncpy(bootfile, rp->file,
                    199:                                                         3*NAMELEN);
                    200:                                                bootfile[3*NAMELEN-1] = 0;
                    201:                                        }
                    202:                                        break;
                    203:                                }
                    204:                        }
                    205:                }
                    206:                alarm(0);
                    207:        }
                    208:        close(ufd[1]);
                    209: 
                    210:        if(field[0])
                    211:                /*print("I am %s sub %s fs %s au %s gw %s\n",
                    212:                fmtaddr(ipaddr), field[0], sys, field[2], field[3])/**/;
                    213:        else {
                    214:                errstr(buf);    /* Clear timeout error from alarm */
                    215: 
                    216:                if(readfile("#e/ipaddr", buf2, sizeof(buf2)) < 0)
                    217:                        strcpy(buf2, "");
                    218:                outin(0, "My IP address", buf2, sizeof(buf2));
                    219:                parseip(ipaddr, buf2);
                    220: 
                    221:                if(readfile("#e/ipmask", buf2, sizeof(buf2)) < 0)
                    222:                        strcpy(buf2, "");
                    223:                outin(0, "My IP mask", buf2, sizeof(buf2));
                    224:                parseip(ipmask, buf2);
                    225:                maskip(ipaddr, ipmask, ipnet);
                    226: 
                    227:                if(readfile("#e/ipgw", buf2, sizeof(buf2)) < 0)
                    228:                        strcpy(buf2, "");
                    229:                outin(0, "My IP gateway", buf2, sizeof(buf2));
                    230:                parseip(gwip, buf2);
                    231: 
                    232:                if(*sys)
                    233:                        strcpy(buf2, sys);
                    234:                else {
                    235:                        if(readfile("#e/fs", buf2, sizeof(buf2)) < 0)
                    236:                                strcpy(buf2, "");
                    237:                        outin(0, "filesystem IP address", buf2, sizeof(buf2));
                    238:                }
                    239:                parseip(fsip, buf2);
                    240: 
                    241:                if(readfile("#e/auth", buf2, sizeof(buf2)) < 0)
                    242:                        strcpy(buf2, "0.0.0.0");
                    243:                outin(0, "authentication server IP address", buf2, sizeof(buf2));
                    244:                parseip(auip, buf2);
                    245:        }
                    246: 
                    247:        if(auip[0] == 0 && auip[1] == 0)
                    248:                mp->auth = 0;
                    249: 
                    250:        /* set our ip address and mask */
                    251:        n = sprint(buf2, "setip %s ", fmtaddr(ipaddr));
                    252:        sprint(buf2+n, "%s", fmtaddr(ipmask));
                    253:        sendmsg(muxctlfd, buf2);
                    254: 
                    255:        /* specify a routing gateway */
                    256:        if(*gwip){
                    257:                sprint(buf2, "add 0.0.0.0 0.0.0.0 %s", fmtaddr(gwip));
                    258:                fd = open("#P/iproute", OWRITE);
                    259:                if(fd < 0)
                    260:                        fatal("opening iproute");
                    261:                if(sendmsg(fd, buf2) < 0)
                    262:                        print("%s failed\n", buf2);
                    263:                close(fd);
                    264:        }
                    265: }
                    266: 
                    267: static int
                    268: ipdial(int *ifd, char *dev, uchar *ip, int service)
                    269: {
                    270:        uchar tmp[4];
                    271:        char buf[64];
                    272:        int arpnotefd;
                    273: 
                    274:        /* start a process to answer arps */
                    275:        arpnotefd = arplisten();
                    276: 
                    277:        /* arp for first hop */
                    278:        maskip(ip, ipmask, tmp);
                    279:        if(equivip(tmp, ipnet))
                    280:                arp(ip);
                    281:        else
                    282:                arp(gwip);
                    283: 
                    284:        /* make the call */
                    285:        sprint(buf, "%s!%d", fmtaddr(ip), service);
                    286:        if(plumb(dev, buf, ifd, 0) < 0){
                    287:                fprint(2, "error dialing %s\n", buf);
                    288:                ifd[1] = -1;
                    289:        }
                    290: 
                    291:        fprint(arpnotefd, "kill");
                    292: 
                    293:        return ifd[1];
                    294: }
                    295: 
                    296: /* send an arprequest, wait for a reply */
                    297: static void
                    298: arp(uchar *addr)
                    299: {
                    300:        int afd[2];
                    301:        int arpdev;
                    302:        int n;
                    303:        Arpentry entry;
                    304:        Arppkt req, *rp;
                    305:        char buf[1600];
                    306: 
                    307:        if(plumb("#l/ether", "0x806", afd, 0) < 0)
                    308:                fatal("opening ip ether");
                    309:        close(afd[0]);
                    310:        arpdev = open("#a/arp/data", OWRITE);
                    311:        if(arpdev < 0)
                    312:                fatal("opening arp/data");
                    313: 
                    314:        /* arp for the file server or the gateway */
                    315:        memset(&req, 0, sizeof(req));
                    316:        memmove(req.tpa, addr, sizeof(req.tpa));
                    317:        memset(req.d, 0xff, sizeof(req.d));
                    318:        memmove(req.spa, ipaddr, sizeof(ipaddr));
                    319:        memmove(req.sha, eaddr, sizeof(eaddr));
                    320:        hnputs(req.type, ET_ARP);
                    321:        hnputs(req.hrd, 1);
                    322:        hnputs(req.pro, 0x800);
                    323:        req.hln = sizeof(req.sha);
                    324:        req.pln = sizeof(req.spa);
                    325:        hnputs(req.op, ARP_REQUEST);
                    326:        for(rp = 0; rp == 0;){
                    327:                if(write(afd[1], &req, sizeof(req)) < 0)
                    328:                        fatal("sending arpreq");
                    329:                alarm(1000);
                    330:                for(;;){
                    331:                        rp = 0;
                    332:                        memset(buf, 0, sizeof(buf));
                    333:                        n = read(afd[1], buf, sizeof(buf));
                    334:                        if(n <= 0)
                    335:                                break;
                    336:                        rp = (Arppkt*)buf;
                    337:                        if(nhgets(rp->op) != ARP_REPLY)
                    338:                                continue;
                    339:                        memcpy(entry.etaddr, rp->sha, sizeof(entry.etaddr));
                    340:                        memcpy(entry.ipaddr, rp->spa, sizeof(entry.ipaddr));
                    341:                        if(write(arpdev, &entry, sizeof(entry)) < 0)
                    342:                                warning("write arp entry");
                    343: print("arp: rcvd for %s\n", fmtaddr(rp->spa));/**/
                    344:                        if(equivip(rp->spa, addr))
                    345:                                break;
                    346:                }
                    347:                alarm(0);
                    348:        }
                    349: 
                    350:        close(arpdev);
                    351:        close(afd[1]);
                    352: }
                    353: 
                    354: /*
                    355:  *  fork a process to answer arp requests for us.  since
                    356:  *  we will kill it after changing user id, we need to open the
                    357:  *  note process here.  arplisten returns the fd of the open note
                    358:  *  process.
                    359:  */
                    360: static int
                    361: arplisten(void)
                    362: {
                    363:        int afd[2];
                    364:        int n;
                    365:        int pid;
                    366:        Arppkt reply, *rp;
                    367:        char buf[1600];
                    368: 
                    369:        alarm(0);
                    370:        notify(catchint);
                    371: 
                    372:        switch(pid = fork()){
                    373:        case -1:
                    374:                fatal("forking arplisten");
                    375:        case 0:
                    376:                break;
                    377:        default:
                    378:                sprint(buf, "#p/%d/note", pid);
                    379:                return open(buf, OWRITE);
                    380:        }
                    381: 
                    382:        if(plumb("#l/ether", "0x806", afd, 0) < 0)
                    383:                fatal("opening ip ether");
                    384: 
                    385:        for(;;){
                    386:                memset(buf, 0, sizeof(buf));
                    387:                n = read(afd[1], buf, sizeof(buf));
                    388:                if(n < 0)
                    389:                        break;
                    390:                if(n == 0)
                    391:                        continue;
                    392:                rp = (Arppkt*)buf;
                    393:                if(nhgets(rp->op) != ARP_REQUEST)
                    394:                        continue;
                    395:                if(memcmp(rp->tpa, ipaddr, sizeof(ipaddr)) != 0)
                    396:                        continue;
                    397: 
                    398:                memset(&reply, 0, sizeof(reply));
                    399:                hnputs(reply.type, ET_ARP);
                    400:                hnputs(reply.hrd, 1);
                    401:                hnputs(reply.pro, 0x800);
                    402:                reply.hln = sizeof(reply.sha);
                    403:                reply.pln = sizeof(reply.spa);
                    404:                hnputs(reply.op, ARP_REPLY);
                    405:                memmove(reply.tha, rp->sha, sizeof(reply.tha));
                    406:                memmove(reply.tpa, rp->spa, sizeof(reply.tpa));
                    407:                memmove(reply.sha, eaddr, sizeof(eaddr));
                    408:                memmove(reply.spa, ipaddr, sizeof(ipaddr));
                    409:                memmove(reply.d, rp->s, sizeof(rp->s));
                    410: print("arplisten: reply to %s\n", fmtaddr(reply.tpa));/**/
                    411:                if(write(afd[1], &reply, ARPSIZE) < 0)
                    412:                        warning("write arp reply");
                    413:        }
                    414:        exits(0);
                    415:        return 0;       /* not reached */
                    416: }
                    417: 
                    418: static ushort
                    419: nhgets(uchar *val)
                    420: {
                    421:        return (val[0]<<8) | val[1];
                    422: }
                    423: 
                    424: static void
                    425: hnputs(uchar *ptr, ushort val)
                    426: {
                    427:        ptr[0] = val>>8;
                    428:        ptr[1] = val;
                    429: }
                    430: 
                    431: int
                    432: myipaddr(uchar *to, char *dev)
                    433: {
                    434:        char buf[256];
                    435:        int n, fd, clone;
                    436:        char *ptr;
                    437: 
                    438:        /* Opening clone ensures the 0 connection exists */
                    439:        sprint(buf, "%s/clone", dev);
                    440:        clone = open(buf, OREAD);
                    441:        if(clone < 0)
                    442:                return -1;
                    443: 
                    444:        sprint(buf, "%s/0/local", dev);
                    445:        fd = open(buf, OREAD);
                    446:        close(clone);
                    447:        if(fd < 0)
                    448:                return -1;
                    449:        n = read(fd, buf, sizeof(buf)-1);
                    450:        close(fd);
                    451:        if(n <= 0)
                    452:                return -1;
                    453:        buf[n] = 0;
                    454: 
                    455:        ptr = strchr(buf, ' ');
                    456:        if(ptr)
                    457:                *ptr = 0;
                    458: 
                    459:        parseip(to, buf);
                    460:        return 0;
                    461: }
                    462: 
                    463: #define CLASS(p) ((*(uchar*)(p))>>6)
                    464: static void
                    465: parseip(uchar *to, char *from)
                    466: {
                    467:        int i;
                    468:        char *p;
                    469: 
                    470:        p = from;
                    471:        memset(to, 0, 4);
                    472:        for(i = 0; i < 4 && *p; i++){
                    473:                to[i] = strtoul(p, &p, 0);
                    474:                if(*p == '.')
                    475:                        p++;
                    476:        }
                    477: 
                    478:        switch(CLASS(to)){
                    479:        case 0: /* class A - 1 byte net */
                    480:        case 1:
                    481:                if(i == 3){
                    482:                        to[3] = to[2];
                    483:                        to[2] = to[1];
                    484:                        to[1] = 0;
                    485:                } else if (i == 2){
                    486:                        to[3] = to[1];
                    487:                        to[1] = 0;
                    488:                }
                    489:                break;
                    490:        case 2: /* class B - 2 byte net */
                    491:                if(i == 3){
                    492:                        to[3] = to[2];
                    493:                        to[2] = 0;
                    494:                }
                    495:                break;
                    496:        }
                    497: }
                    498: 
                    499: static int
                    500: myetheraddr(uchar *to, char *dev)
                    501: {
                    502:        char buf[256];
                    503:        int n, fd;
                    504:        char *ptr;
                    505: 
                    506:        sprint(buf, "%s/1/stats", dev);
                    507:        fd = open(buf, OREAD);
                    508:        if(fd < 0)
                    509:                return -1;
                    510:        n = read(fd, buf, sizeof(buf)-1);
                    511:        close(fd);
                    512:        if(n <= 0)
                    513:                return -1;
                    514:        buf[n] = 0;
                    515: 
                    516:        ptr = strstr(buf, "addr: ");
                    517:        if(!ptr)
                    518:                return -1;
                    519:        ptr += 6;
                    520: 
                    521:        parseether(to, ptr);
                    522:        return 0;
                    523: }
                    524: 
                    525: static int
                    526: parseether(uchar *to, char *from)
                    527: {
                    528:        char nip[4];
                    529:        char *p;
                    530:        int i;
                    531: 
                    532:        p = from;
                    533:        for(i = 0; i < 6; i++){
                    534:                if(*p == 0)
                    535:                        return -1;
                    536:                nip[0] = *p++;
                    537:                if(*p == 0)
                    538:                        return -1;
                    539:                nip[1] = *p++;
                    540:                nip[2] = 0;
                    541:                to[i] = strtoul(nip, 0, 16);
                    542:                if(*p == ':')
                    543:                        p++;
                    544:        }
                    545:        return 0;
                    546: }
                    547: 
                    548: static int
                    549: mygetfields(char *lp, char **fields, int n)
                    550: {
                    551:        int i;
                    552: 
                    553:        for(i=0; lp && *lp && i<n; i++){
                    554:                while(*lp == ' ' || *lp == '\t')
                    555:                        *lp++=0;
                    556:                if(*lp == 0)
                    557:                        break;
                    558:                fields[i]=lp;
                    559:                while(*lp && *lp != ' ' && *lp != '\t')
                    560:                        lp++;
                    561:        }
                    562:        return i;
                    563: }
                    564: 
                    565: static char*
                    566: fmtaddr(uchar *a)
                    567: {
                    568:        static char buf[32];
                    569: 
                    570:        sprint(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
                    571:        return buf;
                    572: }
                    573: 
                    574: static void
                    575: catchint(void *a, char *note)
                    576: {
                    577:        USED(a);
                    578:        if(strstr(note, "alarm"))
                    579:                noted(NCONT);
                    580:        else
                    581:                noted(NDFLT);
                    582: }
                    583: 
                    584: static void
                    585: maskip(uchar *a, uchar *m, uchar *n)
                    586: {
                    587:        int i;
                    588: 
                    589:        for(i = 0; i < 4; i++)
                    590:                n[i] = a[i] & m[i];
                    591: }
                    592: 
                    593: static int
                    594: equivip(uchar *a, uchar *b)
                    595: {
                    596:        int i;
                    597: 
                    598:        for(i = 0; i < 4; i++)
                    599:                if(a[i] != b[i])
                    600:                        return 0;
                    601:        return 1;
                    602: }

unix.superglobalmegacorp.com

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