Annotation of 43BSD/etc/named/tools/ns.lookup/src/list.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *******************************************************************************
                      3:  *
                      4:  *  list.c --
                      5:  *
                      6:  *     Routines to obtain info from name and finger servers.
                      7:  *
                      8:  *     Adapted from 4.3BSD BIND ns_init.c and from /usr/src/ucb/finger.c
                      9:  *
                     10:  *     Copyright (c) 1985 Regents of the University of California.
                     11:  *     All rights reserved.  The Berkeley software License Agreement
                     12:  *     specifies the terms and conditions for redistribution.
                     13:  *
                     14:  *******************************************************************************
                     15:  */
                     16: 
                     17: #ifndef lint
                     18: static char sccsid[] = "@(#)list.c     5.4 (Berkeley) 4/10/86";
                     19: #endif not lint
                     20: 
                     21: #include <sys/types.h>
                     22: #include <sys/socket.h>
                     23: #include <netinet/in.h>
                     24: #include <netdb.h>
                     25: #include <stdio.h>
                     26: #include <strings.h>
                     27: #include <ctype.h>
                     28: #include <arpa/nameser.h>
                     29: #include <resolv.h>
                     30: #include "res.h"
                     31: 
                     32: /*
                     33:  *  Imported from res_debug.c
                     34:  */
                     35: extern char *rcodes[];
                     36: 
                     37: typedef union {
                     38:     HEADER qb1;
                     39:     char qb2[PACKETSZ];
                     40: } querybuf;
                     41: 
                     42: extern u_long          inet_addr();
                     43: extern HostInfo        *defaultPtr;
                     44: extern HostInfo        curHostInfo;
                     45: extern int             curHostValid;
                     46: 
                     47: /*
                     48:  *  During a listing to a file, hash marks are printed 
                     49:  *  every HASH_SIZE records.
                     50:  */
                     51: 
                     52: #define HASH_SIZE 50
                     53: 
                     54: 
                     55: /*
                     56:  *******************************************************************************
                     57:  *
                     58:  *  ListHosts --
                     59:  *
                     60:  *     Requests the name server to do a zone transfer so we
                     61:  *     find out what hosts it knows about.
                     62:  *
                     63:  *     There are three types of output:
                     64:  *     - internet addresses (default)
                     65:  *     - cpu type and operating system (-h option)
                     66:  *     - canonical and alias names  (-a option)
                     67:  *     
                     68:  *     To see all three types of information in sorted order, 
                     69:  *     do the following:
                     70:  *       ls domain.edu > file
                     71:  *       ls -a domain.edu >> file
                     72:  *       ls -h domain.edu >> file
                     73:  *       view file
                     74:  *
                     75:  *  Results:
                     76:  *     SUCCESS         the listing was successful.
                     77:  *     ERROR           the server could not be contacted because 
                     78:  *                     a socket could not be obtained or an error
                     79:  *                     occured while receiving, or the output file
                     80:  *                     could not be opened.
                     81:  *
                     82:  *******************************************************************************
                     83:  */
                     84: 
                     85: int
                     86: ListHosts(string, putToFile)
                     87:     char *string;
                     88:     int  putToFile;
                     89: {
                     90:        querybuf                buf;
                     91:        struct sockaddr_in      sin;
                     92:        HEADER                  *headerPtr;
                     93:        int                     queryType;
                     94:        int                     msglen;
                     95:        int                     amtToRead;
                     96:        int                     numRead;
                     97:        int                     i;
                     98:        int                     numAnswers = 0;
                     99:        int                     result;
                    100:        int                     soacnt = 0;
                    101:        u_short                 len;
                    102:        char                    *cp;
                    103:        char                    name[NAME_LEN];
                    104:        char                    option[NAME_LEN];
                    105:        char                    file[NAME_LEN];
                    106:        char                    *namePtr;
                    107:        enum {
                    108:            NO_ERRORS, 
                    109:            ERR_READING_LEN, 
                    110:            ERR_READING_MSG,
                    111:            ERR_PRINTING,
                    112:        } error = NO_ERRORS;
                    113: 
                    114: 
                    115:        /*
                    116:         *
                    117:     /*
                    118:      *  Parse the command line. It maybe of the form "ls domain",
                    119:      *  "ls -a domain" or "ls -h domain".
                    120:      */ 
                    121:        i = sscanf(string, " ls %s %s", option, name);
                    122:        if (putToFile && i == 2 && name[0] == '>') {
                    123:            i--;
                    124:        }
                    125:        if (i == 2) {
                    126:            if (strcmp("-a", option) == 0) {
                    127:                queryType = T_CNAME;
                    128:            } else if (strcmp("-h", option) == 0) {
                    129:                queryType = T_HINFO;
                    130:            } else if (strcmp("-m", option) == 0) {
                    131:                queryType = T_MX;
                    132:            } else {
                    133:                queryType = T_A;
                    134:            }
                    135:            namePtr = name;
                    136:        } else if (i == 1) {
                    137:            namePtr = option;
                    138:            queryType = T_A;
                    139:        } else {
                    140:            fprintf(stderr, "ListHosts: invalid request %s\n",string);
                    141:            return(ERROR);
                    142:        }
                    143: 
                    144: 
                    145:        /*
                    146:         *  Create a query packet for the requested domain name.
                    147:         *
                    148:         */
                    149:        msglen = res_mkquery(QUERY, namePtr, C_IN, T_AXFR,
                    150:                                (char *)0, 0, (char *)0, 
                    151:                                (char *) &buf, sizeof(buf));
                    152:        if (msglen < 0) {
                    153:            if (_res.options & RES_DEBUG) {
                    154:                fprintf(stderr, "ListHosts: Res_mkquery failed\n");
                    155:            }
                    156:            return (ERROR);
                    157:        }
                    158: 
                    159:        bzero((char *)&sin, sizeof(sin));
                    160:        sin.sin_family  = AF_INET;
                    161:        sin.sin_port    =  htons(NAMESERVER_PORT);
                    162: 
                    163:        /*
                    164:         *  Check to see if we have the address of the server or the
                    165:         *  address of a server who knows about this domain.
                    166:         *       
                    167:         *  For now, just use the first address in the list.
                    168:         */
                    169: 
                    170:        if (defaultPtr->addrList != NULL) {
                    171:          sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
                    172:        } else {
                    173:          sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
                    174:        }
                    175: 
                    176:        /*
                    177:         *  Set up a virtual circuit to the server.
                    178:         */
                    179:        if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                    180:            perror("ListHosts");
                    181:            return(ERROR);
                    182:        }       
                    183:        if (connect(sockFD, &sin, sizeof(sin)) < 0) {
                    184:            perror("ListHosts");
                    185:            (void) close(sockFD);
                    186:            sockFD = -1;
                    187:            return(ERROR);
                    188:        }       
                    189: 
                    190:        /*
                    191:         * Send length & message for zone transfer 
                    192:         */
                    193: 
                    194:         len = htons(msglen);
                    195: 
                    196:         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
                    197:             write(sockFD, (char *) &buf, msglen) != msglen) {
                    198:                perror("ListHosts");
                    199:                (void) close(sockFD);
                    200:                sockFD = -1;
                    201:                return(ERROR);
                    202:        }
                    203: 
                    204:        fprintf(stdout,"[%s]\n",
                    205:                (defaultPtr->addrList != NULL) ? defaultPtr->name : 
                    206:                 defaultPtr->servers[0]->name);
                    207: 
                    208:        if (!putToFile) {
                    209:            filePtr = stdout;
                    210:        } else {
                    211:            filePtr = OpenFile(string, file);
                    212:             if (filePtr == NULL) {
                    213:                 fprintf(stderr, "*** Can't open %s for writing\n", file);
                    214:                (void) close(sockFD);
                    215:                sockFD = -1;
                    216:                 return(ERROR);
                    217:             }
                    218:            fprintf(filePtr, "> %s\n", string);
                    219:            fprintf(filePtr,"[%s]\n",
                    220:                (defaultPtr->addrList != NULL) ? defaultPtr->name : 
                    221:                 defaultPtr->servers[0]->name);
                    222:        }
                    223: 
                    224:        fprintf(filePtr, "%-30s", "Host or domain name");
                    225:        switch(queryType) {
                    226:            case T_A:
                    227:                    fprintf(filePtr, " %-30s\n", "Internet address");
                    228:                    break;
                    229:            case T_HINFO:
                    230:                    fprintf(filePtr, " %-20s %s\n", "CPU", "OS");
                    231:                    break;
                    232:            case T_CNAME:
                    233:                    fprintf(filePtr, " %-30s\n", "Alias");
                    234:                    break;
                    235:            case T_MX:
                    236:                    fprintf(filePtr, " %10s %s\n", "Metric", "Host");
                    237:        }
                    238: 
                    239: 
                    240:        while (1) {
                    241: 
                    242:            /*
                    243:             * Read the length of the response.
                    244:             */
                    245: 
                    246:            cp = (char *) &buf;
                    247:            amtToRead = sizeof(u_short);
                    248:            while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
                    249:                cp        += numRead;
                    250:                amtToRead -= numRead;
                    251:            }
                    252:            if (numRead <= 0) {
                    253:                error = ERR_READING_LEN;
                    254:                break;
                    255:            }   
                    256: 
                    257:            if ((len = htons(*(u_short *)&buf)) == 0) {
                    258:                break;  /* nothing left to read */
                    259:            }
                    260: 
                    261:            /*
                    262:             * Read the response.
                    263:             */
                    264: 
                    265:            amtToRead = len;
                    266:            cp = (char *) &buf;
                    267:            while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
                    268:                cp += numRead;
                    269:                amtToRead -= numRead;
                    270:            }
                    271:            if (numRead <= 0) {
                    272:                error = ERR_READING_MSG;
                    273:                break;
                    274:            }
                    275: 
                    276:            result = PrintListInfo(filePtr, (char *) &buf, cp, queryType);
                    277:            if (result != SUCCESS) {
                    278:                error = ERR_PRINTING;
                    279:                break;
                    280:            }
                    281: 
                    282:            numAnswers++;
                    283:            if (putToFile && ((numAnswers % HASH_SIZE) == 0)) {
                    284:                fprintf(stdout, "#");
                    285:                fflush(stdout);
                    286:            }
                    287:            cp = buf.qb2 + sizeof(HEADER);
                    288:            cp += dn_skip(cp) + QFIXEDSZ;
                    289:            cp += dn_skip(cp);
                    290:            if ((getshort(cp) == T_SOA)) {
                    291:                if (soacnt)
                    292:                    break;
                    293:                else
                    294:                    soacnt++;
                    295:            }
                    296:        }
                    297: 
                    298:        if (putToFile) {
                    299:            fprintf(stdout, "%sReceived %d record%s.\n", 
                    300:                (numAnswers >= HASH_SIZE) ? "\n" : "",
                    301:                numAnswers,
                    302:                (numAnswers > 1) ? "s" : "");
                    303:        }
                    304: 
                    305:        (void) close(sockFD);
                    306:        sockFD = -1;
                    307:        if (putToFile) {
                    308:            fclose(filePtr);
                    309:            filePtr = NULL;
                    310:        }
                    311: 
                    312:        switch (error) {
                    313:            case NO_ERRORS:
                    314:                return (SUCCESS);
                    315: 
                    316:            case ERR_READING_LEN:
                    317:                return(ERROR);
                    318: 
                    319:            case ERR_PRINTING:
                    320:                fprintf(stderr,"*** Error during listing of %s: %s\n", 
                    321:                                namePtr, DecodeError(result));
                    322:                return(result);
                    323: 
                    324:            case ERR_READING_MSG:
                    325:                headerPtr = (HEADER *) &buf;
                    326:                fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
                    327:                fprintf(stderr,
                    328:               "  result: %s, answers = %d, authority = %d, additional = %d\n", 
                    329:                        rcodes[headerPtr->rcode], 
                    330:                        ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), 
                    331:                        ntohs(headerPtr->arcount));
                    332:                return(ERROR);
                    333:            default:
                    334:                return(ERROR);
                    335:        }
                    336: }
                    337: 
                    338: 
                    339: /*
                    340:  *******************************************************************************
                    341:  *
                    342:  *  PrintListInfo --
                    343:  *
                    344:  *     Used by the ListInfo routine to print the answer 
                    345:  *     received from the name server. Only the desired 
                    346:  *     information is printed.
                    347:  *
                    348:  *  Results:
                    349:  *     SUCCESS         the answer was printed without a problem.
                    350:  *     NO_INFO         the answer packet did not contain an answer.
                    351:  *     ERROR           the answer was malformed.
                    352:  *      Misc. errors   returned in the packet header.
                    353:  *
                    354:  *******************************************************************************
                    355:  */
                    356: 
                    357: #define NAME_FORMAT " %-30s"
                    358: #define STRIP_DOMAIN(string) if((dot = index(string, '.')) != NULL) *dot = '\0'
                    359: 
                    360: 
                    361: PrintListInfo(file, msg, eom, queryType)
                    362:     FILE       *file;
                    363:     char       *msg, *eom;
                    364:     int        queryType;
                    365: {
                    366:     register char      *cp;
                    367:     HEADER             *headerPtr;
                    368:     int                type, class, dlen, nameLen;
                    369:     int                n;
                    370:     struct in_addr     inaddr;
                    371:     char               name[NAME_LEN];
                    372:     char               name2[NAME_LEN];
                    373:     char               *dot;
                    374: 
                    375:     /*
                    376:      * Read the header fields.
                    377:      */
                    378:     headerPtr = (HEADER *)msg;
                    379:     cp = msg + sizeof(HEADER);
                    380:     if (headerPtr->rcode != NOERROR) {
                    381:        return(headerPtr->rcode);
                    382:     }
                    383: 
                    384:     /*
                    385:      *  We are looking for info from answer resource records.
                    386:      *  If there aren't any, return with an error. We assume
                    387:      *  there aren't any question records.
                    388:      */
                    389: 
                    390:     if (ntohs(headerPtr->ancount) == 0) {
                    391:        return(NO_INFO);
                    392:     } else {
                    393:        if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) {
                    394:            return (ERROR);
                    395:        }
                    396:        cp += nameLen;
                    397:        type = getshort(cp);
                    398:        cp += sizeof(u_short);
                    399:        class = getshort(cp);
                    400:        cp += sizeof(u_short) + sizeof(u_long);
                    401:        dlen = getshort(cp);
                    402:        cp += sizeof(u_short);
                    403: 
                    404:        /*
                    405:         * QueryType is used to specify the type of desired information.
                    406:         *  T_A         - internet address
                    407:         *  T_CNAME     - aliases
                    408:         *  T_HINFO     - cpu, OS type
                    409:         *  T_MX        - mail routing
                    410:         *
                    411: 
                    412:         */
                    413:        switch (type) {
                    414: 
                    415:            case T_A:
                    416:                if (queryType != T_A)
                    417:                    break;
                    418: 
                    419:                if (class == C_IN) {
                    420:                    STRIP_DOMAIN(name);
                    421:                    fprintf(file, NAME_FORMAT, name);
                    422:                    bcopy(cp, (char *)&inaddr, sizeof(inaddr));
                    423:                    if (dlen == 4) {
                    424:                        fprintf(file," %s\n", inet_ntoa(inaddr));
                    425:                    } else if (dlen == 7) {
                    426:                        fprintf(file," %s", inet_ntoa(inaddr));
                    427:                        fprintf(file," (%d, %d)\n", cp[4],(cp[5] << 8) + cp[6]);
                    428:                    }
                    429:                }
                    430:                break;
                    431:                
                    432:            case T_CNAME:
                    433:                if (queryType != T_CNAME)
                    434:                    break;
                    435: 
                    436:                STRIP_DOMAIN(name);
                    437:                if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
                    438:                    return (ERROR);
                    439:                }
                    440:                /* 
                    441:                 * a bug -- cnames need not be in same domain!
                    442:                 * STRIP_DOMAIN(name2);
                    443:                 */
                    444: 
                    445:                fprintf(file, NAME_FORMAT, name2);
                    446:                fprintf(file, " %s\n", name);
                    447:                break;
                    448:                
                    449:            case T_HINFO:
                    450:                if (queryType != T_HINFO)
                    451:                    break;
                    452: 
                    453:                STRIP_DOMAIN(name);
                    454:                fprintf(file, NAME_FORMAT, name);
                    455:                if (n = *cp++) {
                    456:                    sprintf(name,"%.*s", n, cp);
                    457:                    fprintf(file," %-20s", name);
                    458:                    cp += n;
                    459:                } else {
                    460:                    fprintf(file," %-20s", " ");
                    461:                }
                    462:                if (n = *cp++) {
                    463:                    fprintf(file," %.*s\n", n, cp);
                    464:                    cp += n;
                    465:                }
                    466:                break;
                    467: 
                    468:            case T_MX:
                    469:                if (queryType != T_MX)
                    470:                    break;
                    471: 
                    472:                STRIP_DOMAIN(name);
                    473:                fprintf(file, NAME_FORMAT, name);
                    474: 
                    475:                {
                    476:                    short pref;
                    477: 
                    478:                    pref = getshort(cp);
                    479:                    cp += sizeof(u_short);
                    480:                    fprintf(file,"%10d",pref);
                    481:                }
                    482:                if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
                    483:                    return (ERROR);
                    484:                }
                    485:                fprintf(file, " %s\n", name2);
                    486: 
                    487:                break;
                    488: 
                    489: 
                    490:            case T_NS:
                    491:            case T_PTR:
                    492:                if (queryType != T_A)
                    493:                    break;
                    494:                /*
                    495:                 *  Found a name server or pointer record.
                    496:                 */
                    497:                fprintf(file, NAME_FORMAT, name);
                    498:                fprintf(file," server = ");
                    499:                cp = Print_cdname2(cp, msg, eom, file);
                    500:                fprintf(file,"\n");
                    501:                break;
                    502: 
                    503:            default:
                    504:                /*
                    505:                 * Unwanted answer type -- ignore it.
                    506:                 */
                    507:                 break;
                    508:        }
                    509:     }
                    510:     return(SUCCESS);
                    511: }
                    512: 
                    513: 
                    514: /*
                    515:  *******************************************************************************
                    516:  *
                    517:  *  ViewList --
                    518:  *
                    519:  *     A hack to view the output of the ls command in sorted
                    520:  *     order using more.
                    521:  *
                    522:  *******************************************************************************
                    523:  */
                    524: 
                    525: ViewList(string)
                    526:     char *string;
                    527: {
                    528:     char file[NAME_LEN];
                    529:     char command[NAME_LEN];
                    530: 
                    531:     sscanf(string, " view %s", file);
                    532:     sprintf(command, "grep \"^ \" %s | sort | more", file);
                    533:     system(command);
                    534: }
                    535: 
                    536: /*
                    537:  *******************************************************************************
                    538:  *
                    539:  *   Finger --
                    540:  *
                    541:  *     Connects with the finger server for the current host
                    542:  *     to request info on the specified person (long form)
                    543:  *     who is on the system (short form).
                    544:  *
                    545:  *  Results:
                    546:  *     SUCCESS         the finger server was contacted.
                    547:  *     ERROR           the server could not be contacted because 
                    548:  *                     a socket could not be obtained or connected 
                    549:  *                     to or the service could not be found.
                    550:  *
                    551:  *******************************************************************************
                    552:  */
                    553: 
                    554: Finger(string, putToFile)
                    555:     char *string;
                    556:     int  putToFile;
                    557: {
                    558:        struct servent          *sp;
                    559:        struct sockaddr_in      sin;
                    560:        register FILE           *f;
                    561:        register int            c;
                    562:        register int            lastc;
                    563:        char                    name[NAME_LEN];
                    564:        char                    file[NAME_LEN];
                    565: 
                    566:        /*
                    567:         *  We need a valid current host info to get an inet address.
                    568:         */
                    569:        if (!curHostValid) {
                    570:            fprintf(stderr, "Finger: no current host defined.\n");
                    571:            return (ERROR);
                    572:        }
                    573: 
                    574:        if (sscanf(string, " finger %s", name) == 1) {
                    575:            if (putToFile && (name[0] == '>')) {
                    576:                name[0] = '\0';
                    577:            }
                    578:        } else {
                    579:            name[0] = '\0';
                    580:        }
                    581: 
                    582:        sp = getservbyname("finger", "tcp");
                    583:        if (sp == 0) {
                    584:            fprintf(stderr, "Finger: unknown service\n");
                    585:            return (ERROR);
                    586:        }
                    587: 
                    588:        bzero((char *)&sin, sizeof(sin));
                    589:        sin.sin_family  = curHostInfo.addrType;
                    590:        sin.sin_port    = sp->s_port;
                    591:        bcopy(curHostInfo.addrList[0], (char *)&sin.sin_addr, 
                    592:                curHostInfo.addrLen);
                    593: 
                    594:        /*
                    595:         *  Set up a virtual circuit to the host.
                    596:         */
                    597: 
                    598:        sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0);
                    599:        if (sockFD < 0) {
                    600:            fflush(stdout);
                    601:            perror("Finger");
                    602:            return (ERROR);
                    603:        }
                    604: 
                    605:        if (connect(sockFD, (char *)&sin, sizeof (sin)) < 0) {
                    606:            fflush(stdout);
                    607:            perror("Finger");
                    608:            close(sockFD);
                    609:            sockFD = -1;
                    610:            return (ERROR);
                    611:        }
                    612: 
                    613:        if (!putToFile) {
                    614:            filePtr = stdout;
                    615:        } else {
                    616:            filePtr = OpenFile(string, file);
                    617:            if (filePtr == NULL) {
                    618:                fprintf(stderr, "*** Can't open %s for writing\n", file);
                    619:                close(sockFD);
                    620:                sockFD = -1;
                    621:                return(ERROR);
                    622:            }
                    623:            fprintf(filePtr,"> %s\n", string);
                    624:        }
                    625:        fprintf(filePtr, "[%s]\n", curHostInfo.name);
                    626: 
                    627:        if (name[0] != '\0') {
                    628:            write(sockFD, "/W ", 3);
                    629:        }
                    630:        write(sockFD, name, strlen(name));
                    631:        write(sockFD, "\r\n", 2);
                    632:        f = fdopen(sockFD, "r");
                    633:        while ((c = getc(f)) != EOF) {
                    634:            switch(c) {
                    635:                case 0210:
                    636:                case 0211:
                    637:                case 0212:
                    638:                case 0214:
                    639:                        c -= 0200;
                    640:                        break;
                    641:                case 0215:
                    642:                        c = '\n';
                    643:                        break;
                    644:            }
                    645:            putc(lastc = c, filePtr);
                    646:        }
                    647:        if (lastc != '\n') {
                    648:            putc('\n', filePtr);
                    649:        }
                    650:        putc('\n', filePtr);
                    651: 
                    652:        close(sockFD);
                    653:        sockFD = -1;
                    654: 
                    655:        if (putToFile) {
                    656:            fclose(filePtr);
                    657:            filePtr = NULL;
                    658:        }
                    659:        return (SUCCESS);
                    660: }

unix.superglobalmegacorp.com

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