home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / mint / netlib / lib / ghstaddr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  31.3 KB  |  1,156 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 "socklib.h"
  39. #include <sys/param.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <arpa/inet.h>
  43. #include <arpa/nameser.h>
  44. #include <netdb.h>
  45. #include <resolv.h>
  46. #include <ioctl.h>
  47. #include <unistd.h>
  48. #include <stdio.h>
  49. #include <ctype.h>
  50. #include <errno.h>
  51. #include <string.h>
  52.  
  53. #include <net/if.h>             /* for struct ifconf */
  54. #include <sockios.h>        /* for SIOC* */
  55.  
  56. #ifdef __MINT__
  57. #include <support.h>        /* for gethostname() */
  58. #define strcasecmp(a,b)        stricmp(a,b)
  59. #define strncasecmp(a,b,c)    strnicmp(a,b,c)
  60. #endif
  61.  
  62. #ifndef MAXHOSTNAMELEN
  63. #define MAXHOSTNAMELEN    64
  64. #endif
  65.  
  66. #define    MAXALIASES    35
  67. #define    MAXADDRS    35
  68. #define MAXTRIMDOMAINS  4
  69. #define HOSTDB        _PATH_HOSTS
  70.  
  71. #define SERVICE_NONE    0
  72. #define SERVICE_BIND    1
  73. #define SERVICE_HOSTS    2
  74. #define SERVICE_NIS    3
  75. #define SERVICE_MAX    3
  76.  
  77. #define CMD_ORDER    "order"
  78. #define CMD_TRIMDOMAIN    "trim"
  79. #define CMD_HMA        "multi"
  80. #define CMD_SPOOF    "nospoof"
  81. #define CMD_SPOOFALERT    "alert"
  82. #define CMD_REORDER    "reorder"
  83. #define CMD_ON        "on"
  84. #define CMD_OFF        "off"
  85. #define CMD_WARN    "warn"
  86. #define CMD_NOWARN    "warn off"
  87.  
  88. #define ORD_BIND    "bind"
  89. #define ORD_HOSTS    "hosts"
  90. #define ORD_NIS        "nis"
  91.  
  92. #define ENV_HOSTCONF    "RESOLV_HOST_CONF"
  93. #define ENV_SERVORDER    "RESOLV_SERV_ORDER"
  94. #define ENV_SPOOF    "RESOLV_SPOOF_CHECK"
  95. #define ENV_TRIM_OVERR    "RESOLV_OVERRIDE_TRIM_DOMAINS"
  96. #define ENV_TRIM_ADD    "RESOLV_ADD_TRIM_DOMAINS"
  97. #define ENV_HMA        "RESOLV_MULTI"
  98. #define ENV_REORDER    "RESOLV_REORDER"
  99.  
  100. #define TOKEN_SEPARATORS " ,;:"
  101.  
  102. static int service_order[SERVICE_MAX + 1];
  103. static int service_done = 0;
  104.  
  105. static char *h_addr_ptrs[MAXADDRS + 1];
  106.  
  107. static struct hostent host;
  108. static char *host_aliases[MAXALIASES];
  109. static char hostbuf[BUFSIZ+1];
  110. static struct in_addr host_addr;
  111. static FILE *hostf = NULL;
  112. static char hostaddr[MAXADDRS];
  113. static char *host_addrs[2];
  114. static int stayopen = 0;
  115. static int hosts_multiple_addrs = 0;
  116. static int spoof = 0;
  117. static int spoofalert = 0;
  118. static int reorder = 0;
  119. static char *trimdomain[MAXTRIMDOMAINS];
  120. static char trimdomainbuf[BUFSIZ];
  121. static int numtrimdomains = 0;
  122. char *strpbrk();
  123. extern char *strstr(), *strtok(), *getenv();
  124.  
  125. #ifdef NIS
  126. static struct hostent *_getnishost();
  127. #endif
  128.  
  129. #if PACKETSZ > 1024
  130. #define    MAXPACKET    PACKETSZ
  131. #else
  132. #define    MAXPACKET    1024
  133. #endif
  134.  
  135. typedef union {
  136.     HEADER hdr;
  137.     u_char buf[MAXPACKET];
  138. } querybuf;
  139.  
  140. typedef union {
  141.     long al;
  142.     char ac;
  143. } align;
  144.  
  145. int h_errno;
  146.  
  147. static void
  148. dotrimdomain(c)
  149. char *c;
  150. {
  151.     /* assume c points to the start of a host name; trim off any 
  152.        domain name matching any of the trimdomains */
  153.     int d,l1,l2;
  154.     
  155.     for(d=0;d<numtrimdomains;d++){
  156.         l1=strlen(trimdomain[d]);
  157.         l2=strlen(c);
  158.         if(l2>l1 && !strcasecmp(c+l2-l1,trimdomain[d]))
  159.             *(c+(strlen(c)-l1))='\0';
  160.     }
  161. }
  162.  
  163. static struct hostent *
  164. trim_domains(h)
  165. struct hostent *h;
  166. {
  167.     if(numtrimdomains){
  168.         int i;
  169.         dotrimdomain(h->h_name);
  170.         for(i=0;h->h_aliases[i];i++)
  171.             dotrimdomain(h->h_aliases[i]);
  172.     }
  173.     return(h);
  174. }
  175.  
  176. /* reorder_addrs -- by Tom Limoncelli
  177.     Optimize order of an address list.
  178.  
  179.     gethostbyaddr() usually returns a list of addresses in some
  180.     arbitrary order.  Most programs use the first one and throw the
  181.     rest away.  This routine attempts to find a "best" address and
  182.     swap it into the first position in the list.  "Best" is defined
  183.     as "an address that is on a local subnet".  The search ends after
  184.     one "best" address is found.  If no "best" address is found,
  185.     nothing is changed.
  186.  
  187.     On first execution, a table is built of interfaces, netmasks,
  188.     and mask'ed addresses.  This is to speed up future queries but
  189.     may require you to reboot after changing internet addresses.
  190.     (doesn't everyone reboot after changing internet addresses?)
  191.  
  192.     This routine should not be called if gethostbyaddr() is about
  193.     to return only one address.
  194.  
  195. */
  196.  
  197. /* Hal Stern (June 1992) of Sun claimed that more than 4 ethernets in a
  198. Sun 4/690 would not work.  This variable is set to 10 to accomodate our
  199. version of reality */
  200. #define MAXINTERFACES (10)
  201.  
  202. static void reorder_addrs(h)
  203. struct hostent *h;
  204. {
  205.     static struct {
  206.         char iname[16];
  207.         u_long address, netmask;
  208.         } itab[MAXINTERFACES], *itp;
  209.     static numitab = -1;    /* number of used entries in itab */
  210.     register struct in_addr **r; /* pointer to entry in address list */
  211.     struct in_addr tmp; /* pointer to entry in address list */
  212.     register int cnt;
  213.  
  214.     /***    itab[] contains masked addresses and netmask of each interface.
  215.             numitab is -1 : table is empty.
  216.             numitab is 0  : should never happen.
  217.             numitab is 1,2,3,... :  number of valid entries in the table.
  218.     ***/
  219.     if (!numitab) return;    /* no entries in table */
  220.     if (numitab==-1) { /* build the table */
  221.         int fd, err;
  222.         struct ifconf ifs;
  223.         struct ifreq ifbuf[MAXINTERFACES], *p;
  224.         register struct sockaddr_in *q;
  225.         u_long address, netmask;
  226.         int endp;
  227.  
  228.         /* open a socket */
  229.         fd = socket(PF_INET, SOCK_DGRAM, 0);
  230.         if (fd==-1) return;
  231.  
  232.         /**** get information about the first MAXINTERFACES interfaces ****/
  233.         /* set up the ifconf structure */
  234.         ifs.ifc_len = MAXINTERFACES * sizeof(struct ifreq);
  235.         ifs.ifc_buf = (caddr_t) ifbuf;
  236.         /* get a list of interfaces */
  237.         err = ioctl(fd, SIOCGIFCONF, &ifs);
  238.         if (err == -1) return;
  239.  
  240.         /**** cycle through each interface & get netmask & address ****/
  241.         endp = ifs.ifc_len / sizeof(struct ifreq);
  242.         itp = itab;
  243.         for (p = ifs.ifc_req; endp; p++, endp--) {
  244.             strcpy( itp->iname , p->ifr_name); /* copy interface name */
  245.  
  246.             err = ioctl(fd, SIOCGIFNETMASK, p); /* get netmask */
  247.             if (err == -1) continue;    /* error? skip this interface */
  248.             q = (struct sockaddr_in *) &(p->ifr_addr);
  249.             if (q->sin_family == AF_INET) netmask=q->sin_addr.s_addr;
  250.             else continue;    /* not internet protocol? skip this interface */
  251.  
  252.             err = ioctl(fd, SIOCGIFADDR, p); /* get address */
  253.             if (err == -1) continue;    /* error? skip this interface */
  254.             q = (struct sockaddr_in *) &(p->ifr_addr);
  255.             if (q->sin_family == AF_INET) address=q->sin_addr.s_addr;
  256.             else continue;    /* not internet protocol? skip this interface */
  257.  
  258.             /* store the masked address and netmask in the table */
  259.             address = address & netmask;    /* pre-mask the address */
  260.             if (!address) continue;    /* funny address? skip this interface */
  261.             itp->address = address;
  262.             itp->netmask = netmask;
  263.  
  264.             if (numitab == -1) numitab = 0;     /* first time through */
  265.             itp++; numitab++;
  266.         }
  267.         /**** clean up ****/
  268.         close(fd);
  269.         /**** if we still don't have a table, leave */
  270.         if (!numitab) return;
  271.     }
  272.  
  273.     /**** loop through table for each (address,interface) combo ****/
  274.     for ( r = (struct in_addr **) (h->h_addr_list); *r; r++) {    /* loop through the addresses */
  275.         for ( itp = itab, cnt=numitab; cnt; itp++,cnt--) {    /* loop though the interfaces */
  276.             if (( (*r)->s_addr & itp->netmask) == itp->address) {    /* compare */
  277.                 /* We found a match.  Swap it into [0] */
  278.                 bcopy( ((struct in_addr **) (h->h_addr_list))[0],    &tmp, sizeof(tmp));
  279.                 bcopy( (*r),    ((struct in_addr **) (h->h_addr_list))[0], sizeof(tmp));
  280.                 bcopy( &tmp,                                      (*r), sizeof(tmp));
  281.  
  282.                 return;    /* found one, don't need to continue */
  283.             }
  284.         } /* interfaces */
  285.     } /* addresses */
  286. }
  287.  
  288. static void
  289. init_services()
  290. {
  291.     char *cp, *dp, buf[BUFSIZ];
  292.     register int cc = 0;
  293.     FILE *fd;
  294.     char *tdp = trimdomainbuf;
  295.     char *hostconf;
  296.  
  297.     if(NULL==(hostconf=getenv(ENV_HOSTCONF))){
  298.         hostconf=_PATH_HOSTCONF;
  299.     }
  300.     if ((fd = (FILE *)fopen(hostconf, "rt")) == NULL) {
  301.                 /* make some assumptions */
  302.         service_order[0] = SERVICE_HOSTS;
  303.         service_order[1] = SERVICE_BIND;
  304.         service_order[2] = SERVICE_NONE;
  305.     } else {
  306.         while (fgets(buf, BUFSIZ, fd) != NULL) {
  307.             if ((cp = rindex(buf, '\n')) != NULL)
  308.                 *cp = '\0';
  309.             if (buf[0] == '#')
  310.                 continue;
  311.  
  312. #define checkbuf(b, cmd) (!strncasecmp(b, cmd, strlen(cmd)))
  313. #define bad_config_format(cmd) \
  314.     fprintf(stderr, "resolv+: %s: \"%s\" command incorrectly formatted.\n", hostconf, cmd);
  315.  
  316.             if (checkbuf(buf, CMD_ORDER)) {
  317.                 cp = strpbrk(buf, " \t");
  318.                 if (!cp) 
  319.                                 {
  320.                                     bad_config_format(CMD_ORDER);
  321.                                 } else 
  322.                                 {
  323.                                     do {
  324.                     while (*cp == ' ' || *cp == '\t')
  325.                         cp++;
  326.                     dp = strpbrk(cp, TOKEN_SEPARATORS);
  327.                     if (dp) *dp = '\0';
  328.                     if (checkbuf(cp, ORD_BIND))
  329.                         service_order[cc++] = SERVICE_BIND;
  330.                     else if (checkbuf(cp, ORD_HOSTS))
  331.                         service_order[cc++] = SERVICE_HOSTS;
  332.                     else if (checkbuf(cp, ORD_NIS))
  333.                         service_order[cc++] = SERVICE_NIS;
  334.                     else
  335.                                         {
  336.                                             bad_config_format(CMD_ORDER);
  337.                                             fprintf(stderr, "resolv+: \"%s\" is an invalid keyword\n", cp);
  338.                                             fprintf(stderr, "resolv+: valid keywords are: %s, %s and %s\n",
  339.                                                    ORD_BIND, ORD_HOSTS, ORD_NIS);
  340.                                         }
  341.                                         
  342.                     if (dp) cp = ++dp;
  343.                                     } while (dp != NULL);
  344.                                     if (cc == 0) 
  345.                                     {
  346.                                         bad_config_format(CMD_ORDER);
  347.                                         fprintf(stderr, "resolv+: search order not specified or unrecognized keyword, host resolution will fail.\n");
  348.                                     }
  349.                                 }
  350.                                         
  351.             } else if (checkbuf(buf, CMD_HMA)) {
  352.                             if ( cp = strpbrk(buf, " \t") ) 
  353.                             {
  354.                 while (*cp == ' ' || *cp == '\t') cp++;
  355.                 if (checkbuf(cp, CMD_ON))
  356.                     hosts_multiple_addrs = 1;
  357.                             } else
  358.                                 bad_config_format(CMD_HMA);
  359.                                 
  360.             } else if (checkbuf(buf, CMD_SPOOF)) {
  361.                             if ( cp = strpbrk(buf, " \t") ) 
  362.                             {
  363.                 while (*cp == ' ' || *cp == '\t') cp++;
  364.                 if (checkbuf(cp, CMD_ON))
  365.                     spoof = 1;
  366.                             } else
  367.                                 bad_config_format(CMD_SPOOF);
  368.  
  369.             } else if (checkbuf(buf, CMD_SPOOFALERT)) {
  370.                             if ( cp = strpbrk(buf, " \t") ) 
  371.                             {
  372.                 while (*cp == ' ' || *cp == '\t') cp++;
  373.                 if (checkbuf(cp, CMD_ON))
  374.                     spoofalert = 1;
  375.                             } else
  376.                                 bad_config_format(CMD_SPOOFALERT);
  377.                             
  378.             } else if (checkbuf(buf, CMD_REORDER)) {
  379.                 if (cp = strpbrk(buf, " \t")) {
  380.                 while (*cp == ' ' || *cp == '\t') cp++;
  381.                 if (checkbuf(cp, CMD_ON))
  382.                     reorder = 1;
  383.                 } else
  384.                     bad_config_format(CMD_REORDER);
  385.  
  386.             } else if (checkbuf(buf, CMD_TRIMDOMAIN)) {
  387.                 if(numtrimdomains<MAXTRIMDOMAINS){
  388.                                     if ( cp = strpbrk(buf, " \t") ) 
  389.                                     {
  390.                     while (*cp == ' ' || *cp == '\t') cp++;
  391.                                         if (cp) 
  392.                                         {
  393.                                             (void) strcpy(tdp,cp);    
  394.                                             trimdomain[numtrimdomains++]=tdp;
  395.                                             tdp += strlen(cp)+1;
  396.                                         } else
  397.                                             bad_config_format(CMD_TRIMDOMAIN);
  398.                                     } else
  399.                                         bad_config_format(CMD_TRIMDOMAIN);
  400.                 }
  401.             }
  402.         }
  403.         
  404.         service_order[cc] = SERVICE_NONE;
  405.         fclose(fd);
  406.     }
  407.     /* override service_order if environment variable */
  408.     if(NULL!=(cp=getenv(ENV_SERVORDER))){
  409.         cc=0;
  410.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  411.             do{
  412.                 if(checkbuf(cp, ORD_BIND))
  413.                     service_order[cc++] = SERVICE_BIND;
  414.                 else if (checkbuf(cp, ORD_HOSTS))
  415.                     service_order[cc++] = SERVICE_HOSTS;
  416.                 else if (checkbuf(cp, ORD_NIS))
  417.                     service_order[cc++] = SERVICE_NIS;
  418.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  419.         service_order[cc] = SERVICE_NONE;
  420.         }
  421.     }
  422.     /* override spoof if environment variable */
  423.     if(NULL!=(cp=getenv(ENV_SPOOF))){
  424.         if(checkbuf(cp, CMD_WARN)){
  425.             spoof=1;
  426.             spoofalert=1;
  427.         } else if (checkbuf(cp, CMD_OFF)){
  428.             spoof=0;
  429.             spoofalert=0;
  430.         } else if (checkbuf(cp, CMD_NOWARN)){
  431.             spoof=1;
  432.             spoofalert=0;
  433.         } else {
  434.             spoof=1;
  435.         }
  436.     }
  437.  
  438.     /* override hma if environment variable */
  439.     if(NULL!=(cp=getenv(ENV_HMA)))
  440.         if(checkbuf(cp, CMD_ON))
  441.             hosts_multiple_addrs=1;
  442.         else
  443.             hosts_multiple_addrs=0;
  444.  
  445.     /* override reorder if environment variable */
  446.     if ((cp = getenv(ENV_REORDER)) != NULL)
  447.         if (checkbuf(cp, CMD_ON))
  448.             reorder = 1;
  449.         else
  450.             reorder = 0;
  451.  
  452.     /* add trimdomains from environment variable */
  453.     if(NULL!=(cp=getenv(ENV_TRIM_ADD))){
  454.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  455.             do{
  456.                 if(numtrimdomains<MAXTRIMDOMAINS){
  457.                     (void)strcpy(tdp, cp);
  458.                     trimdomain[numtrimdomains++]=tdp;
  459.                     tdp += strlen(cp)+1;
  460.                 }
  461.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  462.         }
  463.     }
  464.  
  465.     /* override trimdomains from environment variable */
  466.     if(NULL!=(cp=getenv(ENV_TRIM_OVERR))){
  467.         numtrimdomains=0;
  468.         tdp=trimdomainbuf;
  469.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  470.             do{
  471.                 if(numtrimdomains<MAXTRIMDOMAINS){
  472.                     (void)strcpy(tdp, cp);
  473.                     trimdomain[numtrimdomains++]=tdp;
  474.                     tdp += strlen(cp)+1;
  475.                 }
  476.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  477.         }
  478.     }
  479.     
  480.     service_done = 1;
  481. }
  482.  
  483. static struct hostent *
  484. getanswer(answer, anslen, iquery)
  485.     querybuf *answer;
  486.     int anslen;
  487.     int iquery;
  488. {
  489.     register HEADER *hp;
  490.     register u_char *cp;
  491.     register int n;
  492.     u_char *eom;
  493.     char *bp, **ap;
  494.     int type, class, buflen, ancount, qdcount;
  495.     int haveanswer, getclass = C_ANY;
  496.     char **hap;
  497.  
  498.     eom = answer->buf + anslen;
  499.     /*
  500.      * find first satisfactory answer
  501.      */
  502.     hp = &answer->hdr;
  503.     ancount = ntohs(hp->ancount);
  504.     qdcount = ntohs(hp->qdcount);
  505.     bp = hostbuf;
  506.     buflen = sizeof(hostbuf);
  507.     cp = answer->buf + sizeof(HEADER);
  508.     if (qdcount) {
  509.         if (iquery) {
  510.             if ((n = dn_expand((u_char *)answer->buf,
  511.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  512.                 buflen)) < 0) {
  513.                 h_errno = NO_RECOVERY;
  514.                 return ((struct hostent *) NULL);
  515.             }
  516.             cp += n + QFIXEDSZ;
  517.             host.h_name = bp;
  518.             n = strlen(bp) + 1;
  519.             bp += n;
  520.             buflen -= n;
  521.         } else
  522.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  523.         while (--qdcount > 0)
  524.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  525.     } else if (iquery) {
  526.         if (hp->aa)
  527.             h_errno = HOST_NOT_FOUND;
  528.         else
  529.             h_errno = TRY_AGAIN;
  530.         return ((struct hostent *) NULL);
  531.     }
  532.     ap = host_aliases;
  533.     *ap = NULL;
  534.     host.h_aliases = host_aliases;
  535.     hap = h_addr_ptrs;
  536.     *hap = NULL;
  537. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  538.     host.h_addr_list = h_addr_ptrs;
  539. #endif
  540.     haveanswer = 0;
  541.     while (--ancount >= 0 && cp < eom) {
  542.         if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
  543.             (u_char *)cp, (u_char *)bp, buflen)) < 0)
  544.             break;
  545.         cp += n;
  546.         type = _getshort(cp);
  547.          cp += sizeof(u_short);
  548.         class = _getshort(cp);
  549.          cp += sizeof(u_short) + sizeof(u_long);
  550.         n = _getshort(cp);
  551.         cp += sizeof(u_short);
  552.         if (type == T_CNAME) {
  553.             cp += n;
  554.             if (ap >= &host_aliases[MAXALIASES-1])
  555.                 continue;
  556.             *ap++ = bp;
  557.             n = strlen(bp) + 1;
  558.             bp += n;
  559.             buflen -= n;
  560.             continue;
  561.         }
  562.         if (iquery && type == T_PTR) {
  563.             if ((n = dn_expand((u_char *)answer->buf,
  564.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  565.                 buflen)) < 0)
  566.                 break;
  567.             cp += n;
  568.             host.h_name = bp;
  569.             return(&host);
  570.         }
  571.         if (iquery || type != T_A)  {
  572. #ifdef DEBUG
  573.             if (_res.options & RES_DEBUG)
  574.                 printf("unexpected answer type %d, size %d\n",
  575.                     type, n);
  576. #endif
  577.             cp += n;
  578.             continue;
  579.         }
  580.         if (haveanswer) {
  581.             if (n != host.h_length) {
  582.                 cp += n;
  583.                 continue;
  584.             }
  585.             if (class != getclass) {
  586.                 cp += n;
  587.                 continue;
  588.             }
  589.         } else {
  590.             host.h_length = n;
  591.             getclass = class;
  592.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  593.             if (!iquery) {
  594.                 host.h_name = bp;
  595.                 bp += strlen(bp) + 1;
  596.             }
  597.         }
  598.  
  599.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  600.  
  601.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  602. #ifdef DEBUG
  603.             if (_res.options & RES_DEBUG)
  604.                 printf("size (%d) too big\n", n);
  605. #endif
  606.             break;
  607.         }
  608.         bcopy(cp, *hap++ = bp, n);
  609.         bp +=n;
  610.         cp += n;
  611.         haveanswer++;
  612.     }
  613.     if (haveanswer) {
  614.         *ap = NULL;
  615. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  616.         *hap = NULL;
  617. #else
  618.         host.h_addr = h_addr_ptrs[0];
  619. #endif
  620.         return (&host);
  621.     } else {
  622.         h_errno = TRY_AGAIN;
  623.         return ((struct hostent *) NULL);
  624.     }
  625. }
  626.  
  627. struct hostent *
  628. gethostbyname(name)
  629.     const char *name;
  630. {
  631.     querybuf buf;
  632.     register const char *cp;
  633.     register int cc;
  634.     int n;
  635.     struct hostent *hp;
  636.     extern struct hostent *_gethtbyname();
  637.  
  638.     /*
  639.      * disallow names consisting only of digits/dots, unless
  640.      * they end in a dot.
  641.      */
  642.     if (isdigit(name[0]))
  643.         for (cp = name;; ++cp) {
  644.             if (!*cp) {
  645.                 if (*--cp == '.')
  646.                     break;
  647.                 /*
  648.                  * All-numeric, no dot at the end.
  649.                  * Fake up a hostent as if we'd actually
  650.                  * done a lookup.
  651.                  */
  652.                 if (!inet_aton(name, &host_addr)) {
  653.                     h_errno = HOST_NOT_FOUND;
  654.                     return((struct hostent *) NULL);
  655.                 }
  656.                 host.h_name = (char *)name;
  657.                 host.h_aliases = host_aliases;
  658.                 host_aliases[0] = NULL;
  659.                 host.h_addrtype = AF_INET;
  660.                 host.h_length = sizeof(u_long);
  661.                 h_addr_ptrs[0] = (char *)&host_addr;
  662.                 h_addr_ptrs[1] = (char *)0;
  663. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  664.                 host.h_addr_list = h_addr_ptrs;
  665. #else
  666.                 host.h_addr = h_addr_ptrs[0];
  667. #endif
  668.                 return (&host);
  669.             }
  670.             if (!isdigit(*cp) && *cp != '.') 
  671.                 break;
  672.         }
  673.  
  674.     if (!service_done)
  675.         init_services();
  676.  
  677.     for (cc = 0; service_order[cc] != SERVICE_NONE &&
  678.          cc <= SERVICE_MAX; cc++) {
  679.         switch (service_order[cc]) {
  680.         case SERVICE_BIND:
  681.             if ((n = res_search(name, C_IN, T_A,
  682.                         buf.buf, sizeof(buf))) < 0) {
  683. #ifdef DEBUG
  684.                 if (_res.options & RES_DEBUG)
  685.                     printf("res_search failed\n");
  686. #endif
  687.                 break;
  688.             }
  689.             hp = getanswer(&buf, n, 0);
  690.             if (h_addr_ptrs[1] && reorder)
  691.                 reorder_addrs(hp);
  692.             if (hp) 
  693.                 return trim_domains(hp);
  694.             break;
  695.         case SERVICE_HOSTS:
  696.             hp = _gethtbyname(name);
  697.             if (h_addr_ptrs[1] && reorder)
  698.                 reorder_addrs(hp);
  699.             if (hp)
  700.                 return hp;
  701.             h_errno = HOST_NOT_FOUND;
  702.             break;
  703. #ifdef NIS
  704.         case SERVICE_NIS:
  705.             hp = _getnishost(name, "hosts.byname");
  706.             if (h_addr_ptrs[1] && reorder)
  707.                 reorder_addrs(hp);
  708.             if (hp)
  709.                 return hp;
  710.             h_errno = HOST_NOT_FOUND;
  711.             break;
  712. #endif /* NIS */
  713.         }
  714.     }
  715.     return ((struct hostent *) NULL);
  716. }
  717.  
  718. struct hostent *
  719. gethostbyaddr(addr, len, type)
  720.     const char *addr;
  721.     int len, type;
  722. {
  723.     int n;
  724.     querybuf buf;
  725.     register int cc;
  726.     register struct hostent *hp;
  727.     char qbuf[MAXDNAME];
  728.     extern struct hostent *_gethtbyaddr();
  729.     
  730.     if (type != AF_INET)
  731.         return ((struct hostent *) NULL);
  732.     if (!service_done)
  733.       init_services();
  734.  
  735.     cc = 0;
  736.     while (service_order[cc] != SERVICE_NONE) {
  737.             switch (service_order[cc]) {
  738.         case SERVICE_BIND:
  739.             (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  740.                       ((unsigned)addr[3] & 0xff),
  741.                       ((unsigned)addr[2] & 0xff),
  742.                       ((unsigned)addr[1] & 0xff),
  743.                       ((unsigned)addr[0] & 0xff));
  744.             n = res_query(qbuf, C_IN, T_PTR, (char *)&buf,
  745.                       sizeof(buf));
  746.             if (n < 0) {
  747. #ifdef DEBUG
  748.                 if (_res.options & RES_DEBUG)
  749.                     printf("res_query failed\n");
  750. #endif
  751.                 break;
  752.             }
  753.             hp = getanswer(&buf, n, 1);
  754.             if (hp) {
  755.                 if(spoof){
  756.                     /* Spoofing check code by
  757.                      * Caspar Dik <casper@fwi.uva.nl> 
  758.                      */
  759.                     char nambuf[MAXDNAME+1];
  760.                     int ntd, namelen = strlen(hp->h_name);
  761.                     char **addrs;
  762.                     
  763.                     if (namelen >= MAXDNAME)
  764.                         return (struct hostent *)NULL;
  765.                     (void) strcpy(nambuf,hp->h_name);
  766.                     nambuf[namelen] = '.';
  767.                     nambuf[namelen+1] = '\0';
  768.  
  769.                     /* 
  770.                      * turn off domain trimming,
  771.                      * call gethostbyname(), then turn    
  772.                      * it back on, if applicable. This
  773.                      * prevents domain trimming from
  774.                      * making the name comparison fail.
  775.                      */
  776.                     ntd=numtrimdomains; 
  777.                     numtrimdomains=0;
  778.                     hp=gethostbyname(nambuf);
  779.                     numtrimdomains=ntd;
  780.                     nambuf[namelen] = 0;
  781.                     /*
  782.                     * the name must exist and the name 
  783.                     * returned by gethostbyaddr must be 
  784.                     * the canonical name and therefore 
  785.                     * identical to the name returned by 
  786.                     * gethostbyname()
  787.                     */
  788.                     if (!hp || strcmp(nambuf, hp->h_name)){
  789.                         h_errno = HOST_NOT_FOUND;
  790.                         return (struct hostent *)NULL;
  791.                     }
  792.                     /*
  793.                     * now check the addresses
  794.                     */
  795. #if defined(h_addr) || BSD >= 43
  796.                     for (addrs = hp->h_addr_list; 
  797.                         *addrs; addrs++){
  798.                         if (!bcmp(addrs[0], addr, len))
  799.                             return trim_domains(hp);
  800.                     }
  801. #else
  802.                     if (!bcmp(hp->h_addr, addr, len)))
  803.                         return trim_domains(hp);
  804. #endif
  805.                     /* We've been spoofed */
  806.                     h_errno = HOST_NOT_FOUND;
  807. #if 0
  808.                     if(spoofalert){
  809.                         openlog("resolv", LOG_PID,
  810.                             LOG_AUTH);
  811.                         syslog(LOG_NOTICE,
  812.                             "gethostbyaddr: %s != %u.%u.%u.%u, possible spoof attempt",
  813.                             hp->h_name,
  814.                             ((unsigned)addr[0]&0xff),
  815.                             ((unsigned)addr[1]&0xff),
  816.                             ((unsigned)addr[2]&0xff),
  817.                             ((unsigned)addr[3]&0xff));
  818.                     } 
  819. #endif
  820.                     return (struct hostent *)NULL;
  821.                 }
  822.                 hp->h_addrtype = type;
  823.                 hp->h_length = len;
  824.                 h_addr_ptrs[0] = (char *)&host_addr;
  825.                 h_addr_ptrs[1] = (char *)0;
  826.                 host_addr = *(struct in_addr *)addr;
  827. #if BSD < 43 && !defined(h_addr)    /* new-style hostent structure */
  828.                 hp->h_addr = h_addr_ptrs[0];
  829. #endif
  830.                 return trim_domains(hp);
  831.             }
  832.             h_errno = HOST_NOT_FOUND;
  833.             break;
  834.         case SERVICE_HOSTS:
  835.             hp = _gethtbyaddr(addr, len, type);
  836.             if (hp) 
  837.                 return hp;
  838.             h_errno = HOST_NOT_FOUND;
  839.             break;
  840. #ifdef NIS
  841.         case SERVICE_NIS:
  842.             (void)sprintf(qbuf, "%u.%u.%u.%u",
  843.                       ((unsigned)addr[0] & 0xff),
  844.                       ((unsigned)addr[1] & 0xff),
  845.                       ((unsigned)addr[2] & 0xff),
  846.                       ((unsigned)addr[3] & 0xff));
  847.             hp = _getnishost(qbuf, "hosts.byaddr");
  848.             if (hp)
  849.                 return hp;
  850.             h_errno = HOST_NOT_FOUND;
  851.             break;
  852. #endif /* NIS */
  853.         }
  854.         cc++;
  855.     }
  856.     return ((struct hostent *)NULL);
  857. }
  858.  
  859. void
  860. _sethtent(f)
  861.     int f;
  862. {
  863.     if (hostf == NULL)
  864.         hostf = fopen(_PATH_HOSTS, "rt" );
  865.     else
  866.         rewind(hostf);
  867.     stayopen |= f;
  868. }
  869.  
  870. void
  871. _endhtent()
  872. {
  873.     if (hostf && !stayopen) {
  874.         (void) fclose(hostf);
  875.         hostf = NULL;
  876.     }
  877. }
  878.  
  879. struct hostent *
  880. _gethtent()
  881. {
  882.     char *p;
  883.     register char *cp, **q;
  884.  
  885.     if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "rt" )) == NULL)
  886.         return (NULL);
  887. again:
  888.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  889.         return (NULL);
  890.     if (*p == '#')
  891.         goto again;
  892.     cp = strpbrk(p, "#\n");
  893.     if (cp == NULL)
  894.         goto again;
  895.     *cp = '\0';
  896.     cp = strpbrk(p, " \t");
  897.     if (cp == NULL)
  898.         goto again;
  899.     *cp++ = '\0';
  900.     /* THIS STUFF IS INTERNET SPECIFIC */
  901. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  902.     host.h_addr_list = host_addrs;
  903. #endif
  904.     host.h_addr = hostaddr;
  905.     *((u_long *)host.h_addr) = inet_addr(p);
  906.     host.h_length = sizeof (u_long);
  907.     host.h_addrtype = AF_INET;
  908.     while (*cp == ' ' || *cp == '\t')
  909.         cp++;
  910.     host.h_name = cp;
  911.     q = host.h_aliases = host_aliases;
  912.     cp = strpbrk(cp, " \t");
  913.     if (cp != NULL) 
  914.         *cp++ = '\0';
  915.     while (cp && *cp) {
  916.         if (*cp == ' ' || *cp == '\t') {
  917.             cp++;
  918.             continue;
  919.         }
  920.         if (q < &host_aliases[MAXALIASES - 1])
  921.             *q++ = cp;
  922.         cp = strpbrk(cp, " \t");
  923.         if (cp != NULL)
  924.             *cp++ = '\0';
  925.     }
  926.     *q = NULL;
  927.     return (&host);
  928. }
  929.  
  930. /* if hosts_multiple_addrs set, then gethtbyname behaves as follows:
  931.  *  - for hosts with multiple addresses, return all addresses, such that
  932.  *  the first address is most likely to be one on the same net as the
  933.  *  host we're running on, if one exists. 
  934.  *  - like the dns version of gethostsbyname, the alias field is empty
  935.  *  unless the name being looked up is an alias itself, at which point the
  936.  *  alias field contains that name, and the name field contains the primary
  937.  *  name of the host. Unlike dns, however, this behavior will still take place
  938.  *  even if the alias applies only to one of the interfaces. 
  939.  *  - determining a "local" address to put first is dependant on the netmask 
  940.  *  being such that the least significant network bit is more significant 
  941.  *  than any host bit. Only strange netmasks will violate this. 
  942.  *  - we assume addresses fit into u_longs. That's quite internet specific.
  943.  *  - if the host we're running on is not in the host file, the address 
  944.  *  shuffling will not take place.
  945.  *                     - John DiMarco <jdd@cdf.toronto.edu>
  946.  */ 
  947. struct hostent *
  948. _gethtbyname(name)
  949.     char *name;
  950. {
  951.     register struct hostent *p;
  952.     register char **cp;
  953.     char **hap, **lhap, *bp, *lbp;
  954.     int htbuflen, locbuflen;
  955.     int found=0, localfound=0;
  956.     char localname[MAXHOSTNAMELEN];
  957.  
  958.     static char htbuf[BUFSIZ+1]; /* buffer for host addresses */
  959.     static char locbuf[BUFSIZ+1]; /* buffer for local hosts's addresses */
  960.     static char *ht_addr_ptrs[MAXADDRS+1];
  961.     static char *loc_addr_ptrs[MAXADDRS+1];
  962.     static struct hostent ht;
  963.     static char *aliases[MAXALIASES];
  964.     static char namebuf[MAXHOSTNAMELEN];
  965.     
  966.     hap = ht_addr_ptrs;
  967.     lhap = loc_addr_ptrs;
  968.     *hap = NULL;
  969.     *lhap = NULL;
  970.     bp=htbuf;
  971.     lbp=locbuf;
  972.     htbuflen = sizeof(htbuf);
  973.     locbuflen = sizeof(locbuf);
  974.  
  975.     aliases[0]=NULL;
  976.     aliases[1]=NULL;
  977.     (void) strcpy(namebuf, name);
  978.  
  979.     (void)gethostname(localname, sizeof(localname));
  980.  
  981.     _sethtent(0);
  982.     while (p = _gethtent()) {
  983.         if (strcasecmp(p->h_name, name) == 0) 
  984.             found++;
  985.         else 
  986.             for (cp = p->h_aliases; *cp != 0; cp++)
  987.                 if (strcasecmp(*cp, name) == 0){ 
  988.                     found++;
  989.                     aliases[0]=name;
  990.                     (void) strcpy(namebuf, p->h_name);
  991.                 }
  992.         if (strcasecmp(p->h_name, localname) == 0)
  993.             localfound++;
  994.         else
  995.             for (cp=p->h_aliases; *cp != 0; cp++)
  996.                 if (strcasecmp(*cp, localname) == 0)
  997.                     localfound++;
  998.  
  999.         if(found){
  1000.             int n;
  1001.  
  1002.             if(!hosts_multiple_addrs){
  1003.                 /* original behaviour requested */
  1004.                 _endhtent();
  1005.                 return(p);
  1006.             }
  1007.             n = p->h_length;
  1008.  
  1009.             ht.h_addrtype = p->h_addrtype;
  1010.             ht.h_length = p->h_length;
  1011.  
  1012.             if(n<=htbuflen){
  1013.                 /* add the found address to the list */
  1014.                 bcopy(p->h_addr_list[0], bp, n);
  1015.                 *hap++=bp;
  1016.                 *hap=NULL;
  1017.                 bp+=n;
  1018.                 htbuflen-=n;
  1019.             }
  1020.             found=0;
  1021.         }
  1022.         if(localfound){
  1023.             int n = p->h_length;
  1024.             if(n<=locbuflen){
  1025.                 /* add the found local address to the list */
  1026.                 bcopy(p->h_addr_list[0], lbp, n);
  1027.                 *lhap++=lbp;
  1028.                 *lhap=NULL;
  1029.                 lbp+=n;
  1030.                 locbuflen-=n;
  1031.             }
  1032.             localfound=0;
  1033.         }
  1034.     }
  1035.     _endhtent();
  1036.  
  1037.     if(NULL==ht_addr_ptrs[0]){
  1038.         return((struct hostent *)NULL);
  1039.     }
  1040.  
  1041.     ht.h_aliases = aliases; 
  1042.     ht.h_name = namebuf;
  1043.  
  1044.     /* shuffle addresses around to ensure one on same net as local host 
  1045.        is first, if exists */
  1046.     {
  1047.         /* "best" address is assumed to be the one with the greatest
  1048.            number of leftmost bits matching any of the addresses of
  1049.            the local host. This assumes a netmask in which all net
  1050.            bits precede host bits. Usually but not always a fair 
  1051.            assumption. */
  1052.  
  1053.         /* portability alert: assumption: iaddr fits in u_long.
  1054.            This is really internet specific. */
  1055.         int i,j, best=0;
  1056.         u_long bestval = (u_long)~0;
  1057.         
  1058.         for(i=0;loc_addr_ptrs[i];i++){
  1059.             for(j=0;ht_addr_ptrs[j];j++){
  1060.                 u_long t, l, h;
  1061.                 /* assert(sizeof(u_long)>=ht.h_length); */
  1062.                 bcopy(loc_addr_ptrs[i], (char *)&t,
  1063.                     ht.h_length);
  1064.                 l=ntohl(t);
  1065.                 bcopy(ht_addr_ptrs[j], (char *)&t, 
  1066.                     ht.h_length);
  1067.                 t=l^h;
  1068.  
  1069.                 if(t<bestval){
  1070.                     best=j;
  1071.                     bestval=t;
  1072.                 }
  1073.             }
  1074.         }
  1075.         if(best){
  1076.             char *tmp;
  1077.  
  1078.             /* swap first and best address */
  1079.             tmp=ht_addr_ptrs[0];
  1080.             ht_addr_ptrs[0]=ht_addr_ptrs[best];
  1081.             ht_addr_ptrs[best]=tmp;
  1082.         }
  1083.     }
  1084.     
  1085.     ht.h_addr_list = ht_addr_ptrs;
  1086.     return (&ht);
  1087. }
  1088.  
  1089. struct hostent *
  1090. _gethtbyaddr(addr, len, type)
  1091.     const char *addr;
  1092.     int len, type;
  1093. {
  1094.     register struct hostent *p;
  1095.  
  1096.     _sethtent(0);
  1097.     while (p = _gethtent())
  1098.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  1099.             break;
  1100.     _endhtent();
  1101.     return (p);
  1102. }
  1103.  
  1104. #ifdef NIS
  1105. static struct hostent *
  1106. _getnishost(name, map)
  1107.     char *name, *map;
  1108. {
  1109.     register char *cp, *dp, **q;
  1110.     char *result;
  1111.     int resultlen;
  1112.     static struct hostent h;
  1113.     static char *domain = (char *)NULL;
  1114.  
  1115.     if (domain == (char *)NULL)
  1116.         if (yp_get_default_domain (&domain))
  1117.             return ((struct hostent *)NULL);
  1118.  
  1119.     if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
  1120.         return ((struct hostent *)NULL);
  1121.  
  1122.     if (cp = index(result, '\n'))
  1123.         *cp = '\0';
  1124.  
  1125.     cp = strpbrk(result, " \t");
  1126.     *cp++ = '\0';
  1127. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  1128.     h.h_addr_list = host_addrs;
  1129. #endif
  1130.     h.h_addr = hostaddr;
  1131.     *((u_long *)h.h_addr) = inet_addr(result);
  1132.     h.h_length = sizeof(u_long);
  1133.     h.h_addrtype = AF_INET;
  1134.     while (*cp == ' ' || *cp == '\t')
  1135.         cp++;
  1136.     h.h_name = cp;
  1137.     q = h.h_aliases = host_aliases;
  1138.     cp = strpbrk(cp, " \t");
  1139.     if (cp != NULL)
  1140.         *cp++ = '\0';
  1141.     while (cp && *cp) {
  1142.         if (*cp == ' ' || *cp == '\t') {
  1143.             cp++;
  1144.             continue;
  1145.         }
  1146.         if (q < &host_aliases[MAXALIASES - 1])
  1147.             *q++ = cp;
  1148.         cp = strpbrk(cp, " \t");
  1149.         if (cp != NULL)
  1150.             *cp++ = '\0';
  1151.     }
  1152.     *q = NULL;
  1153.     return (&h);
  1154. }
  1155. #endif /* NIS */
  1156.