home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / inet / gethstnmad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-02  |  35.8 KB  |  1,423 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 are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #if defined(LIBC_SCCS) && !defined(lint)
  19. static char sccsid[] = "@(#)gethostnamadr.c    6.39 (Berkeley) 1/4/90";
  20. #endif /* LIBC_SCCS and not lint */
  21.  
  22. #include "inetprivate.h"
  23. #include <syslog.h>
  24.  
  25. #if defined(USE_OPTIONS_H)
  26. # include "res_opts.h"
  27. #endif
  28.  
  29. #define    MAXALIASES    35
  30. #define    MAXADDRS    35
  31. #define MAXTRIMDOMAINS  4
  32.  
  33. #define _PATH_HOSTCONF    __PATH_ETC_INET"/host.conf"
  34.  
  35. /* Strict but flexible checking in _PATH_HOSTCONF file.
  36.  
  37.  * (+) Keywords need not start at the begining of the line.
  38.  * (+) Invalid keywords are warned.
  39.  * (+) Invalid booleans (other than "on" or "off") are warned.
  40.  
  41.  * Mitch DSouza <m.dsouza@mrc-apu.cam.ac.uk> - 30th October 1993
  42.  */
  43. #define STRICT
  44.  
  45. #define SERVICE_NONE    0
  46. #define SERVICE_BIND    1
  47. #define SERVICE_HOSTS    2
  48. #define SERVICE_NIS    3
  49. #define SERVICE_MAX    3
  50.  
  51. #define CMD_ORDER    "order"
  52. #define CMD_TRIMDOMAIN    "trim"
  53. #define CMD_HMA        "multi"
  54. #define CMD_SPOOF    "nospoof"
  55. #define CMD_SPOOFALERT    "alert"
  56. #define CMD_REORDER    "reorder"
  57. #define CMD_ON        "on"
  58. #define CMD_OFF        "off"
  59. #define CMD_WARN    "warn"
  60. #define CMD_NOWARN    "warn off"
  61.  
  62. #define ORD_BIND    "bind"
  63. #define ORD_HOSTS    "hosts"
  64. #define ORD_NIS        "nis"
  65.  
  66. #define ENV_HOSTCONF    "RESOLV_HOST_CONF"
  67. #define ENV_SERVORDER    "RESOLV_SERV_ORDER"
  68. #define ENV_SPOOF    "RESOLV_SPOOF_CHECK"
  69. #define ENV_TRIM_OVERR    "RESOLV_OVERRIDE_TRIM_DOMAINS"
  70. #define ENV_TRIM_ADD    "RESOLV_ADD_TRIM_DOMAINS"
  71. #define ENV_HMA        "RESOLV_MULTI"
  72. #define ENV_REORDER    "RESOLV_REORDER"
  73.  
  74. #define TOKEN_SEPARATORS " ,;:"
  75.  
  76. static int service_order[SERVICE_MAX + 1];
  77. static int service_done = 0;
  78.  
  79. static const char AskedForGot[] =
  80.               "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
  81.  
  82. static char *h_addr_ptrs[MAXADDRS + 1];
  83.  
  84. static struct hostent host;
  85. static char *host_aliases[MAXALIASES];
  86. static char hostbuf[BUFSIZ+1];
  87. static struct in_addr host_addr;
  88. static char HOSTDB[] = _PATH_HOSTS;
  89. static FILE *hostf = NULL;
  90. static char hostaddr[MAXADDRS];
  91. static char *host_addrs[2];
  92. static int stayopen = 0;
  93. static int hosts_multiple_addrs = 0;
  94. static int spoof = 0;
  95. static int spoofalert = 0;
  96. static int reorder = 0;
  97. static char *trimdomain[MAXTRIMDOMAINS];
  98. static char trimdomainbuf[BUFSIZ];
  99. static int numtrimdomains = 0;
  100. #ifdef NIS
  101. static struct hostent *_getnishost();
  102. #endif
  103.  
  104. #ifdef RESOLVSORT
  105. static void addrsort __P((char **, int));
  106. #endif
  107.  
  108. #if PACKETSZ > 1024
  109. #define    MAXPACKET    PACKETSZ
  110. #else
  111. #define    MAXPACKET    1024
  112. #endif
  113.  
  114. typedef union {
  115.     HEADER hdr;
  116.     u_char buf[MAXPACKET];
  117. } querybuf;
  118.  
  119. typedef union {
  120.     long al;
  121.     char ac;
  122. } align;
  123.  
  124. #ifdef SHLIB
  125. extern int h_errno;
  126. #else
  127. extern int h_errno;
  128. #endif
  129. extern int errno;
  130.  
  131. #if NLS
  132. #include "nl_types.h"
  133. #endif
  134.  
  135. static void
  136. dotrimdomain(c)
  137. char *c;
  138. {
  139.     /* assume c points to the start of a host name; trim off any
  140.        domain name matching any of the trimdomains */
  141.     int d,l1,l2;
  142.  
  143.     for(d=0;d<numtrimdomains;d++){
  144.         l1=strlen(trimdomain[d]);
  145.         l2=strlen(c);
  146.         if(l2>l1 && !strcasecmp(c+l2-l1,trimdomain[d]))
  147.             *(c+(strlen(c)-l1))='\0';
  148.     }
  149. }
  150.  
  151. static struct hostent *
  152. trim_domains(h)
  153. struct hostent *h;
  154. {
  155.     if(numtrimdomains){
  156.         int i;
  157.         dotrimdomain(h->h_name);
  158.         for(i=0;h->h_aliases[i];i++)
  159.             dotrimdomain(h->h_aliases[i]);
  160.     }
  161.     return(h);
  162. }
  163.  
  164.  
  165. #if NLS
  166. #define bad_config_format(cmd) \
  167.     fprintf(stderr, catgets(_libc_cat, NetMiscSet, \
  168.         NetMiscResolvIncorrectFormat, \
  169.         "resolv+: %s: \"%s\" command incorrectly formatted.\n"), \
  170.         hostconf, cmd);
  171. #else
  172. #define bad_config_format(cmd) \
  173.     fprintf(stderr, "resolv+: %s: \"%s\" command incorrectly formatted.\n", hostconf, cmd);
  174. #endif
  175.  
  176. /* static void debug_breakout(x)
  177. long x;
  178. {
  179.     register int a, b, c, d;
  180.  
  181.     d = x & 255; x >>= 8;
  182.     c = x & 255; x >>= 8;
  183.     b = x & 255; x >>= 8;
  184.     a = x & 255; x >>= 8;
  185.     fprintf(stderr, "resolv+: %d.%d.%d.%d", a,b,c,d );
  186.  
  187.     return;
  188. } */
  189.  
  190. /* reorder_addrs -- by Tom Limoncelli
  191.     Optimize order of an address list.
  192.  
  193.     gethostbyaddr() usually returns a list of addresses in some
  194.     arbitrary order.  Most programs use the first one and throw the
  195.     rest away.  This routine attempts to find a "best" address and
  196.     swap it into the first position in the list.  "Best" is defined
  197.     as "an address that is on a local subnet".  The search ends after
  198.     one "best" address is found.  If no "best" address is found,
  199.     nothing is changed.
  200.  
  201.     On first execution, a table is built of interfaces, netmasks,
  202.     and mask'ed addresses.  This is to speed up future queries but
  203.     may require you to reboot after changing internet addresses.
  204.     (doesn't everyone reboot after changing internet addresses?)
  205.  
  206.     This routine should not be called if gethostbyaddr() is about
  207.     to return only one address.
  208.  
  209. */
  210.  
  211. /* Hal Stern (June 1992) of Sun claimed that more than 4 ethernets in a
  212. Sun 4/690 would not work.  This variable is set to 10 to accomodate our
  213. version of reality */
  214. #define MAXINTERFACES (10)
  215.  
  216. static void reorder_addrs(h)
  217. struct hostent *h;
  218. {
  219.     static struct {
  220.         char iname[16];
  221.         u_long address, netmask;
  222.         } itab[MAXINTERFACES], *itp;
  223.     static numitab = -1;    /* number of used entries in itab */
  224.     register struct in_addr **r; /* pointer to entry in address list */
  225.     struct in_addr tmp; /* pointer to entry in address list */
  226.     register int cnt;
  227.  
  228.     /***    itab[] contains masked addresses and netmask of each interface.
  229.             numitab is -1 : table is empty.
  230.             numitab is 0  : should never happen.
  231.             numitab is 1,2,3,... :  number of valid entries in the table.
  232.     ***/
  233.     if (!numitab || h==NULL) return;    /* no entries in table */
  234.     if (numitab==-1) { /* build the table */
  235.         int fd, err;
  236.         struct ifconf ifs;
  237.         struct ifreq ifbuf[MAXINTERFACES], *p;
  238.         register struct sockaddr_in *q;
  239.         u_long address, netmask;
  240.         int endp;
  241.  
  242.         /* open a socket */
  243.         fd = socket(PF_INET, SOCK_STREAM, 0);
  244.         if (fd==-1) return;
  245.  
  246.         /**** get information about the first MAXINTERFACES interfaces ****/
  247.         /* set up the ifconf structure */
  248.         ifs.ifc_len = MAXINTERFACES * sizeof(struct ifreq);
  249.         ifs.ifc_buf = (caddr_t) ifbuf;
  250.         /* get a list of interfaces */
  251.         err = ioctl(fd, SIOCGIFCONF, &ifs);
  252.         if (err == -1) return;
  253.  
  254.         /**** cycle through each interface & get netmask & address ****/
  255.         endp = ifs.ifc_len / sizeof(struct ifreq);
  256.         itp = itab;
  257.         for (p = ifs.ifc_req; endp; p++, endp--) {
  258.             strcpy( itp->iname , p->ifr_name); /* copy interface name */
  259.  
  260.             err = ioctl(fd, SIOCGIFNETMASK, p); /* get netmask */
  261.             if (err == -1) continue;    /* error? skip this interface */
  262.             q = (struct sockaddr_in *) &(p->ifr_addr);
  263.             if (q->sin_family == AF_INET) netmask=q->sin_addr.s_addr;
  264.             else continue;    /* not internet protocol? skip this interface */
  265.  
  266.             err = ioctl(fd, SIOCGIFADDR, p); /* get address */
  267.             if (err == -1) continue;    /* error? skip this interface */
  268.             q = (struct sockaddr_in *) &(p->ifr_addr);
  269.             if (q->sin_family == AF_INET) address=q->sin_addr.s_addr;
  270.             else continue;    /* not internet protocol? skip this interface */
  271.  
  272.             /* store the masked address and netmask in the table */
  273.             address = address & netmask;    /* pre-mask the address */
  274.             if (!address) continue;    /* funny address? skip this interface */
  275.             itp->address = address;
  276.             itp->netmask = netmask;
  277.  
  278.             if (numitab == -1) numitab = 0;     /* first time through */
  279.             itp++; numitab++;
  280.         }
  281.         /**** clean up ****/
  282.         close(fd);
  283.         /**** if we still don't have a table, leave */
  284.         if (!numitab) return;
  285.     }
  286.  
  287.     /**** loop through table for each (address,interface) combo ****/
  288.     for ( r = (struct in_addr **) (h->h_addr_list); r && *r; r++) {    /* loop through the addresses */
  289.         for ( itp = itab, cnt=numitab; cnt; itp++,cnt--) {    /* loop though the interfaces */
  290.             if (( (*r)->s_addr & itp->netmask) == itp->address) {    /* compare */
  291.                 /* We found a match.  Swap it into [0] */
  292.                 bcopy( ((struct in_addr **) (h->h_addr_list))[0],    &tmp, sizeof(tmp));
  293.                 bcopy( (*r),    ((struct in_addr **) (h->h_addr_list))[0], sizeof(tmp));
  294.                 bcopy( &tmp,                                      (*r), sizeof(tmp));
  295.  
  296.                 return;    /* found one, don't need to continue */
  297.             }
  298.         } /* interfaces */
  299.     } /* addresses */
  300. }
  301.  
  302. static void
  303. init_services()
  304. {
  305.     char *cp, *dp, buf[BUFSIZ];
  306.     register int cc = 0;
  307.     FILE *fd;
  308.     char *tdp = trimdomainbuf;
  309.     char *hostconf;
  310.  
  311. #if NLS
  312.     libc_nls_init();
  313. #endif
  314.     if(NULL==(hostconf=getenv(ENV_HOSTCONF))){
  315.         hostconf=_PATH_HOSTCONF;
  316.     }
  317.     if ((fd = (FILE *)fopen(hostconf, "r")) == NULL) {
  318.                 /* make some assumptions */
  319.         service_order[0] = SERVICE_BIND;
  320.         service_order[1] = SERVICE_NONE;
  321.     } else {
  322.         while (fgets(buf, BUFSIZ, fd) != NULL) {
  323.             if ((cp = rindex(buf, '\n')) != NULL)
  324.                 *cp = '\0';
  325.             if (buf[0] == '#')
  326.                 continue;
  327.  
  328. #ifdef STRICT
  329. #define checkbuf(b, cmd) (!strncasecmp(b, cmd, strlen(cmd)) && \
  330.               (!b[strlen(cmd)] || isspace(b[strlen(cmd)])))
  331. #else
  332. #define checkbuf(b, cmd) (!strncasecmp(b, cmd, strlen(cmd)))
  333. #endif
  334.  
  335.  
  336.             for (cp=buf; cp && *cp && isspace(*cp); cp++);
  337.             if  (cp && *cp) {
  338.             strcpy(buf,cp);
  339.             if (checkbuf(buf, CMD_ORDER)) {
  340.                 cp = strpbrk(buf, " \t");
  341.                 if (!cp 
  342. #ifdef STRICT
  343.                     || !*(cp+1)
  344. #endif
  345.                     )
  346.                                 {
  347.                                     bad_config_format(CMD_ORDER);
  348.                                 } else
  349.                                 {
  350.                                     do {
  351.                     while (*cp == ' ' || *cp == '\t')
  352.                         cp++;
  353.                     dp = strpbrk(cp, TOKEN_SEPARATORS);
  354.                     if (dp) *dp = '\0';
  355.                     if (checkbuf(cp, ORD_BIND))
  356.                         service_order[cc++] = SERVICE_BIND;
  357.                     else if (checkbuf(cp, ORD_HOSTS))
  358.                         service_order[cc++] = SERVICE_HOSTS;
  359.                     else if (checkbuf(cp, ORD_NIS))
  360.                         service_order[cc++] = SERVICE_NIS;
  361.                     else
  362.                                         {
  363.                                             bad_config_format(CMD_ORDER);
  364. #if NLS
  365.             fprintf(stderr, catgets(_libc_cat, NetMiscSet,
  366.                         NetMiscResolvInvalid,
  367.                         "resolv+: \"%s\" is an invalid keyword\n"), cp);
  368.             fprintf(stderr, catgets(_libc_cat, NetMiscSet,
  369.                         NetMiscResolvValid,
  370.                         "resolv+: valid keywords are: %s, %s and %s\n"),
  371. #else
  372.                                             fprintf(stderr, "resolv+: \"%s\" is an invalid keyword\n", cp);
  373.                                             fprintf(stderr, "resolv+: valid keywords are: %s, %s and %s\n",
  374. #endif
  375.                                                    ORD_BIND, ORD_HOSTS, ORD_NIS);
  376.  
  377.                                         }
  378.  
  379.                     if (dp) cp = ++dp;
  380.                                     } while (dp != NULL);
  381.                                     if (cc == 0)
  382.                                     {
  383.                                         bad_config_format(CMD_ORDER);
  384. #if NLS
  385.                                         fprintf(stderr,catgets(_libc_cat, NetMiscSet,
  386.                                    NetMiscUnrecognized,
  387.                                    "resolv+: search order not specified or unrecognized keyword, host resolution will fail.\n"));
  388. #else
  389.                                         fprintf(stderr,"resolv+: search order not specified or unrecognized keyword, host resolution will fail.\n");
  390. #endif
  391.                                     }
  392.                                 }
  393.  
  394.             } else if (checkbuf(buf, CMD_HMA)) {
  395. #ifdef STRICT
  396.  
  397. #if NLS
  398. #define check_legal(key,val) { \
  399.                 for (cp=strpbrk(buf, " \t"); \
  400.                     cp && *cp && isspace(*cp); cp++); \
  401.                 if (cp && *cp) {\
  402.                 if (strlen(CMD_ON) == strlen(cp) && \
  403.                     checkbuf(cp,CMD_ON)) val = 1; \
  404.                 else if (strlen(CMD_OFF) == strlen(cp) && \
  405.                      checkbuf(cp,CMD_OFF)) val = 0; \
  406.                 else  { bad_config_format(key); \
  407.                     fprintf(stderr, catgets(_libc_cat, NetMiscSet, \
  408.                         NetMiscResolvInvalid, \
  409.                         "resolv+: \"%s\" is an invalid keyword\n"), cp); }\
  410.                 } else bad_config_format(key); }
  411. #else
  412.  
  413. #define check_legal(key,val) { \
  414.                 for (cp=strpbrk(buf, " \t"); \
  415.                     cp && *cp && isspace(*cp); cp++); \
  416.                 if (cp && *cp) {\
  417.                 if (strlen(CMD_ON) == strlen(cp) && \
  418.                     checkbuf(cp,CMD_ON)) val = 1; \
  419.                 else if (strlen(CMD_OFF) == strlen(cp) && \
  420.                      checkbuf(cp,CMD_OFF)) val = 0; \
  421.                 else  { bad_config_format(key); \
  422.                                      fprintf(stderr, "resolv+: \"%s\" is an invalid keyword\n", cp); } \
  423.                 } else bad_config_format(key); }
  424. #endif /* NLS */
  425.                 check_legal(CMD_HMA,hosts_multiple_addrs);
  426.  
  427. #else /* !STRICT */
  428.                             if ( cp = strpbrk(buf, " \t") )
  429.                             {
  430.                 while (*cp == ' ' || *cp == '\t') cp++;
  431.                 if (checkbuf(cp, CMD_ON))
  432.                     hosts_multiple_addrs = 1;
  433.                             } else
  434.                                 bad_config_format(CMD_HMA);
  435. #endif /* STRICT */
  436.  
  437.             } else if (checkbuf(buf, CMD_SPOOF)) {
  438. #ifdef STRICT
  439.                 check_legal(CMD_SPOOF,spoof);
  440. #else
  441.                             if ( cp = strpbrk(buf, " \t") )
  442.                             {
  443.                 while (*cp == ' ' || *cp == '\t') cp++;
  444.                 if (checkbuf(cp, CMD_ON))
  445.                     spoof = 1;
  446.                             } else
  447.                                 bad_config_format(CMD_SPOOF);
  448. #endif
  449.  
  450.  
  451.             } else if (checkbuf(buf, CMD_SPOOFALERT)) {
  452. #ifdef STRICT
  453.                 check_legal(CMD_SPOOFALERT,spoofalert);
  454. #else
  455.                             if ( cp = strpbrk(buf, " \t") )
  456.                             {
  457.                 while (*cp == ' ' || *cp == '\t') cp++;
  458.                 if (checkbuf(cp, CMD_ON))
  459.                     spoofalert = 1;
  460.                             } else
  461.                                 bad_config_format(CMD_SPOOFALERT);
  462. #endif
  463.  
  464.             } else if (checkbuf(buf, CMD_REORDER)) {
  465. #ifdef STRICT
  466.                 check_legal(CMD_REORDER,reorder);
  467. #else
  468.                 if (cp = strpbrk(buf, " \t")) {
  469.                 while (*cp == ' ' || *cp == '\t') cp++;
  470.                 if (checkbuf(cp, CMD_ON))
  471.                     reorder = 1;
  472.                 } else
  473.                     bad_config_format(CMD_REORDER);
  474. #endif
  475.  
  476.             } else if (checkbuf(buf, CMD_TRIMDOMAIN)) {
  477.                 if(numtrimdomains<MAXTRIMDOMAINS){
  478.                                     if ( cp = strpbrk(buf, " \t") )
  479.                                     {
  480.                     while (*cp == ' ' || *cp == '\t') cp++;
  481.                                         if (cp)
  482.                                         {
  483.                                             (void) strcpy(tdp,cp);
  484.                                             trimdomain[numtrimdomains++]=tdp;
  485.                                             tdp += strlen(cp)+1;
  486.                                         } else
  487.                                             bad_config_format(CMD_TRIMDOMAIN);
  488.                                     } else
  489.                                         bad_config_format(CMD_TRIMDOMAIN);
  490.                 }
  491.             }
  492. #ifdef STRICT
  493.                 else {
  494.                     if (cp = strpbrk(buf, " \t")) *cp='\0';
  495. #if NLS
  496.             fprintf(stderr, catgets(_libc_cat, NetMiscSet,
  497.                         NetMiscResolvInvalid,
  498.                         "resolv+: \"%s\" is an invalid keyword\n"), buf);
  499. #else
  500.                     fprintf(stderr, "resolv+: \"%s\" is an invalid keyword\n", buf);
  501. #endif
  502.                 }
  503. #endif
  504.             }
  505.         }
  506.         service_order[cc] = SERVICE_NONE;
  507.         fclose(fd);
  508.     }
  509.     /* override service_order if environment variable */
  510.     if(NULL!=(cp=getenv(ENV_SERVORDER))){
  511.         cc=0;
  512.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  513.             do{
  514.                 if(checkbuf(cp, ORD_BIND))
  515.                     service_order[cc++] = SERVICE_BIND;
  516.                 else if (checkbuf(cp, ORD_HOSTS))
  517.                     service_order[cc++] = SERVICE_HOSTS;
  518.                 else if (checkbuf(cp, ORD_NIS))
  519.                     service_order[cc++] = SERVICE_NIS;
  520.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  521.         service_order[cc] = SERVICE_NONE;
  522.         }
  523.     }
  524.     /* override spoof if environment variable */
  525.     if(NULL!=(cp=getenv(ENV_SPOOF))){
  526.         if(checkbuf(cp, CMD_WARN)){
  527.             spoof=1;
  528.             spoofalert=1;
  529.         } else if (checkbuf(cp, CMD_OFF)){
  530.             spoof=0;
  531.             spoofalert=0;
  532.         } else if (checkbuf(cp, CMD_NOWARN)){
  533.             spoof=1;
  534.             spoofalert=0;
  535.         } else {
  536.             spoof=1;
  537.         }
  538.     }
  539.  
  540.     /* override hma if environment variable */
  541.     if(NULL!=(cp=getenv(ENV_HMA)))
  542.         if(checkbuf(cp, CMD_ON))
  543.             hosts_multiple_addrs=1;
  544.         else
  545.             hosts_multiple_addrs=0;
  546.  
  547.     /* override reorder if environment variable */
  548.     if ((cp = getenv(ENV_REORDER)) != NULL)
  549.         if (checkbuf(cp, CMD_ON))
  550.             reorder = 1;
  551.         else
  552.             reorder = 0;
  553.  
  554.     /* add trimdomains from environment variable */
  555.     if(NULL!=(cp=getenv(ENV_TRIM_ADD))){
  556.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  557.             do{
  558.                 if(numtrimdomains<MAXTRIMDOMAINS){
  559.                     (void)strcpy(tdp, cp);
  560.                     trimdomain[numtrimdomains++]=tdp;
  561.                     tdp += strlen(cp)+1;
  562.                 }
  563.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  564.         }
  565.     }
  566.  
  567.     /* override trimdomains from environment variable */
  568.     if(NULL!=(cp=getenv(ENV_TRIM_OVERR))){
  569.         numtrimdomains=0;
  570.         tdp=trimdomainbuf;
  571.         if(NULL!=(cp=strtok(cp, TOKEN_SEPARATORS))){
  572.             do{
  573.                 if(numtrimdomains<MAXTRIMDOMAINS){
  574.                     (void)strcpy(tdp, cp);
  575.                     trimdomain[numtrimdomains++]=tdp;
  576.                     tdp += strlen(cp)+1;
  577.                 }
  578.             } while(cp=strtok(NULL, TOKEN_SEPARATORS));
  579.         }
  580.     }
  581.  
  582.     service_done = 1;
  583. }
  584.  
  585. static struct hostent *
  586. getanswer(answer, anslen, qname, qclass, qtype)
  587.     const querybuf *answer;
  588.     int anslen;
  589.     const char *qname;
  590.     int qclass, qtype;
  591. {
  592.     register const HEADER *hp;
  593.     register const u_char *cp;
  594.     register int n;
  595.     const u_char *eom;
  596.     char *bp, **ap, **hap;
  597.     int type, class, buflen, ancount, qdcount;
  598.     int haveanswer, had_error;
  599.     int toobig = 0;
  600.     char tbuf[MAXDNAME+1];
  601.  
  602.     host.h_name = NULL;
  603.     eom = answer->buf + anslen;
  604.     /*
  605.      * find first satisfactory answer
  606.      */
  607.     hp = &answer->hdr;
  608.     ancount = ntohs(hp->ancount);
  609.     qdcount = ntohs(hp->qdcount);
  610.     bp = hostbuf;
  611.     buflen = sizeof hostbuf;
  612.     cp = answer->buf + HFIXEDSZ;
  613.     if (qdcount != 1) {
  614.         h_errno = NO_RECOVERY;
  615.         return (NULL);
  616.     }
  617.     if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
  618.         h_errno = NO_RECOVERY;
  619.         return (NULL);
  620.     }
  621. #if NLS
  622.     libc_nls_init();
  623. #endif
  624.     cp += n + QFIXEDSZ;
  625.     if (qtype == T_A) {
  626.         /* res_send() has already verified that the query name is the
  627.          * same as the one we sent; this just gets the expanded name
  628.          * (i.e., with the succeeding search-domain tacked on).
  629.          */
  630.         n = strlen(bp) + 1;        /* for the \0 */
  631.         host.h_name = bp;
  632.         bp += n;
  633.         buflen -= n;
  634.         /* The qname can be abbreviated, but h_name is now absolute. */
  635.         qname = host.h_name;
  636.     }
  637.     ap = host_aliases;
  638.     *ap = NULL;
  639.     host.h_aliases = host_aliases;
  640.     hap = h_addr_ptrs;
  641.     *hap = NULL;
  642. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  643.     host.h_addr_list = h_addr_ptrs;
  644. #endif
  645.     haveanswer = 0;
  646.     had_error = 0;
  647.     while (ancount-- > 0 && cp < eom && !had_error) {
  648.         n = dn_expand(answer->buf, eom, cp, bp, buflen);
  649.         if (n < 0) {
  650.             had_error++;
  651.             continue;
  652.         }
  653.         cp += n;            /* name */
  654.         type = _getshort(cp);
  655.          cp += INT16SZ;            /* type */
  656.         class = _getshort(cp);
  657.          cp += INT16SZ + INT32SZ;    /* class, TTL */
  658.         n = _getshort(cp);
  659.         cp += INT16SZ;            /* len */
  660.         if (class != qclass) {
  661.             /* XXX - debug? syslog? */
  662.             cp += n;
  663.             continue;        /* XXX - had_error++ ? */
  664.         }
  665.         if (qtype == T_A && type == T_CNAME) {
  666.             if (ap >= &host_aliases[MAXALIASES-1])
  667.                 continue;
  668.             n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  669.             if (n < 0) {
  670.                 had_error++;
  671.                 continue;
  672.             }
  673.             cp += n;
  674.             if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
  675.                 syslog(LOG_NOTICE|LOG_AUTH,
  676. #if NLS
  677.         catgets(_libc_cat, NetMiscSet, NetMiscAskedForGotCNAME,
  678.         "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\""),
  679.  
  680. #else
  681.         "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
  682. #endif
  683.                        host.h_name, bp);
  684.                 continue;    /* XXX - had_error++ ? */
  685.             }
  686.             /* Store alias. */
  687.             *ap++ = bp;
  688.             n = strlen(bp) + 1;    /* for the \0 */
  689.             bp += n;
  690.             buflen -= n;
  691.             /* Get canonical name. */
  692.             n = strlen(tbuf) + 1;    /* for the \0 */
  693.             if (n > buflen) {
  694.                 had_error++;
  695.                 continue;
  696.             }
  697.             strcpy(bp, tbuf);
  698.             host.h_name = bp;
  699.             bp += n;
  700.             buflen -= n;
  701.             continue;
  702.         }
  703.         if (type != qtype) {
  704.             syslog(LOG_NOTICE|LOG_AUTH,
  705. #if NLS
  706.         catgets(_libc_cat, NetMiscSet, NetMiscAskedForType,
  707.              "gethostby*.getanswer: asked for type %d(%s), got %d(%s)"),
  708. #else
  709.              "gethostby*.getanswer: asked for type %d(%s), got %d(%s)",
  710. #endif
  711.                    qtype, qname, type, bp);
  712.             cp += n;
  713.             continue;        /* XXX - had_error++ ? */
  714.         }
  715.         switch (type) {
  716.         case T_PTR:
  717.             if (strcasecmp(qname, bp) != 0) {
  718.                 syslog(LOG_NOTICE|LOG_AUTH,
  719. #if NLS
  720.            catgets(_libc_cat, NetMiscSet, NetMiscAskedForGot, AskedForGot),
  721. #else
  722.                        AskedForGot,
  723. #endif
  724.                        qname, bp);
  725.                 cp += n;
  726.                 continue;    /* XXX - had_error++ ? */
  727.             }
  728.             n = dn_expand(answer->buf, eom, cp, bp, buflen);
  729.             if (n < 0) {
  730.                 had_error++;
  731.                 break;
  732.             }
  733. #if MULTI_PTRS_ARE_ALIASES
  734.             cp += n;
  735.             if (!haveanswer)
  736.                 host.h_name = bp;
  737.             else if (ap < &host_aliases[MAXALIASES-1])
  738.                 *ap++ = bp;
  739.             else
  740.                 n = -1;
  741.             if (n != -1) {
  742.                 n = strlen(bp) + 1;    /* for the \0 */
  743.                 bp += n;
  744.                 buflen -= n;
  745.             }
  746.             break;
  747. #else
  748.             host.h_name = bp;
  749.             return (&host);
  750. #endif
  751.         case T_A:
  752.             if (strcasecmp(host.h_name, bp) != 0) {
  753.                 syslog(LOG_NOTICE|LOG_AUTH,
  754. #if NLS
  755.            catgets(_libc_cat, NetMiscSet, NetMiscAskedForGot, AskedForGot),
  756. #else
  757.                        AskedForGot,
  758. #endif
  759.                        host.h_name, bp);
  760.                 cp += n;
  761.                 continue;    /* XXX - had_error++ ? */
  762.             }
  763.             if (haveanswer) {
  764.                 if (n != host.h_length) {
  765.                     cp += n;
  766.                     continue;
  767.                 }
  768.             } else {
  769.                 register int nn;
  770.  
  771.                 host.h_length = n;
  772.                 host.h_addrtype = (class == C_IN)
  773.                           ? AF_INET
  774.                           : AF_UNSPEC;
  775.                 host.h_name = bp;
  776.                 nn = strlen(bp) + 1;    /* for the \0 */
  777.                 bp += nn;
  778.                 buflen -= nn;
  779.             }
  780.  
  781.             bp += sizeof(align) - ((u_long)bp % sizeof(align));
  782.  
  783.             if (bp + n >= &hostbuf[sizeof hostbuf]) {
  784. #ifdef DEBUG
  785.                 if (_res.options & RES_DEBUG)
  786.                     printf("size (%d) too big\n", n);
  787. #endif
  788.                 had_error++;
  789.                 continue;
  790.             }
  791.             if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
  792.                 if (_res.options & RES_DEBUG && !toobig++)
  793.                     printf("Too many addresses (%d)\n",
  794.                            MAXADDRS);
  795.                 cp += n;
  796.                 continue;
  797.             }
  798.             bcopy(cp, *hap++ = bp, n);
  799.             bp += n;
  800.             cp += n;
  801.             break;
  802.         default:
  803.             abort();
  804.         } /*switch*/
  805.         if (!had_error)
  806.             haveanswer++;
  807.     } /*while*/
  808.     if (haveanswer) {
  809.         *ap = NULL;
  810.         *hap = NULL;
  811. # if defined(RESOLVSORT)
  812.         /*
  813.          * Note: we sort even if host can take only one address
  814.          * in its return structures - should give it the "best"
  815.          * address in that case, not some random one
  816.          */
  817.         if (_res.nsort && haveanswer > 1 &&
  818.             qclass == C_IN && qtype == T_A)
  819.             addrsort(h_addr_ptrs, haveanswer);
  820. # endif /*RESOLVSORT*/
  821. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  822.         /* nothing */
  823. #else
  824.         host.h_addr = h_addr_ptrs[0];
  825. #endif /*BSD*/
  826.         if (!host.h_name) {
  827.             n = strlen(qname) + 1;    /* for the \0 */
  828.             strcpy(bp, qname);
  829.             host.h_name = bp;
  830.         }
  831.         return (&host);
  832.     } else {
  833.         h_errno = TRY_AGAIN;
  834.         return (NULL);
  835.     }
  836. }
  837.  
  838. struct hostent *
  839. gethostbyname(const char *name)
  840. {
  841.     querybuf buf;
  842.     register char *cp;
  843.     register int cc;
  844.     int n;
  845.     struct hostent *hp;
  846.     extern struct hostent *_gethtbyname();
  847.  
  848.     /*
  849.      * disallow names consisting only of digits/dots, unless
  850.      * they end in a dot.
  851.      */
  852.     if (isdigit(name[0]))
  853.         for (cp = name;; ++cp) {
  854.             if (!*cp) {
  855.                 if (*--cp == '.')
  856.                     break;
  857.                 /*
  858.                  * All-numeric, no dot at the end.
  859.                  * Fake up a hostent as if we'd actually
  860.                  * done a lookup.  What if someone types
  861.                  * 255.255.255.255?  The test below will
  862.                  * succeed spuriously... ???
  863.                  */
  864.                 if ((host_addr.s_addr = inet_addr(name)) == -1) {
  865.                     h_errno = HOST_NOT_FOUND;
  866.                     return((struct hostent *) NULL);
  867.                 }
  868.                 host.h_name = name;
  869.                 host.h_aliases = host_aliases;
  870.                 host_aliases[0] = NULL;
  871.                 host.h_addrtype = AF_INET;
  872.                 host.h_length = sizeof(u_long);
  873.                 h_addr_ptrs[0] = (char *)&host_addr;
  874.                 h_addr_ptrs[1] = (char *)0;
  875. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  876.                 host.h_addr_list = h_addr_ptrs;
  877. #else
  878.                 host.h_addr = h_addr_ptrs[0];
  879. #endif
  880.                 h_errno = NETDB_SUCCESS;
  881.                 return (&host);
  882.             }
  883.             if (!isdigit(*cp) && *cp != '.')
  884.                 break;
  885.         }
  886.  
  887.     if (!service_done)
  888.         init_services();
  889.  
  890.     for (cc = 0; service_order[cc] != SERVICE_NONE &&
  891.          cc <= SERVICE_MAX; cc++) {
  892.         switch (service_order[cc]) {
  893.         case SERVICE_BIND:
  894.             if ((n = res_search(name, C_IN, T_A,
  895.                         buf.buf, sizeof(buf))) < 0) {
  896. #ifdef DEBUG
  897.                 if (_res.options & RES_DEBUG)
  898.                     printf("res_search failed\n");
  899. #endif
  900.             }
  901.             hp = getanswer(&buf, n, name, C_IN, T_A);
  902.             if (h_addr_ptrs[1] && reorder)
  903.                 reorder_addrs(hp);
  904.             if (hp)
  905.                 return trim_domains(hp);
  906.             break;
  907.         case SERVICE_HOSTS:
  908.             hp = _gethtbyname(name);
  909.             if (h_addr_ptrs[1] && reorder)
  910.                 reorder_addrs(hp);
  911.             if (hp)
  912.                 return hp;
  913.             h_errno = HOST_NOT_FOUND;
  914.             break;
  915. #ifdef NIS
  916.         case SERVICE_NIS:
  917.             hp = _getnishost(name, "hosts.byname");
  918.             if (h_addr_ptrs[1] && reorder)
  919.                 reorder_addrs(hp);
  920.             if (hp)
  921.                 return hp;
  922.             h_errno = HOST_NOT_FOUND;
  923.             break;
  924. #endif /* NIS */
  925.         }
  926.     }
  927.     return ((struct hostent *) NULL);
  928. }
  929.  
  930. struct hostent *
  931. gethostbyaddr(const char *addr, int len, int type)
  932. {
  933.     int n;
  934.     querybuf buf;
  935.     register int cc;
  936.     register struct hostent *hp;
  937.     char qbuf[MAXDNAME];
  938.     extern struct hostent *_gethtbyaddr();
  939.  
  940.     if (type != AF_INET) {
  941.         h_errno = NETDB_INTERNAL;
  942.         return ((struct hostent *) NULL);
  943.     }
  944.  
  945.     if (!service_done)
  946.       init_services();
  947.  
  948. #if NLS
  949.     libc_nls_init();
  950. #endif
  951.     cc = 0;
  952.     while (service_order[cc] != SERVICE_NONE) {
  953.             switch (service_order[cc]) {
  954.         case SERVICE_BIND:
  955.             (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  956.                       ((unsigned)addr[3] & 0xff),
  957.                       ((unsigned)addr[2] & 0xff),
  958.                       ((unsigned)addr[1] & 0xff),
  959.                       ((unsigned)addr[0] & 0xff));
  960.             n = res_query(qbuf, C_IN, T_PTR, (char *)&buf,
  961.                       sizeof(buf));
  962.             if (n < 0) {
  963. #ifdef DEBUG
  964.                 if (_res.options & RES_DEBUG)
  965.                     printf("res_query failed\n");
  966. #endif
  967.                 break;
  968.             }
  969.             hp = getanswer(&buf, n, qbuf, C_IN, T_PTR);
  970.             if (hp) {
  971.                 if(spoof){
  972.                     /* Spoofing check code by
  973.                      * Caspar Dik <casper@fwi.uva.nl>
  974.                      */
  975.                     char nambuf[MAXDNAME+1];
  976.                     int ntd, namelen = strlen(hp->h_name);
  977.                     char **addrs;
  978.  
  979.                     if (namelen >= MAXDNAME)
  980.                         return (struct hostent *)NULL;
  981.                     (void) strcpy(nambuf,hp->h_name);
  982.                     nambuf[namelen] = '.';
  983.                     nambuf[namelen+1] = '\0';
  984.  
  985.                     /*
  986.                      * turn off domain trimming,
  987.                      * call gethostbyname(), then turn
  988.                      * it back on, if applicable. This
  989.                      * prevents domain trimming from
  990.                      * making the name comparison fail.
  991.                      */
  992.                     ntd=numtrimdomains;
  993.                     numtrimdomains=0;
  994.                     hp=gethostbyname(nambuf);
  995.                     numtrimdomains=ntd;
  996.                     nambuf[namelen] = 0;
  997.                     /*
  998.                     * the name must exist and the name
  999.                     * returned by gethostbyaddr must be
  1000.                     * the canonical name and therefore
  1001.                     * identical to the name returned by
  1002.                     * gethostbyname()
  1003.                     */
  1004.                     if (!hp || strcmp(nambuf, hp->h_name)){
  1005.                         h_errno = HOST_NOT_FOUND;
  1006.                         return (struct hostent *)NULL;
  1007.                     }
  1008.                     /*
  1009.                     * now check the addresses
  1010.                     */
  1011. #if defined(h_addr) || BSD >= 43
  1012.                     for (addrs = hp->h_addr_list;
  1013.                         *addrs; addrs++){
  1014.                         if (!bcmp(addrs[0], addr, len))
  1015.                             return trim_domains(hp);
  1016.                     }
  1017. #else
  1018.                     if (!bcmp(hp->h_addr, addr, len)))
  1019.                         return trim_domains(hp);
  1020. #endif
  1021.                     /* We've been spoofed */
  1022.                     h_errno = HOST_NOT_FOUND;
  1023.                     if(spoofalert){
  1024.                         openlog("resolv", LOG_PID,
  1025.                             LOG_AUTH);
  1026.                         syslog(LOG_NOTICE,
  1027. #if NLS
  1028.                             catgets(_libc_cat, NetMiscSet,
  1029.                                 NetMiscPossibleSpoof,
  1030.                                 "gethostbyaddr: %s != %u.%u.%u.%u, possible spoof attempt"),
  1031. #else
  1032.                             "gethostbyaddr: %s != %u.%u.%u.%u, possible spoof attempt",
  1033. #endif
  1034.                             hp->h_name,
  1035.                             ((unsigned)addr[0]&0xff),
  1036.                             ((unsigned)addr[1]&0xff),
  1037.                             ((unsigned)addr[2]&0xff),
  1038.                             ((unsigned)addr[3]&0xff));
  1039.                     }
  1040.                     return (struct hostent *)NULL;
  1041.                 }
  1042.                 hp->h_addrtype = type;
  1043.                 hp->h_length = len;
  1044.                 h_addr_ptrs[0] = (char *)&host_addr;
  1045.                 h_addr_ptrs[1] = (char *)0;
  1046.                 host_addr = *(struct in_addr *)addr;
  1047. #if BSD < 43 && !defined(h_addr)    /* new-style hostent structure */
  1048.                 hp->h_addr = h_addr_ptrs[0];
  1049. #endif
  1050.                 return trim_domains(hp);
  1051.             }
  1052.             h_errno = HOST_NOT_FOUND;
  1053.             break;
  1054.         case SERVICE_HOSTS:
  1055.             hp = _gethtbyaddr(addr, len, type);
  1056.             if (hp)
  1057.                 return hp;
  1058.             h_errno = HOST_NOT_FOUND;
  1059.             break;
  1060. #ifdef NIS
  1061.         case SERVICE_NIS:
  1062.             (void)sprintf(qbuf, "%u.%u.%u.%u",
  1063.                       ((unsigned)addr[0] & 0xff),
  1064.                       ((unsigned)addr[1] & 0xff),
  1065.                       ((unsigned)addr[2] & 0xff),
  1066.                       ((unsigned)addr[3] & 0xff));
  1067.             hp = _getnishost(qbuf, "hosts.byaddr");
  1068.             if (hp)
  1069.                 return hp;
  1070.             h_errno = HOST_NOT_FOUND;
  1071.             break;
  1072. #endif /* NIS */
  1073.         }
  1074.         cc++;
  1075.     }
  1076.     return ((struct hostent *)NULL);
  1077. }
  1078.  
  1079. void
  1080. _sethtent(f)
  1081.     int f;
  1082. {
  1083.     if (hostf == NULL)
  1084.         hostf = fopen(HOSTDB, "r" );
  1085.     else
  1086.         rewind(hostf);
  1087.     stayopen |= f;
  1088. }
  1089.  
  1090. void
  1091. _endhtent()
  1092. {
  1093.     if (hostf && !stayopen) {
  1094.         (void) fclose(hostf);
  1095.         hostf = NULL;
  1096.     }
  1097. }
  1098.  
  1099. struct hostent *
  1100. _gethtent()
  1101. {
  1102.     char *p;
  1103.     register char *cp, **q;
  1104.  
  1105.     if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) {
  1106.          h_errno = NETDB_INTERNAL;
  1107.         return (NULL);
  1108.     }
  1109. again:
  1110.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) {
  1111.         h_errno = HOST_NOT_FOUND;
  1112.         return (NULL);
  1113.     }
  1114.     if (*p == '#')
  1115.         goto again;
  1116.     cp = strpbrk(p, "#\n");
  1117.     if (cp == NULL)
  1118.         goto again;
  1119.     *cp = '\0';
  1120.     cp = strpbrk(p, " \t");
  1121.     if (cp == NULL)
  1122.         goto again;
  1123.     *cp++ = '\0';
  1124.     /* THIS STUFF IS INTERNET SPECIFIC */
  1125. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  1126.     host.h_addr_list = host_addrs;
  1127. #endif
  1128.     host.h_addr = hostaddr;
  1129.     *((u_long *)host.h_addr) = inet_addr(p);
  1130.     host.h_length = sizeof (u_long);
  1131.     host.h_addrtype = AF_INET;
  1132.     while (*cp == ' ' || *cp == '\t')
  1133.         cp++;
  1134.     host.h_name = cp;
  1135.     q = host.h_aliases = host_aliases;
  1136.     cp = strpbrk(cp, " \t");
  1137.     if (cp != NULL)
  1138.         *cp++ = '\0';
  1139.     while (cp && *cp) {
  1140.         if (*cp == ' ' || *cp == '\t') {
  1141.             cp++;
  1142.             continue;
  1143.         }
  1144.         if (q < &host_aliases[MAXALIASES - 1])
  1145.             *q++ = cp;
  1146.         cp = strpbrk(cp, " \t");
  1147.         if (cp != NULL)
  1148.             *cp++ = '\0';
  1149.     }
  1150.     *q = NULL;
  1151.     h_errno = NETDB_SUCCESS;
  1152.     return (&host);
  1153. }
  1154.  
  1155. /* if hosts_multiple_addrs set, then gethtbyname behaves as follows:
  1156.  *  - for hosts with multiple addresses, return all addresses, such that
  1157.  *  the first address is most likely to be one on the same net as the
  1158.  *  host we're running on, if one exists.
  1159.  *  - like the dns version of gethostsbyname, the alias field is empty
  1160.  *  unless the name being looked up is an alias itself, at which point the
  1161.  *  alias field contains that name, and the name field contains the primary
  1162.  *  name of the host. Unlike dns, however, this behavior will still take place
  1163.  *  even if the alias applies only to one of the interfaces.
  1164.  *  - determining a "local" address to put first is dependant on the netmask
  1165.  *  being such that the least significant network bit is more significant
  1166.  *  than any host bit. Only strange netmasks will violate this.
  1167.  *  - we assume addresses fit into u_longs. That's quite internet specific.
  1168.  *  - if the host we're running on is not in the host file, the address
  1169.  *  shuffling will not take place.
  1170.  *                     - John DiMarco <jdd@cdf.toronto.edu>
  1171.  */
  1172. struct hostent *
  1173. _gethtbyname(const char *name)
  1174. {
  1175.     register struct hostent *p;
  1176.     register char **cp;
  1177.     char **hap, **lhap, *bp, *lbp;
  1178.     int htbuflen, locbuflen;
  1179.     int found=0, localfound=0;
  1180.     char localname[MAXHOSTNAMELEN];
  1181.  
  1182.     static char htbuf[BUFSIZ+1]; /* buffer for host addresses */
  1183.     static char locbuf[BUFSIZ+1]; /* buffer for local hosts's addresses */
  1184.     static char *ht_addr_ptrs[MAXADDRS+1];
  1185.     static char *loc_addr_ptrs[MAXADDRS+1];
  1186.     static struct hostent ht;
  1187.     static char *aliases[MAXALIASES];
  1188.     static char namebuf[MAXHOSTNAMELEN];
  1189.  
  1190.     hap = ht_addr_ptrs;
  1191.     lhap = loc_addr_ptrs;
  1192.     *hap = NULL;
  1193.     *lhap = NULL;
  1194.     bp=htbuf;
  1195.     lbp=locbuf;
  1196.     htbuflen = sizeof(htbuf);
  1197.     locbuflen = sizeof(locbuf);
  1198.  
  1199.     aliases[0]=NULL;
  1200.     aliases[1]=NULL;
  1201.     (void) strcpy(namebuf, name);
  1202.  
  1203.     (void)gethostname(localname, sizeof(localname));
  1204.  
  1205.     _sethtent(0);
  1206.     while (p = _gethtent()) {
  1207.         if (strcasecmp(p->h_name, name) == 0)
  1208.             found++;
  1209.         else
  1210.             for (cp = p->h_aliases; *cp != 0; cp++)
  1211.                 if (strcasecmp(*cp, name) == 0){
  1212.                     found++;
  1213.                     aliases[0]=name;
  1214.                     (void) strcpy(namebuf, p->h_name);
  1215.                 }
  1216.         if (strcasecmp(p->h_name, localname) == 0)
  1217.             localfound++;
  1218.         else
  1219.             for (cp=p->h_aliases; *cp != 0; cp++)
  1220.                 if (strcasecmp(*cp, localname) == 0)
  1221.                     localfound++;
  1222.  
  1223.         if(found){
  1224.             int n;
  1225.  
  1226.             if(!hosts_multiple_addrs){
  1227.                 /* original behaviour requested */
  1228.                 _endhtent();
  1229.                 return(p);
  1230.             }
  1231.             n = p->h_length;
  1232.  
  1233.             ht.h_addrtype = p->h_addrtype;
  1234.             ht.h_length = p->h_length;
  1235.  
  1236.             if(n<=htbuflen){
  1237.                 /* add the found address to the list */
  1238.                 bcopy(p->h_addr_list[0], bp, n);
  1239.                 *hap++=bp;
  1240.                 *hap=NULL;
  1241.                 bp+=n;
  1242.                 htbuflen-=n;
  1243.             }
  1244.             found=0;
  1245.         }
  1246.         if(localfound){
  1247.             int n = p->h_length;
  1248.             if(n<=locbuflen){
  1249.                 /* add the found local address to the list */
  1250.                 bcopy(p->h_addr_list[0], lbp, n);
  1251.                 *lhap++=lbp;
  1252.                 *lhap=NULL;
  1253.                 lbp+=n;
  1254.                 locbuflen-=n;
  1255.             }
  1256.             localfound=0;
  1257.         }
  1258.     }
  1259.     _endhtent();
  1260.  
  1261.     if(NULL==ht_addr_ptrs[0]){
  1262.         return((struct hostent *)NULL);
  1263.     }
  1264.  
  1265.     ht.h_aliases = aliases;
  1266.     ht.h_name = namebuf;
  1267.  
  1268.     /* shuffle addresses around to ensure one on same net as local host
  1269.        is first, if exists */
  1270.     {
  1271.         /* "best" address is assumed to be the one with the greatest
  1272.            number of leftmost bits matching any of the addresses of
  1273.            the local host. This assumes a netmask in which all net
  1274.            bits precede host bits. Usually but not always a fair
  1275.            assumption. */
  1276.  
  1277.         /* portability alert: assumption: iaddr fits in u_long.
  1278.            This is really internet specific. */
  1279.         int i,j, best=0;
  1280.         u_long bestval = (u_long)~0;
  1281.  
  1282.         for(i=0;loc_addr_ptrs[i];i++){
  1283.             for(j=0;ht_addr_ptrs[j];j++){
  1284.                 u_long t, l, h;
  1285.                 /* assert(sizeof(u_long)>=ht.h_length); */
  1286.                 bcopy(loc_addr_ptrs[i], (char *)&t,
  1287.                     ht.h_length);
  1288.                 l=ntohl(t);
  1289.                 bcopy(ht_addr_ptrs[j], (char *)&h,
  1290.                     ht.h_length);
  1291.                 t=l^h;
  1292.  
  1293.                 if(t<bestval){
  1294.                     best=j;
  1295.                     bestval=t;
  1296.                 }
  1297.             }
  1298.         }
  1299.         if(best){
  1300.             char *tmp;
  1301.  
  1302.             /* swap first and best address */
  1303.             tmp=ht_addr_ptrs[0];
  1304.             ht_addr_ptrs[0]=ht_addr_ptrs[best];
  1305.             ht_addr_ptrs[best]=tmp;
  1306.         }
  1307.     }
  1308.  
  1309.     ht.h_addr_list = ht_addr_ptrs;
  1310.     return (&ht);
  1311. }
  1312.  
  1313. #ifdef NIS
  1314. static struct hostent *
  1315. _getnishost(name, map)
  1316.     char *name, *map;
  1317. {
  1318.     register char *cp, *dp, **q;
  1319.     char *result;
  1320.     int resultlen;
  1321.     static struct hostent h;
  1322.     static char *domain = (char *)NULL;
  1323.  
  1324.     if (domain == (char *)NULL)
  1325.         if (yp_get_default_domain (&domain))
  1326.             return ((struct hostent *)NULL);
  1327.  
  1328.     if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
  1329.         return ((struct hostent *)NULL);
  1330.  
  1331.     if (cp = index(result, '\n'))
  1332.         *cp = '\0';
  1333.  
  1334.     cp = strpbrk(result, " \t");
  1335.     *cp++ = '\0';
  1336. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  1337.     h.h_addr_list = host_addrs;
  1338. #endif
  1339.     h.h_addr = hostaddr;
  1340.     *((u_long *)h.h_addr) = inet_addr(result);
  1341.     h.h_length = sizeof(u_long);
  1342.     h.h_addrtype = AF_INET;
  1343.     while (*cp == ' ' || *cp == '\t')
  1344.         cp++;
  1345.     h.h_name = cp;
  1346.     q = h.h_aliases = host_aliases;
  1347.     cp = strpbrk(cp, " \t");
  1348.     if (cp != NULL)
  1349.         *cp++ = '\0';
  1350.     while (cp && *cp) {
  1351.         if (*cp == ' ' || *cp == '\t') {
  1352.             cp++;
  1353.             continue;
  1354.         }
  1355.         if (q < &host_aliases[MAXALIASES - 1])
  1356.             *q++ = cp;
  1357.         cp = strpbrk(cp, " \t");
  1358.         if (cp != NULL)
  1359.             *cp++ = '\0';
  1360.     }
  1361.     *q = NULL;
  1362.     return (&h);
  1363. }
  1364. #endif /* NIS */
  1365.  
  1366. struct hostent *
  1367. _gethtbyaddr(const char *addr, int len, int type)
  1368. {
  1369.     register struct hostent *p;
  1370.  
  1371.     _sethtent(0);
  1372.     while (p = _gethtent())
  1373.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  1374.             break;
  1375.     _endhtent();
  1376.     return (p);
  1377. }
  1378.  
  1379. #ifdef RESOLVSORT
  1380. static void
  1381. addrsort(ap, num)
  1382.     char **ap;
  1383.     int num;
  1384. {
  1385.     int i, j;
  1386.     char **p;
  1387.     short aval[MAXADDRS];
  1388.     int needsort = 0;
  1389.  
  1390.     p = ap;
  1391.     for (i = 0; i < num; i++, p++) {
  1392.         for (j = 0 ; j < _res.nsort; j++)
  1393.         if (_res.sort_list[j].addr.s_addr == 
  1394.             (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
  1395.             break;
  1396.         aval[i] = j;
  1397.         if (needsort == 0 && i > 0 && j < aval[i-1])
  1398.         needsort = i;
  1399.     }
  1400.     if (!needsort)
  1401.         return;
  1402.  
  1403.     while (needsort < num) {
  1404.         for (j = needsort - 1; j >= 0; j--) {
  1405.         if (aval[j] > aval[j+1]) {
  1406.             char *hp;
  1407.  
  1408.             i = aval[j];
  1409.             aval[j] = aval[j+1];
  1410.             aval[j+1] = i;
  1411.  
  1412.             hp = ap[j];
  1413.             ap[j] = ap[j+1];
  1414.             ap[j+1] = hp;
  1415.  
  1416.         } else
  1417.             break;
  1418.         }
  1419.         needsort++;
  1420.     }
  1421. }
  1422. #endif
  1423.