|
|
1.1 ! root 1: /* ! 2: ******************************************************************************* ! 3: * ! 4: * getinfo.c -- ! 5: * ! 6: * Routines to create requests to name servers ! 7: * and interpret the answers. ! 8: * ! 9: * Adapted from 4.3BSD BIND gethostnamadr.c ! 10: * ! 11: * Copyright (c) 1985 Regents of the University of California. ! 12: * All rights reserved. The Berkeley software License Agreement ! 13: * specifies the terms and conditions for redistribution. ! 14: * ! 15: ******************************************************************************* ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char sccsid[] = "@(#)getinfo.c 5.3 (Berkeley) 3/31/86"; ! 20: #endif not lint ! 21: ! 22: #include <sys/types.h> ! 23: #include <sys/socket.h> ! 24: #include <netinet/in.h> ! 25: #include <stdio.h> ! 26: #include <ctype.h> ! 27: #include <arpa/nameser.h> ! 28: #include <resolv.h> ! 29: #include "res.h" ! 30: ! 31: extern char *rcodes[]; ! 32: extern char *res_skip(); ! 33: ! 34: #define MAXALIASES 35 ! 35: #define MAXADDRS 35 ! 36: #define MAXDOMAINS 35 ! 37: #define MAXSERVERS 10 ! 38: ! 39: static char *addr_list[MAXADDRS + 1]; ! 40: ! 41: static char *host_aliases[MAXALIASES]; ! 42: static int host_aliases_len[MAXALIASES]; ! 43: static char hostbuf[BUFSIZ+1]; ! 44: ! 45: typedef struct { ! 46: char *name; ! 47: char *domain[MAXDOMAINS]; ! 48: int numDomains; ! 49: char *address[MAXADDRS]; ! 50: int numAddresses; ! 51: } ServerTable; ! 52: ! 53: ServerTable server[MAXSERVERS]; ! 54: ! 55: typedef union { ! 56: HEADER qb1; ! 57: char qb2[PACKETSZ]; ! 58: } querybuf; ! 59: ! 60: static union { ! 61: long al; ! 62: char ac; ! 63: } align; ! 64: ! 65: ! 66: /* ! 67: ******************************************************************************* ! 68: * ! 69: * GetAnswer -- ! 70: * ! 71: * Interprets an answer packet and retrieves the following ! 72: * information: ! 73: * ! 74: * Results: ! 75: * SUCCESS the info was retrieved. ! 76: * NO_INFO the packet did not contain an answer. ! 77: * NONAUTH non-authoritative information was found. ! 78: * ERROR the answer was malformed. ! 79: * Other errors returned in the packet header. ! 80: * ! 81: ******************************************************************************* ! 82: */ ! 83: ! 84: static int ! 85: GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr) ! 86: struct in_addr *nsAddrPtr; ! 87: char *msg; ! 88: int queryType; ! 89: int msglen; ! 90: int iquery; ! 91: register HostInfo *hostPtr; ! 92: { ! 93: register HEADER *headerPtr; ! 94: register char *cp; ! 95: querybuf answer; ! 96: char *eom, *bp, **aliasPtr; ! 97: char **addrPtr; ! 98: char *namePtr; ! 99: char *dnamePtr; ! 100: int type, class; ! 101: int qdcount, ancount, arcount, nscount, buflen; ! 102: int haveanswer, getclass; ! 103: int numAliases = 0; ! 104: int numAddresses = 0; ! 105: int n, i, j; ! 106: int len; ! 107: int dlen; ! 108: int status; ! 109: int numServers; ! 110: int found; ! 111: ! 112: ! 113: /* ! 114: * If the hostPtr was used before, free up ! 115: * the calloc'd areas. ! 116: */ ! 117: FreeHostInfoPtr(hostPtr); ! 118: ! 119: status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer, ! 120: sizeof(answer), &n); ! 121: ! 122: if (status != SUCCESS) { ! 123: if (_res.options & RES_DEBUG2) ! 124: printf("SendRequest failed\n"); ! 125: return (status); ! 126: } ! 127: eom = (char *) &answer + n; ! 128: ! 129: headerPtr = (HEADER *) &answer; ! 130: qdcount = ntohs(headerPtr->qdcount); ! 131: ancount = ntohs(headerPtr->ancount); ! 132: arcount = ntohs(headerPtr->arcount); ! 133: nscount = ntohs(headerPtr->nscount); ! 134: ! 135: if (headerPtr->rcode != NOERROR) { ! 136: if (_res.options & RES_DEBUG) { ! 137: printf( ! 138: "Failed: %s, num. answers = %d, ns = %d, additional = %d\n", ! 139: rcodes[headerPtr->rcode], ancount, nscount, arcount); ! 140: } ! 141: return (headerPtr->rcode); ! 142: } ! 143: ! 144: /* ! 145: * If there are no answer, n.s. or additional records ! 146: * then return with an error. ! 147: */ ! 148: if (ancount == 0 && nscount == 0 && arcount == 0) { ! 149: return (NO_INFO); ! 150: } ! 151: ! 152: ! 153: bp = hostbuf; ! 154: buflen = sizeof(hostbuf); ! 155: cp = (char *) &answer + sizeof(HEADER); ! 156: ! 157: /* ! 158: * For inverse queries, the desired information is returned ! 159: * in the question section. If there are no question records, ! 160: * return with an error. ! 161: * ! 162: */ ! 163: if (qdcount) { ! 164: if (iquery) { ! 165: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) { ! 166: return (ERROR); ! 167: } ! 168: cp += n + QFIXEDSZ; ! 169: len = strlen(bp) + 1; ! 170: hostPtr->name = Calloc((unsigned)1, (unsigned)len); ! 171: bcopy(bp, hostPtr->name, len); ! 172: } else { ! 173: cp += dn_skip(cp) + QFIXEDSZ; ! 174: } ! 175: while (--qdcount > 0) { ! 176: cp += dn_skip(cp) + QFIXEDSZ; ! 177: } ! 178: } else if (iquery) { ! 179: return (NO_INFO); ! 180: } ! 181: ! 182: aliasPtr = host_aliases; ! 183: addrPtr = addr_list; ! 184: haveanswer = 0; ! 185: ! 186: /* ! 187: * Scan through the answer resource records. ! 188: * Answers for address query types are saved. ! 189: * Other query type answers are just printed. ! 190: */ ! 191: while (--ancount >= 0 && cp < eom) { ! 192: if (queryType != T_A) { ! 193: if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { ! 194: return(ERROR); ! 195: } ! 196: continue; ! 197: } else { ! 198: if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { ! 199: return(ERROR); ! 200: } ! 201: cp += n; ! 202: type = getshort(cp); ! 203: cp += sizeof(u_short); ! 204: class = getshort(cp); ! 205: cp += sizeof(u_short) + sizeof(u_long); ! 206: dlen = getshort(cp); ! 207: cp += sizeof(u_short); ! 208: if (type == T_CNAME) { ! 209: /* ! 210: * Found an alias. ! 211: */ ! 212: cp += dlen; ! 213: if (aliasPtr >= &host_aliases[MAXALIASES-1]) ! 214: continue; ! 215: *aliasPtr++ = bp; ! 216: n = strlen(bp) + 1; ! 217: host_aliases_len[numAliases] = n; ! 218: numAliases++; ! 219: bp += n; ! 220: buflen -= n; ! 221: continue; ! 222: } else if (type == T_PTR) { ! 223: /* ! 224: * Found a "pointer" to the real name. ! 225: */ ! 226: if((n= dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0){ ! 227: cp += n; ! 228: continue; ! 229: } ! 230: cp += n; ! 231: len = strlen(bp) + 1; ! 232: hostPtr->name = Calloc((unsigned)1, (unsigned)len); ! 233: bcopy(bp, hostPtr->name, len); ! 234: haveanswer = 1; ! 235: break; ! 236: } else if (type != T_A) { ! 237: cp += dlen; ! 238: continue; ! 239: } ! 240: if (haveanswer) { ! 241: if (n != hostPtr->addrLen) { ! 242: cp += dlen; ! 243: continue; ! 244: } ! 245: if (class != getclass) { ! 246: cp += dlen; ! 247: continue; ! 248: } ! 249: } else { ! 250: hostPtr->addrLen = dlen; ! 251: getclass = class; ! 252: hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; ! 253: if (!iquery) { ! 254: len = strlen(bp) + 1; ! 255: hostPtr->name = Calloc((unsigned)1, (unsigned)len); ! 256: bcopy(bp, hostPtr->name, len); ! 257: } ! 258: } ! 259: bp += (((u_long)bp) % sizeof(align)); ! 260: ! 261: if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { ! 262: if (_res.options & RES_DEBUG) ! 263: printf("Size (%d) too big\n", dlen); ! 264: break; ! 265: } ! 266: bcopy(cp, *addrPtr++ = bp, dlen); ! 267: bp +=dlen; ! 268: cp += dlen; ! 269: numAddresses++; ! 270: haveanswer = 1; ! 271: } ! 272: } ! 273: ! 274: if (queryType == T_A && haveanswer) { ! 275: ! 276: /* ! 277: * Go through the alias and address lists and return them ! 278: * in the hostPtr variable. ! 279: */ ! 280: ! 281: if (numAliases > 0) { ! 282: hostPtr->aliases = (char **) Calloc((unsigned)1+numAliases, ! 283: sizeof(char *)); ! 284: for (i = 0; i < numAliases; i++) { ! 285: hostPtr->aliases[i] = Calloc((unsigned)1, (unsigned)host_aliases_len[i]); ! 286: bcopy(host_aliases[i], hostPtr->aliases[i], ! 287: host_aliases_len[i]); ! 288: } ! 289: hostPtr->aliases[i] = NULL; ! 290: } ! 291: if (numAddresses > 0) { ! 292: hostPtr->addrList = (char **) Calloc((unsigned)1+numAddresses, ! 293: sizeof(char *)); ! 294: for (i = 0; i < numAddresses; i++) { ! 295: hostPtr->addrList[i] = Calloc((unsigned)1, (unsigned)hostPtr->addrLen); ! 296: bcopy(addr_list[i], hostPtr->addrList[i], ! 297: hostPtr->addrLen); ! 298: } ! 299: hostPtr->addrList[i] = NULL; ! 300: } ! 301: hostPtr->servers= NULL; ! 302: return (SUCCESS); ! 303: } ! 304: ! 305: /* ! 306: * At this point, only non-authoritative answers for ! 307: * the T_A query type remain. For other query types, ! 308: * additional information might be found in the additional ! 309: * resource records part. ! 310: */ ! 311: ! 312: cp = res_skip((char *) &answer, 2); ! 313: ! 314: numServers = 0; ! 315: while (--nscount >= 0 && cp < eom) { ! 316: /* ! 317: * Go through the NS records and retrieve the ! 318: * names of hosts that server the requested domain, ! 319: * their addresses and other domains they might serve. ! 320: */ ! 321: ! 322: if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { ! 323: return(ERROR); ! 324: } ! 325: cp += n; ! 326: len = strlen(bp) + 1; ! 327: dnamePtr = Calloc((unsigned)1, (unsigned)len); /* domain name */ ! 328: bcopy(bp, dnamePtr, len); ! 329: ! 330: type = getshort(cp); ! 331: cp += sizeof(u_short); ! 332: class = getshort(cp); ! 333: cp += sizeof(u_short) + sizeof(u_long); ! 334: dlen = getshort(cp); ! 335: cp += sizeof(u_short); ! 336: ! 337: if (type != T_NS) { ! 338: cp += dlen; ! 339: } else { ! 340: if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { ! 341: return(ERROR); ! 342: } ! 343: cp += n; ! 344: len = strlen(bp) + 1; ! 345: namePtr = Calloc((unsigned)1, (unsigned)len); /* server host name */ ! 346: bcopy(bp, namePtr, len); ! 347: ! 348: /* ! 349: * Store the information keyed by the server host name. ! 350: */ ! 351: found = FALSE; ! 352: for (j = 0; j < numServers; j++) { ! 353: if (strcmp(namePtr, server[j].name) == 0) { ! 354: found = TRUE; ! 355: free(namePtr); ! 356: break; ! 357: } ! 358: } ! 359: if (found) { ! 360: server[j].numDomains++; ! 361: if (server[j].numDomains <= MAXDOMAINS) { ! 362: server[j].domain[server[j].numDomains-1] = dnamePtr; ! 363: } ! 364: } else { ! 365: if (numServers > MAXSERVERS) { ! 366: break; ! 367: } ! 368: numServers++; ! 369: server[numServers -1].name = namePtr; ! 370: server[numServers -1].domain[0] = dnamePtr; ! 371: server[numServers -1].numDomains = 1; ! 372: server[numServers -1].numAddresses = 0; ! 373: } ! 374: } ! 375: } ! 376: ! 377: if (!headerPtr->aa && (queryType != T_A) && arcount > 0) { ! 378: printf("Authoritative answers can be found from:\n"); ! 379: } ! 380: ! 381: /* ! 382: * Additional resource records contain addresses of ! 383: * servers. ! 384: */ ! 385: cp = res_skip((char *) &answer, 3); ! 386: while (--arcount >= 0 && cp < eom) { ! 387: /* ! 388: * If we don't need to save the record, just print it. ! 389: */ ! 390: if (queryType != T_A) { ! 391: if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { ! 392: return(ERROR); ! 393: } ! 394: continue; ! 395: ! 396: } else { ! 397: if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) ! 398: break; ! 399: cp += n; ! 400: type = getshort(cp); ! 401: cp += sizeof(u_short); ! 402: class = getshort(cp); ! 403: cp += sizeof(u_short) + sizeof(u_long); ! 404: dlen = getshort(cp); ! 405: cp += sizeof(u_short); ! 406: ! 407: if (type != T_A) { ! 408: cp += dlen; ! 409: continue; ! 410: } else { ! 411: for (j = 0; j < numServers; j++) { ! 412: if (strcmp(bp, server[j].name) == 0) { ! 413: server[j].numAddresses++; ! 414: if (server[j].numAddresses <= MAXADDRS) { ! 415: server[j].address[server[j].numAddresses-1]=Calloc((unsigned)1,(unsigned)dlen); ! 416: bcopy(cp,server[j].address[server[j].numAddresses-1],dlen); ! 417: break; ! 418: } ! 419: } ! 420: } ! 421: cp += dlen; ! 422: } ! 423: } ! 424: } ! 425: ! 426: /* ! 427: * If we are returning name server info, transfer it to ! 428: * the hostPtr. ! 429: * ! 430: */ ! 431: if (numServers > 0) { ! 432: hostPtr->servers = (ServerInfo **) Calloc((unsigned)numServers+1, ! 433: sizeof(ServerInfo *)); ! 434: for (i = 0; i < numServers; i++) { ! 435: hostPtr->servers[i] = (ServerInfo *) Calloc((unsigned)1, sizeof(ServerInfo)); ! 436: hostPtr->servers[i]->name = server[i].name; ! 437: ! 438: ! 439: hostPtr->servers[i]->domains = (char **) ! 440: Calloc((unsigned)server[i].numDomains+1,sizeof(char *)); ! 441: for (j = 0; j < server[i].numDomains; j++) { ! 442: hostPtr->servers[i]->domains[j] = server[i].domain[j]; ! 443: } ! 444: hostPtr->servers[i]->domains[j] = NULL; ! 445: ! 446: ! 447: hostPtr->servers[i]->addrList = (char **) ! 448: Calloc((unsigned)server[i].numAddresses+1,sizeof(char *)); ! 449: for (j = 0; j < server[i].numAddresses; j++) { ! 450: hostPtr->servers[i]->addrList[j] = server[i].address[j]; ! 451: } ! 452: hostPtr->servers[i]->addrList[j] = NULL; ! 453: ! 454: } ! 455: hostPtr->servers[i] = NULL; ! 456: } ! 457: ! 458: ! 459: if (queryType != T_A) { ! 460: return(SUCCESS); ! 461: } else { ! 462: return(NONAUTH); ! 463: } ! 464: } ! 465: ! 466: /* ! 467: ******************************************************************************* ! 468: * ! 469: * GetHostInfo -- ! 470: * ! 471: * Retrieves host name, address and alias information ! 472: * for a domain. ! 473: * ! 474: * Results: ! 475: * ERROR - res_mkquery failed. ! 476: * + return values from GetAnswer() ! 477: * ! 478: ******************************************************************************* ! 479: */ ! 480: ! 481: int ! 482: GetHostInfo(nsAddrPtr, queryType, name, hostPtr) ! 483: struct in_addr *nsAddrPtr; ! 484: int queryType; ! 485: char *name; ! 486: HostInfo *hostPtr; ! 487: { ! 488: int n; ! 489: int result; ! 490: querybuf buf; ! 491: extern char *Calloc(); ! 492: ! 493: /* catch explicit addresses */ ! 494: if (isdigit(*name)) { ! 495: long ina; ! 496: ! 497: ina = inet_addr(name); ! 498: ! 499: if (ina == -1) ! 500: return(ERROR); ! 501: ! 502: hostPtr->name = Calloc((unsigned)strlen(name)+3,1); ! 503: sprintf(hostPtr->name,"[%s]",name); ! 504: hostPtr->aliases = 0; ! 505: hostPtr->servers = 0; ! 506: hostPtr->addrType = AF_INET; ! 507: hostPtr->addrLen = 4; ! 508: hostPtr->addrList = (char **)Calloc((unsigned)2,sizeof(char *)); ! 509: hostPtr->addrList[0] = Calloc(sizeof(long),sizeof(char)); ! 510: bcopy((char *)&ina,hostPtr->addrList[0],sizeof(ina)); ! 511: hostPtr->addrList[1] = 0; ! 512: ! 513: return(SUCCESS); ! 514: } ! 515: ! 516: n = res_mkquery(QUERY, name, C_ANY, queryType, ! 517: (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf)); ! 518: if (n < 0) { ! 519: if (_res.options & RES_DEBUG) { ! 520: printf("Res_mkquery failed\n"); ! 521: } ! 522: return (ERROR); ! 523: } ! 524: ! 525: result = GetAnswer(nsAddrPtr, queryType, (char *) &buf, n, 0, hostPtr); ! 526: ! 527: /* ! 528: * GetAnswer didn't find a name, so set it to the specified one. ! 529: */ ! 530: if (result == NONAUTH) { ! 531: if (hostPtr->name == NULL) { ! 532: int len = strlen(name) + 1; ! 533: hostPtr->name = Calloc((unsigned)len, sizeof(char)); ! 534: bcopy(name, hostPtr->name, len); ! 535: } ! 536: } ! 537: return(result); ! 538: } ! 539: ! 540: ! 541: /* ! 542: ******************************************************************************* ! 543: * ! 544: * FindHostInfo -- ! 545: * ! 546: * Performs an inverse query to find the host name ! 547: * that corresponds to the given address. ! 548: * ! 549: * Results: ! 550: * ERROR - res_mkquery failed. ! 551: * + return values from GetAnswer() ! 552: * ! 553: ******************************************************************************* ! 554: */ ! 555: ! 556: int ! 557: FindHostInfo(nsAddrPtr, address, len, hostPtr) ! 558: struct in_addr *nsAddrPtr; ! 559: struct in_addr *address; ! 560: int len; ! 561: HostInfo *hostPtr; ! 562: { ! 563: int n; ! 564: querybuf buf; ! 565: ! 566: n = res_mkquery(IQUERY, (char *)0, C_IN, T_A, ! 567: (char *)address, len, (char *)0, (char *) &buf, sizeof(buf)); ! 568: if (n < 0) { ! 569: if (_res.options & RES_DEBUG) { ! 570: printf("Res_mkquery failed\n"); ! 571: } ! 572: return (ERROR); ! 573: } ! 574: return(GetAnswer(nsAddrPtr, T_A, (char *) &buf, n, 1, hostPtr)); ! 575: } ! 576: ! 577: /* ! 578: ******************************************************************************* ! 579: * ! 580: * FreeHostInfoPtr -- ! 581: * ! 582: * Deallocates all the calloc'd areas for a HostInfo ! 583: * variable. ! 584: * ! 585: ******************************************************************************* ! 586: */ ! 587: ! 588: void ! 589: FreeHostInfoPtr(hostPtr) ! 590: HostInfo *hostPtr; ! 591: { ! 592: int i, j; ! 593: ! 594: if (hostPtr->name != NULL) { ! 595: free(hostPtr->name); ! 596: hostPtr->name = NULL; ! 597: } ! 598: ! 599: if (hostPtr->aliases != NULL) { ! 600: i = 0; ! 601: while (hostPtr->aliases[i] != NULL) { ! 602: free(hostPtr->aliases[i]); ! 603: i++; ! 604: } ! 605: free((char *)hostPtr->aliases); ! 606: hostPtr->aliases = NULL; ! 607: } ! 608: ! 609: if (hostPtr->addrList != NULL) { ! 610: i = 0; ! 611: while (hostPtr->addrList[i] != NULL) { ! 612: free(hostPtr->addrList[i]); ! 613: i++; ! 614: } ! 615: free((char *)hostPtr->addrList); ! 616: hostPtr->addrList = NULL; ! 617: } ! 618: ! 619: if (hostPtr->servers != NULL) { ! 620: i = 0; ! 621: while (hostPtr->servers[i] != NULL) { ! 622: ! 623: if (hostPtr->servers[i]->name != NULL) { ! 624: free(hostPtr->servers[i]->name); ! 625: } ! 626: ! 627: if (hostPtr->servers[i]->domains != NULL) { ! 628: j = 0; ! 629: while (hostPtr->servers[i]->domains[j] != NULL) { ! 630: free(hostPtr->servers[i]->domains[j]); ! 631: j++; ! 632: } ! 633: free((char *)hostPtr->servers[i]->domains); ! 634: } ! 635: ! 636: if (hostPtr->servers[i]->addrList != NULL) { ! 637: j = 0; ! 638: while (hostPtr->servers[i]->addrList[j] != NULL) { ! 639: free(hostPtr->servers[i]->addrList[j]); ! 640: j++; ! 641: } ! 642: free((char *)hostPtr->servers[i]->addrList); ! 643: } ! 644: free((char *)hostPtr->servers[i]); ! 645: i++; ! 646: } ! 647: free((char *)hostPtr->servers); ! 648: hostPtr->servers = NULL; ! 649: } ! 650: } ! 651: ! 652: /* ! 653: ******************************************************************************* ! 654: * ! 655: * GetHostList -- ! 656: * ! 657: * Performs a completion query when given an incomplete ! 658: * name. ! 659: * ! 660: * Still under development. ! 661: * ! 662: ******************************************************************************* ! 663: */ ! 664: ! 665: #if notdef ! 666: ! 667: int ! 668: GetHostList(nsAddrPtr, queryType, name, defaultName, hostPtr) ! 669: struct in_addr *nsAddrPtr; ! 670: int queryType; ! 671: char *name, *defaultName; ! 672: HostInfo *hostPtr; ! 673: { ! 674: int n; ! 675: querybuf buf; ! 676: ! 677: n = res_mkquery(CQUERYM, name, C_IN, T_A, defaultName, 0, (char *)0, ! 678: (char *) &buf, sizeof(buf)); ! 679: if (n < 0) { ! 680: if (_res.options & RES_DEBUG) ! 681: printf("Res_mkquery failed\n"); ! 682: return (ERROR); ! 683: } ! 684: return(GetAnswer( nsAddrPtr, queryType, (char *) &buf, n, 0, hostPtr)); ! 685: } ! 686: #endif notdef
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.