|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.