Annotation of lucent/sys/src/9/boot/ip.c, revision 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.