home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / libc / net / gethostnamadr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-25  |  9.9 KB  |  430 lines

  1. /*
  2.  * Copyright (c) 1985, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)gethostnamadr.c    6.48 (Berkeley) 1/10/93";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <arpa/inet.h>
  42. #include <arpa/nameser.h>
  43. #include <netdb.h>
  44. #include <resolv.h>
  45. #include <stdio.h>
  46. #include <ctype.h>
  47. #include <errno.h>
  48. #include <string.h>
  49.  
  50. #define    MAXALIASES    35
  51. #define    MAXADDRS    35
  52.  
  53. static char *h_addr_ptrs[MAXADDRS + 1];
  54.  
  55. static struct hostent host;
  56. static char *host_aliases[MAXALIASES];
  57. static char hostbuf[BUFSIZ+1];
  58. static struct in_addr host_addr;
  59. static FILE *hostf = NULL;
  60. static char hostaddr[MAXADDRS];
  61. static char *host_addrs[2];
  62. static int stayopen = 0;
  63. char *strpbrk();
  64.  
  65. #if PACKETSZ > 1024
  66. #define    MAXPACKET    PACKETSZ
  67. #else
  68. #define    MAXPACKET    1024
  69. #endif
  70.  
  71. typedef union {
  72.     HEADER hdr;
  73.     u_char buf[MAXPACKET];
  74. } querybuf;
  75.  
  76. typedef union {
  77.     long al;
  78.     char ac;
  79. } align;
  80.  
  81. int h_errno;
  82.  
  83. static struct hostent *
  84. getanswer(answer, anslen, iquery)
  85.     querybuf *answer;
  86.     int anslen;
  87.     int iquery;
  88. {
  89.     register HEADER *hp;
  90.     register u_char *cp;
  91.     register int n;
  92.     u_char *eom;
  93.     char *bp, **ap;
  94.     int type, class, buflen, ancount, qdcount;
  95.     int haveanswer, getclass = C_ANY;
  96.     char **hap;
  97.  
  98.     eom = answer->buf + anslen;
  99.     /*
  100.      * find first satisfactory answer
  101.      */
  102.     hp = &answer->hdr;
  103.     ancount = ntohs(hp->ancount);
  104.     qdcount = ntohs(hp->qdcount);
  105.     bp = hostbuf;
  106.     buflen = sizeof(hostbuf);
  107.     cp = answer->buf + sizeof(HEADER);
  108.     if (qdcount) {
  109.         if (iquery) {
  110.             if ((n = dn_expand((u_char *)answer->buf,
  111.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  112.                 buflen)) < 0) {
  113.                 h_errno = NO_RECOVERY;
  114.                 return ((struct hostent *) NULL);
  115.             }
  116.             cp += n + QFIXEDSZ;
  117.             host.h_name = bp;
  118.             n = strlen(bp) + 1;
  119.             bp += n;
  120.             buflen -= n;
  121.         } else
  122.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  123.         while (--qdcount > 0)
  124.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  125.     } else if (iquery) {
  126.         if (hp->aa)
  127.             h_errno = HOST_NOT_FOUND;
  128.         else
  129.             h_errno = TRY_AGAIN;
  130.         return ((struct hostent *) NULL);
  131.     }
  132.     ap = host_aliases;
  133.     *ap = NULL;
  134.     host.h_aliases = host_aliases;
  135.     hap = h_addr_ptrs;
  136.     *hap = NULL;
  137. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  138.     host.h_addr_list = h_addr_ptrs;
  139. #endif
  140.     haveanswer = 0;
  141.     while (--ancount >= 0 && cp < eom) {
  142.         if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
  143.             (u_char *)cp, (u_char *)bp, buflen)) < 0)
  144.             break;
  145.         cp += n;
  146.         type = _getshort(cp);
  147.          cp += sizeof(u_short);
  148.         class = _getshort(cp);
  149.          cp += sizeof(u_short) + sizeof(u_long);
  150.         n = _getshort(cp);
  151.         cp += sizeof(u_short);
  152.         if (type == T_CNAME) {
  153.             cp += n;
  154.             if (ap >= &host_aliases[MAXALIASES-1])
  155.                 continue;
  156.             *ap++ = bp;
  157.             n = strlen(bp) + 1;
  158.             bp += n;
  159.             buflen -= n;
  160.             continue;
  161.         }
  162.         if (iquery && type == T_PTR) {
  163.             if ((n = dn_expand((u_char *)answer->buf,
  164.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  165.                 buflen)) < 0)
  166.                 break;
  167.             cp += n;
  168.             host.h_name = bp;
  169.             return(&host);
  170.         }
  171.         if (iquery || type != T_A)  {
  172. #ifdef DEBUG
  173.             if (_res.options & RES_DEBUG)
  174.                 printf("unexpected answer type %d, size %d\n",
  175.                     type, n);
  176. #endif
  177.             cp += n;
  178.             continue;
  179.         }
  180.         if (haveanswer) {
  181.             if (n != host.h_length) {
  182.                 cp += n;
  183.                 continue;
  184.             }
  185.             if (class != getclass) {
  186.                 cp += n;
  187.                 continue;
  188.             }
  189.         } else {
  190.             host.h_length = n;
  191.             getclass = class;
  192.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  193.             if (!iquery) {
  194.                 host.h_name = bp;
  195.                 bp += strlen(bp) + 1;
  196.             }
  197.         }
  198.  
  199.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  200.  
  201.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  202. #ifdef DEBUG
  203.             if (_res.options & RES_DEBUG)
  204.                 printf("size (%d) too big\n", n);
  205. #endif
  206.             break;
  207.         }
  208.         bcopy(cp, *hap++ = bp, n);
  209.         bp +=n;
  210.         cp += n;
  211.         haveanswer++;
  212.     }
  213.     if (haveanswer) {
  214.         *ap = NULL;
  215. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  216.         *hap = NULL;
  217. #else
  218.         host.h_addr = h_addr_ptrs[0];
  219. #endif
  220.         return (&host);
  221.     } else {
  222.         h_errno = TRY_AGAIN;
  223.         return ((struct hostent *) NULL);
  224.     }
  225. }
  226.  
  227. struct hostent *
  228. gethostbyname(name)
  229.     const char *name;
  230. {
  231.     querybuf buf;
  232.     register const char *cp;
  233.     int n;
  234.     extern struct hostent *_gethtbyname();
  235.  
  236.     /*
  237.      * disallow names consisting only of digits/dots, unless
  238.      * they end in a dot.
  239.      */
  240.     if (isdigit(name[0]))
  241.         for (cp = name;; ++cp) {
  242.             if (!*cp) {
  243.                 if (*--cp == '.')
  244.                     break;
  245.                 /*
  246.                  * All-numeric, no dot at the end.
  247.                  * Fake up a hostent as if we'd actually
  248.                  * done a lookup.
  249.                  */
  250.                 if (!inet_aton(name, &host_addr)) {
  251.                     h_errno = HOST_NOT_FOUND;
  252.                     return((struct hostent *) NULL);
  253.                 }
  254.                 host.h_name = (char *)name;
  255.                 host.h_aliases = host_aliases;
  256.                 host_aliases[0] = NULL;
  257.                 host.h_addrtype = AF_INET;
  258.                 host.h_length = sizeof(u_long);
  259.                 h_addr_ptrs[0] = (char *)&host_addr;
  260.                 h_addr_ptrs[1] = (char *)0;
  261. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  262.                 host.h_addr_list = h_addr_ptrs;
  263. #else
  264.                 host.h_addr = h_addr_ptrs[0];
  265. #endif
  266.                 return (&host);
  267.             }
  268.             if (!isdigit(*cp) && *cp != '.') 
  269.                 break;
  270.         }
  271.  
  272.     if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
  273. #ifdef DEBUG
  274.         if (_res.options & RES_DEBUG)
  275.             printf("res_search failed\n");
  276. #endif
  277.         if (errno == ECONNREFUSED)
  278.             return (_gethtbyname(name));
  279.         else
  280.             return ((struct hostent *) NULL);
  281.     }
  282.     return (getanswer(&buf, n, 0));
  283. }
  284.  
  285. struct hostent *
  286. gethostbyaddr(addr, len, type)
  287.     const char *addr;
  288.     int len, type;
  289. {
  290.     int n;
  291.     querybuf buf;
  292.     register struct hostent *hp;
  293.     char qbuf[MAXDNAME];
  294.     extern struct hostent *_gethtbyaddr();
  295.     
  296.     if (type != AF_INET)
  297.         return ((struct hostent *) NULL);
  298.     (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  299.         ((unsigned)addr[3] & 0xff),
  300.         ((unsigned)addr[2] & 0xff),
  301.         ((unsigned)addr[1] & 0xff),
  302.         ((unsigned)addr[0] & 0xff));
  303.     n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
  304.     if (n < 0) {
  305. #ifdef DEBUG
  306.         if (_res.options & RES_DEBUG)
  307.             printf("res_query failed\n");
  308. #endif
  309.         if (errno == ECONNREFUSED)
  310.             return (_gethtbyaddr(addr, len, type));
  311.         return ((struct hostent *) NULL);
  312.     }
  313.     hp = getanswer(&buf, n, 1);
  314.     if (hp == NULL)
  315.         return ((struct hostent *) NULL);
  316.     hp->h_addrtype = type;
  317.     hp->h_length = len;
  318.     h_addr_ptrs[0] = (char *)&host_addr;
  319.     h_addr_ptrs[1] = (char *)0;
  320.     host_addr = *(struct in_addr *)addr;
  321. #if BSD < 43 && !defined(h_addr)    /* new-style hostent structure */
  322.     hp->h_addr = h_addr_ptrs[0];
  323. #endif
  324.     return(hp);
  325. }
  326.  
  327. _sethtent(f)
  328.     int f;
  329. {
  330.     if (hostf == NULL)
  331.         hostf = fopen(_PATH_HOSTS, "r" );
  332.     else
  333.         rewind(hostf);
  334.     stayopen |= f;
  335. }
  336.  
  337. _endhtent()
  338. {
  339.     if (hostf && !stayopen) {
  340.         (void) fclose(hostf);
  341.         hostf = NULL;
  342.     }
  343. }
  344.  
  345. struct hostent *
  346. _gethtent()
  347. {
  348.     char *p;
  349.     register char *cp, **q;
  350.  
  351.     if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
  352.         return (NULL);
  353. again:
  354.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  355.         return (NULL);
  356.     if (*p == '#')
  357.         goto again;
  358.     cp = strpbrk(p, "#\n");
  359.     if (cp == NULL)
  360.         goto again;
  361.     *cp = '\0';
  362.     cp = strpbrk(p, " \t");
  363.     if (cp == NULL)
  364.         goto again;
  365.     *cp++ = '\0';
  366.     /* THIS STUFF IS INTERNET SPECIFIC */
  367. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  368.     host.h_addr_list = host_addrs;
  369. #endif
  370.     host.h_addr = hostaddr;
  371.     *((u_long *)host.h_addr) = inet_addr(p);
  372.     host.h_length = sizeof (u_long);
  373.     host.h_addrtype = AF_INET;
  374.     while (*cp == ' ' || *cp == '\t')
  375.         cp++;
  376.     host.h_name = cp;
  377.     q = host.h_aliases = host_aliases;
  378.     cp = strpbrk(cp, " \t");
  379.     if (cp != NULL) 
  380.         *cp++ = '\0';
  381.     while (cp && *cp) {
  382.         if (*cp == ' ' || *cp == '\t') {
  383.             cp++;
  384.             continue;
  385.         }
  386.         if (q < &host_aliases[MAXALIASES - 1])
  387.             *q++ = cp;
  388.         cp = strpbrk(cp, " \t");
  389.         if (cp != NULL)
  390.             *cp++ = '\0';
  391.     }
  392.     *q = NULL;
  393.     return (&host);
  394. }
  395.  
  396. struct hostent *
  397. _gethtbyname(name)
  398.     char *name;
  399. {
  400.     register struct hostent *p;
  401.     register char **cp;
  402.     
  403.     _sethtent(0);
  404.     while (p = _gethtent()) {
  405.         if (strcasecmp(p->h_name, name) == 0)
  406.             break;
  407.         for (cp = p->h_aliases; *cp != 0; cp++)
  408.             if (strcasecmp(*cp, name) == 0)
  409.                 goto found;
  410.     }
  411. found:
  412.     _endhtent();
  413.     return (p);
  414. }
  415.  
  416. struct hostent *
  417. _gethtbyaddr(addr, len, type)
  418.     const char *addr;
  419.     int len, type;
  420. {
  421.     register struct hostent *p;
  422.  
  423.     _sethtent(0);
  424.     while (p = _gethtent())
  425.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  426.             break;
  427.     _endhtent();
  428.     return (p);
  429. }
  430.