Annotation of researchv10no/ipc/internet/ipconfig.c, revision 1.1.1.1

1.1       root        1: #include <sys/param.h>
                      2: #include <stdio.h>
                      3: #include <errno.h>
                      4: #include <signal.h>
                      5: #include <sys/filio.h>
                      6: #include <sys/inio.h>
                      7: #include <sys/enio.h>
                      8: #include <sys/inet/ethernet.h>
                      9: #include <sys/inet/in.h>
                     10: #include "config.h"
                     11: 
                     12: extern errno;
                     13: extern unsigned short htons();
                     14: extern int ip_ld;
                     15: extern char *optarg;
                     16: extern int optind;
                     17: char *enpr();
                     18: 
                     19: /*
                     20:  *  global because we're too lazy to pass them as args
                     21:  */
                     22: int debug, fool;
                     23: in_addr myinaddr, hisinaddr, mask, broadcast;
                     24: int superarp;
                     25: u_char myenaddr[6];
                     26: u_char noether[6];
                     27: 
                     28: usage(name)
                     29:        char *name;
                     30: {
                     31:        fprint(2,
                     32:           "Usage: %s [-m subnet-mask] [-s] device myinaddr hisinaddr [arp-device]\n",
                     33:           name);
                     34:        fprint(2,
                     35:           "       %s [-m subnet-mask] [-s] myinaddr hisinaddr\n",
                     36:           name);
                     37:        fprint(2,
                     38:           "       %s [-m subnet-mask] [-s] myinaddr\n",
                     39:           name);
                     40:        exit(1);
                     41: }
                     42: 
                     43: main(argc, argv)
                     44: char *argv[];
                     45: {
                     46:        char *dev, *me, *it, *arp;
                     47:        int ipfd, enfd, x, ld;
                     48:        int c, mtu;
                     49: 
                     50:        /*
                     51:         *  process arguments
                     52:         */
                     53:        while((c = getopt(argc, argv, "dfm:s")) != -1)
                     54:                switch(c){
                     55:                case 'd':
                     56:                        /*
                     57:                         *  debugging
                     58:                         */
                     59:                        debug = 1;
                     60:                        break;
                     61:                case 'f':
                     62:                        /*
                     63:                         *  fool people not understanding the
                     64:                         *  broadcast IP address to shut them up
                     65:                         */
                     66:                        fool = 1;
                     67:                        break;
                     68:                case 'm':
                     69:                        /*
                     70:                         *  subnet mask
                     71:                         */
                     72:                        if(strchr(optarg, '.'))
                     73:                                mask = in_aton(optarg);
                     74:                        else
                     75:                                sscanf(optarg, "%x", &mask);
                     76:                        break;
                     77:                case 's':
                     78:                        /*
                     79:                         *  answer all arp requests for this net ignoring mask
                     80:                         */
                     81:                        superarp = 1;
                     82:                        break;
                     83:                default:
                     84:                        usage(argv[0]);
                     85:                        break;
                     86:                }
                     87: 
                     88:        switch(argc-optind){
                     89:        case 1:
                     90:                dev = 0;
                     91:                me = argv[optind++];
                     92:                it = me;
                     93:                arp = 0;
                     94:                break;
                     95:        case 2:
                     96:                dev = 0;
                     97:                me = argv[optind++];
                     98:                it = argv[optind++];
                     99:                arp = 0;
                    100:                break;
                    101:        case 3:
                    102:                dev = argv[optind++];
                    103:                me = argv[optind++];
                    104:                it = argv[optind++];
                    105:                arp = 0;
                    106:                break;
                    107:        case 4:
                    108:                dev = argv[optind++];
                    109:                me = argv[optind++];
                    110:                it = argv[optind++];
                    111:                arp = argv[optind++];
                    112:                break;
                    113:        default:
                    114:                usage(argv[0]);
                    115:                break;
                    116:        }
                    117: 
                    118:        /*
                    119:         *  look up the addresses
                    120:         */
                    121:        hisinaddr = in_address(it);
                    122:        if(hisinaddr == 0){
                    123:                logevent("ipconfig: unknown host/net %s\n", it);
                    124:                exit(1);
                    125:        }
                    126:        myinaddr = in_addronnet(me, hisinaddr, mask);
                    127:        if(myinaddr == 0){
                    128:                logevent("ipconfig: no host %s on same net as %s\n", me,it);
                    129:                exit(1);
                    130:        }
                    131: 
                    132:        /*
                    133:         *  push disciplines onto the right device
                    134:         */
                    135:        signal(SIGHUP, SIG_IGN);
                    136:        if(dev) {
                    137:                ipfd = open(dev, 2);
                    138:                if(ipfd < 0){
                    139:                        perror(dev);
                    140:                        exit(1);
                    141:                }
                    142:                if(arp){
                    143:                        x = htons((unsigned short)ETHERPUP_IPTYPE);
                    144:                        if(ioctl(ipfd, ENIOTYPE, &x) < 0){
                    145:                                logevent("ENIOTYPE\n");
                    146:                                exit(1);
                    147:                        }
                    148:                }
                    149:                flavor(ipfd, myinaddr, hisinaddr, mtu);
                    150:        } else {
                    151:                int pfd[2];
                    152:                if(pipe(pfd)<0){
                    153:                        logevent("pipe\n");
                    154:                        exit(1);
                    155:                }
                    156:                flavor(pfd[0], myinaddr, hisinaddr, mtu);
                    157:                flavor(pfd[1], hisinaddr, myinaddr, mtu);
                    158:        }
                    159: 
                    160:        /*
                    161:         *  wait for ever or do arping
                    162:         */
                    163:        if(arp == 0){
                    164:                if(!debug)
                    165:                        detach("ipconfig");
                    166:                pause();        /* forever, hopefully */
                    167:                exit(0);
                    168:        }
                    169:        if(ioctl(ipfd, IPIOARP, 0) < 0){
                    170:                logevent("IPIOARP\n");
                    171:                exit(1);
                    172:        }
                    173:        enfd = open(arp, 2);
                    174:        if(enfd < 0){
                    175:                logevent("can't open arp device %s\n", arp);
                    176:                exit(1);
                    177:        }
                    178:        if(!debug)
                    179:                detach("ipconfig");
                    180:        doarp(ipfd, enfd);
                    181: }
                    182: 
                    183: flavor(ipfd, myinaddr, hisinaddr, mtu)
                    184:        int ipfd;
                    185:        in_addr myinaddr, hisinaddr;
                    186:        int mtu;
                    187: {
                    188:        if(ioctl(ipfd, FIOPUSHLD, &ip_ld) < 0){
                    189:                logevent("PUSHLD\n");
                    190:                exit(1);
                    191:        }
                    192: 
                    193:        /*
                    194:         *  tell the line disciplines the identity of the ends
                    195:         */
                    196:        if(ioctl(ipfd, IPIOLOCAL, &myinaddr) < 0){
                    197:                logevent("IPIOLOCAL\n");
                    198:                exit(1);
                    199:        }
                    200:        if(hisinaddr!=in_netof(hisinaddr) && !mask){
                    201:                /*
                    202:                 *  host to host connection
                    203:                 */
                    204:                ioctl(ipfd, IPIOHOST, &hisinaddr);
                    205:                broadcast = hisinaddr;
                    206:        } else {
                    207:                /*
                    208:                 *  host to network connection
                    209:                 */
                    210:                mtu = 1500;
                    211:                ioctl(ipfd, IPIOMTU, &mtu);
                    212:                ioctl(ipfd, IPIONET, &hisinaddr);
                    213:                if(mask) {
                    214:                        ioctl(ipfd, IPIOMASK, &mask);
                    215:                        broadcast = hisinaddr | ~mask;
                    216:                } else {
                    217:                        broadcast = hisinaddr |
                    218:                                    (IN_CLASSA(hisinaddr) ? IN_CLASSA_HOST :
                    219:                                     (IN_CLASSB(hisinaddr) ? IN_CLASSB_HOST :
                    220:                                      (IN_CLASSC(hisinaddr) ? IN_CLASSC_HOST :
                    221:                                       0)));
                    222:                }
                    223:        }
                    224: }
                    225: 
                    226: /*
                    227:  * Address resolution
                    228:  */
                    229: 
                    230: struct ether_arp{
                    231:        /* driver goo */
                    232:        struct etherpup arp_ether;
                    233: 
                    234:        /* arp stuff */
                    235:        u_short arp_hrd;
                    236: #define ARPHRD_ETHER   1
                    237:        u_short arp_pro;
                    238:        u_char  arp_hln;
                    239:        u_char  arp_pln;
                    240:        u_short arp_op;
                    241: #define ARPOP_REQUEST  1
                    242: #define ARPOP_REPLY    2
                    243:        u_char  arp_sha[6];     /* sender ether addr */
                    244:        u_char  arp_spa[4];     /* sender internet addr */
                    245:        u_char  arp_tha[6];     /* target ether addr */
                    246:        u_char  arp_tpa[4];     /* target internet addr */
                    247: };
                    248: 
                    249: u_char broadaddr[6] = {
                    250:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    251: };
                    252: 
                    253: /* wait for ARP requests and answers */
                    254: doarp(ipfd, enfd)
                    255:        int ipfd;
                    256:        int enfd;
                    257: {
                    258:        fd_set rdfds;
                    259:        int x;
                    260:        char buf[2000];
                    261:        struct goo{
                    262:                in_addr inaddr;
                    263:                u_char enaddr[6];
                    264:        } goo;
                    265:        in_addr tpa;
                    266: 
                    267:        x = htons((u_short)ETHERPUP_ARPTYPE);
                    268:        if(ioctl(enfd, ENIOTYPE, &x) < 0){
                    269:                perror("ipconfig: ENIOTYPE");
                    270:                exit(1);
                    271:        }
                    272:        if(ioctl(enfd, ENIOADDR, myenaddr) < 0){
                    273:                perror("ipconfig: ENIOADDR");
                    274:                exit(1);
                    275:        }
                    276: 
                    277:        FD_ZERO(rdfds);
                    278:        while(1){
                    279:                FD_SET(ipfd, rdfds);
                    280:                FD_SET(enfd, rdfds);
                    281: 
                    282:                errno = 0;      /* just in case */
                    283:                if(select(20, &rdfds, 0, 2000) < 0){
                    284:                        if(errno == EINTR)
                    285:                                continue;
                    286:                        logevent("ipconfig: select error\n");
                    287:                        exit(1);
                    288:                }
                    289:                if(FD_ISSET(ipfd, rdfds)){
                    290:                        if(read(ipfd, &tpa, sizeof(tpa)) != sizeof(tpa))
                    291:                                logevent("ipconfig: in read\n");
                    292:                        arpwhohas(enfd, ipfd, tpa);
                    293:                }
                    294:                if(FD_ISSET(enfd, rdfds)){
                    295:                        if(read(enfd, buf, sizeof(buf)) <= 0)
                    296:                                logevent("ipconfig: en read\n");
                    297:                        arpinput(ipfd, enfd, buf);
                    298:                }
                    299:        }
                    300: }
                    301: 
                    302: /* broadcast an arp request */
                    303: arpwhohas(enfd, ipfd, addr)
                    304:        in_addr addr;
                    305: {
                    306:        struct goo{
                    307:                in_addr inaddr;
                    308:                u_char enaddr[6];
                    309:        } goo;
                    310:        struct ether_arp a;
                    311:        in_addr rddaniym;
                    312: 
                    313:        if(addr == myinaddr){
                    314:                goo.inaddr = addr;
                    315:                bcopy(myenaddr, goo.enaddr, sizeof(goo.enaddr));
                    316:                ioctl(ipfd, IPIORESOLVE, &goo);
                    317:                return;
                    318:        }
                    319:        if(addr == hisinaddr || addr == broadcast){
                    320:                goo.inaddr = addr;
                    321:                bcopy(broadaddr, goo.enaddr, sizeof(goo.enaddr));
                    322:                ioctl(ipfd, IPIORESOLVE, &goo);
                    323:                return;
                    324:        }
                    325:        bcopy(broadaddr, a.arp_ether.dhost, sizeof(a.arp_ether.dhost));
                    326:        a.arp_ether.type = htons(ETHERPUP_ARPTYPE);
                    327: 
                    328:        a.arp_hrd = htons(ARPHRD_ETHER);
                    329:        a.arp_pro = htons(ETHERPUP_IPTYPE);
                    330:        a.arp_hln = sizeof(goo.enaddr);
                    331:        a.arp_pln = sizeof(in_addr);
                    332:        a.arp_op = htons(ARPOP_REQUEST);
                    333: 
                    334:        bcopy(myenaddr, a.arp_sha, sizeof(a.arp_sha));
                    335:        rddaniym = htonl(myinaddr);
                    336:        bcopy(&rddaniym, a.arp_spa, sizeof(a.arp_spa));
                    337:        addr = htonl(addr);
                    338:        bcopy(&addr, a.arp_tpa, sizeof(a.arp_tpa));
                    339: 
                    340:        write(enfd, &a, sizeof(a));
                    341: }
                    342: 
                    343: /* process an arp request */
                    344: arpinput(ipfd, enfd, ap)
                    345:        struct ether_arp *ap;
                    346: {
                    347:        struct goo{
                    348:                in_addr inaddr;
                    349:                u_char enaddr[6];
                    350:        } goo;
                    351:        in_addr spa, tpa;
                    352:        in_addr rddaniym;
                    353:        int forgery = 0;
                    354: 
                    355:        bcopy(ap->arp_spa, &spa, sizeof(spa));
                    356:        bcopy(ap->arp_tpa, &tpa, sizeof(tpa));
                    357:        spa = ntohl(spa);
                    358:        tpa = ntohl(tpa);
                    359: 
                    360:        if(debug){
                    361:                print("%s from %s", 
                    362:                        ap->arp_op == ntohs(ARPOP_REQUEST) ? "request" : "answer",
                    363:                        in_ntoa(spa));
                    364:                print(" for %s\n", in_ntoa(tpa));
                    365:        }
                    366: 
                    367:        if(ntohs(ap->arp_pro) != ETHERPUP_IPTYPE)
                    368:                return;
                    369: 
                    370:        /* make sure noone's trying to be me */
                    371:        if(memcmp(ap->arp_sha, myenaddr, sizeof(myenaddr)) != 0){
                    372:                if(spa == myinaddr){
                    373:                        /*
                    374:                         *  scream on the console and send out an
                    375:                         *  arp packet with my correct ether addrss
                    376:                         */
                    377:                        logconsole("ipconfig: machine at ether address %s is forging my IP address\n", enpr(ap->arp_ether.shost));
                    378:                        tpa = spa;
                    379:                        bcopy(myenaddr, ap->arp_sha, sizeof(myenaddr));
                    380:                        forgery = 1;
                    381:                }
                    382:        }
                    383: 
                    384:        if(!forgery){
                    385:                /* incorporate sender's address */
                    386:                goo.inaddr = spa;
                    387:                bcopy(ap->arp_sha, goo.enaddr, sizeof(goo.enaddr));
                    388:                if(ioctl(ipfd, IPIORESOLVE, &goo) < 0)
                    389:                        logevent("ipconfig: IPIORESOLVE");
                    390: 
                    391:                /* send reply only to a request */
                    392:                if(ap->arp_op != ntohs(ARPOP_REQUEST))
                    393:                        return;
                    394:        }
                    395: 
                    396:        /*  accept the request if
                    397:         *  (1) the target is me or
                    398:         *  (2) superarp==1 and (  the target is not on my subnet &&
                    399:         *                         the target is on my net  )
                    400:         */
                    401:        if(tpa==myinaddr || (superarp && in_netof(tpa)==in_netof(myinaddr) &&
                    402:                             in_subnetof(tpa, mask)!=in_subnetof(myinaddr, mask))){
                    403:                if(debug)
                    404:                        print("answering %s\n", enpr(ap->arp_sha));
                    405:                ap->arp_hrd = htons(ARPHRD_ETHER);
                    406:                ap->arp_pro = htons(ETHERPUP_IPTYPE);
                    407:                ap->arp_op = htons(ARPOP_REPLY);
                    408:                rddaniym = htonl(tpa);
                    409:                tpa = htonl(spa);
                    410:                spa = rddaniym;
                    411:                bcopy(&tpa, ap->arp_tpa, sizeof(ap->arp_tpa));
                    412:                bcopy(&spa, ap->arp_spa, sizeof(ap->arp_spa));
                    413:                bcopy(ap->arp_sha, ap->arp_tha, sizeof(ap->arp_tha));
                    414:                bcopy(myenaddr, ap->arp_sha, sizeof(ap->arp_sha));
                    415:                bcopy(broadaddr, ap->arp_ether.dhost, sizeof(ap->arp_ether.dhost));
                    416:                ap->arp_ether.type = htons(ETHERPUP_ARPTYPE);
                    417:                write(enfd, ap, sizeof(struct ether_arp));
                    418:        } else if((tpa==hisinaddr || tpa==broadcast)){
                    419:                /*
                    420:                 *  For various reasons, some systems to not understand
                    421:                 *  the correct IP address to use for broadcast.  This
                    422:                 *  causes them to send there future arp requests (for that
                    423:                 *  address) to a non-existant ether address.
                    424:                 */
                    425:                logevent("bozo request from %s", in_ntoa(spa));
                    426:                fprint(2, " for %s\n", in_ntoa(tpa));
                    427:                if(fool){
                    428:                        logevent("giving him bozoid arp response\n");
                    429:                        ap->arp_hrd = htons(ARPHRD_ETHER);
                    430:                        ap->arp_pro = htons(ETHERPUP_IPTYPE);
                    431:                        ap->arp_op = htons(ARPOP_REPLY);
                    432:                        rddaniym = htonl(tpa);
                    433:                        tpa = htonl(spa);
                    434:                        spa = rddaniym;
                    435:                        bcopy(&tpa, ap->arp_tpa, sizeof(ap->arp_tpa));
                    436:                        bcopy(&spa, ap->arp_spa, sizeof(ap->arp_spa));
                    437:                        bcopy(ap->arp_sha, ap->arp_tha, sizeof(ap->arp_tha));
                    438:                        bcopy(noether, ap->arp_sha, sizeof(ap->arp_sha));
                    439:                        bcopy(ap->arp_ether.shost, ap->arp_ether.dhost,sizeof(ap->arp_ether.dhost));
                    440:                        ap->arp_ether.type = htons(ETHERPUP_ARPTYPE);
                    441: 
                    442:                        write(enfd, ap, sizeof(struct ether_arp));
                    443:                }
                    444:        }
                    445: }
                    446: 
                    447: arppr(a)
                    448: struct ether_arp a;
                    449: {
                    450:        in_addr spa, tpa;
                    451: 
                    452:        print("dhost %s\n", enpr(a.arp_ether.dhost));
                    453:        print("shost %s\n", enpr(a.arp_ether.shost));
                    454:        print("type  %x\n", ntohs(a.arp_ether.type));
                    455:        a.arp_hrd = ntohs(a.arp_hrd);
                    456:        a.arp_pro = ntohs(a.arp_pro);
                    457:        a.arp_op = ntohs(a.arp_op);
                    458: 
                    459:        bcopy(a.arp_spa, &spa, sizeof(spa));
                    460:        bcopy(a.arp_tpa, &tpa, sizeof(tpa));
                    461:        tpa = ntohl(tpa);
                    462:        spa = ntohl(spa);
                    463: 
                    464:        print("hrd %d pro %x op %d spa %x tpa %x\n",
                    465:                a.arp_hrd, a.arp_pro, a.arp_op, spa, tpa);
                    466:        print("sha %s\n", enpr(a.arp_sha));
                    467:        print("tha %s\n", enpr(a.arp_tha));
                    468: }
                    469: 
                    470: char *
                    471: enpr(en)
                    472: u_char *en;
                    473: {
                    474:        static char a[128];
                    475: 
                    476:        sprint(a, "%02x %02x %02x %02x %02x %02x", en[0], en[1], en[2],
                    477:                en[3], en[4], en[5]);
                    478:        return a;
                    479: }

unix.superglobalmegacorp.com

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