home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / libncftp / older_versions / libncftp-3.1.5-src.tar.gz / libncftp-3.1.5-src.tar / libncftp-3.1.5 / sio / DNSUtil.c < prev    next >
C/C++ Source or Header  |  2002-10-13  |  14KB  |  567 lines

  1. #include "syshdrs.h"
  2. #ifdef PRAGMA_HDRSTOP
  3. #    pragma hdrstop
  4. #endif
  5.  
  6. #ifndef STRNCPY
  7. #    define STRNCPY(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a) - 1] = '\0'
  8. #    define Strncpy(a,b,s) strncpy(a, b, s); a[s - 1] = '\0' 
  9. #    define Strncat(a,b,s)\
  10.     { \
  11.         size_t alen = strlen(a); \
  12.         if (alen < s) { \
  13.             strncpy(a + alen, b, s - alen); \
  14.         } \
  15.         a[s - 1] = '\0'  \
  16.     }
  17. #endif
  18.  
  19. #if ((defined(MACOSX)) || (defined(AIX) && (AIX < 430)) || (defined(DIGITAL_UNIX)) || (defined(SOLARIS)) || (defined(SCO)) || (defined(HPUX)))
  20. extern int getdomainname(char *name, gethostname_size_t namelen);
  21. #endif
  22.  
  23.  
  24. int
  25. GetHostByName(struct hostent *const hp, const char *const name, char *const hpbuf, size_t hpbufsize)
  26. {
  27. #if defined(HAVE_GETHOSTBYNAME_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
  28.     struct hostent *h;
  29.     int h_errno_unused = 0;
  30.     memset(hpbuf, 0, hpbufsize);
  31.     h = gethostbyname_r(name, hp, hpbuf, hpbufsize, &h_errno_unused);
  32.     if (h != NULL)
  33.         return (0);
  34. #elif defined(HAVE_GETHOSTBYNAME2_R) && defined(LINUX)
  35.     char *usehpbuf;
  36.     struct hostent *h;
  37.     int my_h_errno, rc;
  38.  
  39.     usehpbuf = hpbuf;
  40.     forever {
  41.         errno = 0;
  42.         my_h_errno = 0;
  43.         h = NULL;
  44.         memset(usehpbuf, 0, hpbufsize);
  45.         rc = gethostbyname2_r(name, AF_INET, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
  46.         if ((rc == 0) && (h != NULL))
  47.             return (0);
  48.         if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
  49.             hpbufsize *= 2;
  50.             usehpbuf = alloca(hpbufsize);
  51.             if (usehpbuf == NULL) {
  52.                 errno = ENOMEM;
  53.                 return (-1);
  54.             }
  55.         }
  56.         if ((rc == 0) && (my_h_errno != 0))
  57.             errno = ENOENT;
  58.         break;
  59.     }
  60. #elif defined(HAVE_GETHOSTBYNAME_R) && defined(LINUX)
  61.     char *usehpbuf;
  62.     struct hostent *h;
  63.     int my_h_errno, rc;
  64.  
  65.     usehpbuf = hpbuf;
  66.     forever {
  67.         errno = 0;
  68.         my_h_errno = 0;
  69.         h = NULL;
  70.         memset(usehpbuf, 0, hpbufsize);
  71.         rc = gethostbyname_r(name, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
  72.         if ((rc == 0) && (my_h_errno == 0))
  73.             return (0);
  74.         if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
  75.             hpbufsize *= 2;
  76.             usehpbuf = alloca(hpbufsize);
  77.             if (usehpbuf == NULL) {
  78.                 errno = ENOMEM;
  79.                 return (-1);
  80.             }
  81.         }
  82.         if ((rc == 0) && (my_h_errno != 0))
  83.             errno = ENOENT;
  84.         break;
  85.     }
  86. #elif defined(HAVE_GETHOSTBYNAME_R) && defined(AIX)
  87.     struct hostent_data hed;
  88.     memset(hpbuf, 0, hpbufsize);
  89.     memset(&hed, 0, sizeof(hed));
  90.     if (gethostbyname_r(name, hp, &hed) == 0)
  91.         return (0);
  92. #else
  93.     /* Note: gethostbyname is already threadsafe on: HP-UX, Tru64 */
  94.     struct hostent *h;
  95.     h = gethostbyname(name);
  96.     if (h != NULL) {
  97.         memcpy(hp, h, sizeof(struct hostent));
  98.         return (0);
  99.     } else {
  100.         memset(hp, 0, sizeof(struct hostent));
  101.         memset(hpbuf, 0, hpbufsize);
  102.     }
  103. #endif
  104.     return (-1);
  105. }    /* GetHostByName */
  106.  
  107.  
  108.  
  109.  
  110. int
  111. GetHostByAddr(struct hostent *const hp, void *addr, int asize, int atype, char *const hpbuf, size_t hpbufsize)
  112. {
  113. #if defined(HAVE_GETHOSTBYADDR_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
  114.     struct hostent *h;
  115.     int h_errno_unused = 0;
  116.     memset(hpbuf, 0, hpbufsize);
  117.     h = gethostbyaddr_r((gethost_addrptr_t) addr, asize, atype, hp, hpbuf, hpbufsize, &h_errno_unused);
  118.     if (h != NULL)
  119.         return (0);
  120. #elif defined(HAVE_GETHOSTBYADDR_R) && defined(LINUX)
  121.     char *usehpbuf;
  122.     struct hostent *h;
  123.     int my_h_errno, rc;
  124.  
  125.     usehpbuf = hpbuf;
  126.     forever {
  127.         errno = 0;
  128.         my_h_errno = 0;
  129.         h = NULL;
  130.         memset(usehpbuf, 0, hpbufsize);
  131.         rc = gethostbyaddr_r((gethost_addrptr_t) addr, asize, atype, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
  132.         if ((rc == 0) && (h != NULL))
  133.             return (0);
  134.         if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
  135.             hpbufsize *= 2;
  136.             usehpbuf = alloca(hpbufsize);
  137.             if (usehpbuf == NULL) {
  138.                 errno = ENOMEM;
  139.                 return (-1);
  140.             }
  141.         }
  142.         if ((rc == 0) && (my_h_errno != 0))
  143.             errno = ENOENT;
  144.         break;
  145.     }
  146. #elif defined(HAVE_GETHOSTBYADDR_R) && defined(AIX)
  147.     struct hostent_data hed;
  148.     memset(hpbuf, 0, hpbufsize);
  149.     memset(&hed, 0, sizeof(hed));
  150.     if (gethostbyaddr_r(addr, asize, atype, hp, &hed) == 0)
  151.         return (0);
  152. #else
  153.     /* Note: gethostbyaddr is already threadsafe on: HP-UX, Tru64 */
  154.     struct hostent *h;
  155.     h = gethostbyaddr((gethost_addrptr_t) addr, asize, atype);
  156.     if (h != NULL) {
  157.         memcpy(hp, h, sizeof(struct hostent));
  158.         return (0);
  159.     } else {
  160.         memset(hp, 0, sizeof(struct hostent));
  161.         memset(hpbuf, 0, hpbufsize);
  162.     }
  163. #endif
  164.     return (-1);
  165. }    /* GetHostByAddr */
  166.  
  167.  
  168.  
  169.  
  170. /* On entry, you should have 'host' be set to a symbolic name (like
  171.  * cse.unl.edu), or set to a numeric address (like 129.93.3.1).
  172.  * If the function fails, it will return NULL, but if the host was
  173.  * a numeric style address, you'll have the ip_address to fall back on.
  174.  */
  175.  
  176. int
  177. GetHostEntry(struct hostent *const hp, const char *const host, struct in_addr *const ip_address, char *const hpbuf, size_t hpbufsize)
  178. {
  179.     struct in_addr ip;
  180.     int rc = -1;
  181.     
  182.     /* See if the host was given in the dotted IP format, like "36.44.0.2."
  183.      * If it was, inet_addr will convert that to a 32-bit binary value;
  184.      * if not, inet_addr will return (-1L).
  185.      */
  186.     ip.s_addr = inet_addr(host);
  187.     if (ip.s_addr != INADDR_NONE) {
  188.         if (GetHostByAddr(hp, (char *) &ip, (int) sizeof(ip), AF_INET, hpbuf, hpbufsize) == 0) {
  189.             rc = 0;
  190.             if (ip_address != NULL)
  191.                 (void) memcpy(&ip_address->s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
  192.         } else if (ip_address != NULL) {
  193.             (void) memcpy(ip_address, &ip, sizeof(struct in_addr));
  194.         }
  195.     } else {
  196.         /* No IP address, so it must be a hostname, like ftp.wustl.edu. */
  197.         if (ip_address != NULL)
  198.             ip_address->s_addr = INADDR_NONE;
  199.         if (GetHostByName(hp, host, hpbuf, hpbufsize) == 0) {
  200.             rc = 0;
  201.             if (ip_address != NULL)
  202.                 (void) memcpy(&ip_address->s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
  203.         }
  204.     }
  205.     return (rc);
  206. }    /* GetHostEntry */
  207.  
  208.  
  209.  
  210.  
  211. static char *
  212. strtokc(char *parsestr, const char *delims, char **context)
  213. {
  214.     char *cp;
  215.     const char *cp2;
  216.     char c, c2;
  217.     char *start;
  218.  
  219.     if (parsestr == NULL)
  220.         start = *context;
  221.     else
  222.         start = parsestr;
  223.  
  224.     if ((start == NULL) || (delims == NULL)) {
  225.         *context = NULL;
  226.         return NULL;
  227.     }
  228.  
  229.     /* Eat leading delimiters. */
  230.     for (cp = start; ; ) {
  231. next1:
  232.         c = *cp++;
  233.         if (c == '\0') {
  234.             /* No more tokens. */
  235.             *context = NULL;
  236.             return (NULL);
  237.         }
  238.         for (cp2 = delims; ; ) {
  239.             c2 = (char) *cp2++;
  240.             if (c2 == '\0') {
  241.                 /* This character was not a delimiter.
  242.                  * The token starts here.
  243.                  */
  244.                 start = cp - 1;
  245.                 goto starttok;
  246.             }
  247.             if (c2 == c) {
  248.                 /* This char was a delimiter. */
  249.                 /* Skip it, look at next character. */
  250.                 goto next1;
  251.             }
  252.         }
  253.         /*NOTREACHED*/
  254.     }
  255.  
  256. starttok:
  257.     for ( ; ; cp++) {
  258.         c = *cp;
  259.         if (c == '\0') {
  260.             /* Token is finished. */
  261.             *context = cp;
  262.             break;
  263.         }
  264.         for (cp2 = delims; ; ) {
  265.             c2 = (char) *cp2++;
  266.             if (c2 == '\0') {
  267.                 /* This character was not a delimiter.
  268.                  * Keep it as part of current token.
  269.                  */
  270.                 break;
  271.             }
  272.             if (c2 == c) {
  273.                 /* This char was a delimiter. */
  274.                 /* End of token. */
  275.                 *cp++ = '\0';
  276.                 *context = cp;
  277.                 return (start);
  278.             }
  279.         }
  280.     }
  281.     return (start);
  282. }    /* strtokc */
  283.  
  284.  
  285.  
  286. #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
  287. int
  288. getdomainname(char *const domain, unsigned int dsize)
  289. {
  290.     HKEY hkey;
  291.     DWORD rc;
  292.     DWORD valSize;
  293.  
  294.     /* Works for Win NT/2000/XP */
  295.     rc = RegOpenKeyEx(
  296.             HKEY_LOCAL_MACHINE,
  297.             "System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
  298.             0,
  299.             KEY_READ,
  300.             &hkey
  301.     );
  302.  
  303.     if (rc == ERROR_SUCCESS) {
  304.         valSize = (DWORD) (dsize - 1);
  305.         memset(domain, 0, dsize);
  306.         rc = RegQueryValueEx(
  307.             hkey,
  308.             "DhcpDomain",
  309.             NULL,
  310.             NULL,
  311.             (LPBYTE) domain,
  312.             &valSize
  313.         );
  314.  
  315.         if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
  316.             RegCloseKey(hkey);
  317.             return (0);
  318.         }
  319.  
  320.         valSize = (DWORD) (dsize - 1);
  321.         memset(domain, 0, dsize);
  322.         rc = RegQueryValueEx(
  323.             hkey,
  324.             "Domain",
  325.             NULL,
  326.             NULL,
  327.             (LPBYTE) domain,
  328.             &valSize
  329.         );
  330.  
  331.         if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
  332.             RegCloseKey(hkey);
  333.             return (0);
  334.         }
  335.  
  336.         RegCloseKey(hkey);
  337.     }
  338.  
  339.     /* Works for Win 9x */
  340.     rc = RegOpenKeyEx(
  341.             HKEY_LOCAL_MACHINE,
  342.             "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
  343.             0,
  344.             KEY_READ,
  345.             &hkey
  346.     );
  347.  
  348.     if (rc == ERROR_SUCCESS) {
  349.         valSize = (DWORD) (dsize - 1);
  350.         memset(domain, 0, dsize);
  351.         rc = RegQueryValueEx(
  352.             hkey,
  353.             "Domain",
  354.             NULL,
  355.             NULL,
  356.             (LPBYTE) domain,
  357.             &valSize
  358.         );
  359.  
  360.         if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
  361.             RegCloseKey(hkey);
  362.             return (0);
  363.         }
  364.  
  365.         RegCloseKey(hkey);
  366.     }
  367.  
  368.     memset(domain, 0, dsize);
  369.     return (-1);
  370. }    /* getdomainname */
  371. #endif    /* WINDOWS */
  372.  
  373.  
  374.  
  375. /* Makes every effort to return a fully qualified domain name. */
  376. int
  377. GetOurHostName(char *const host, const size_t siz)
  378. {
  379. #ifdef HOSTNAME
  380.     /* You can hardcode in the name if this routine doesn't work
  381.      * the way you want it to.
  382.      */
  383.     (void) Strncpy(host, HOSTNAME, siz);
  384.     return (kHostnameHardCoded);        /* Success */
  385. #else
  386.     struct hostent hp;
  387.     struct in_addr ip;
  388.     int result;
  389.     char **curAlias;
  390.     char domain[128];
  391.     char hpbuf[1024];
  392.     char *cp;
  393.     char *dlim, *dcp;
  394.     char *ctext;
  395.     int rc = 0;
  396.  
  397.     memset(host, 0, siz);
  398.     result = gethostname(host, (gethostname_size_t) siz);
  399.     if ((result < 0) || (host[0] == '\0')) {
  400.         rc = kGethostnameFailed;
  401.         goto done;    /* Failure */
  402.     }
  403.  
  404.     if (strchr(host, '.') != NULL) {
  405.         /* gethostname returned full name (like "cse.unl.edu"), instead
  406.          * of just the node name (like "cse").
  407.          */
  408.         rc = kGethostnameFullyQualified;
  409.         goto done;    /* Success */
  410.     }
  411.  
  412.     if ((GetHostByName(&hp, host, hpbuf, sizeof(hpbuf)) == 0) && (hp.h_name != NULL) && (hp.h_name[0] != '\0')) {
  413.         /* Maybe the host entry has the full name. */
  414.         cp = strchr((char *) hp.h_name, '.');
  415.         if ((cp != NULL) && (cp[1] != '\0')) {
  416.             /* The 'name' field for the host entry had full name. */
  417.             (void) Strncpy(host, (char *) hp.h_name, siz);
  418.             rc = kGethostbynameFullyQualified;
  419.             goto done;    /* Success */
  420.         }
  421.  
  422.         /* Make note of the IP address. */
  423.         ip = * ((struct in_addr **) hp.h_addr_list)[0];
  424.  
  425.         /* Now try the list of aliases, to see if any of those look real. */
  426.         for (curAlias = hp.h_aliases; *curAlias != NULL; curAlias++) {
  427.             cp = strchr(*curAlias, '.');
  428.             if ((cp != NULL) && (cp[1] != '\0')) {
  429.                 (void) Strncpy(host, *curAlias, siz);
  430.                 rc = kGethostbynameHostAliasFullyQualified;
  431.                 goto done;    /* Success */
  432.             }
  433.         }
  434.  
  435.         /* Use saved IP address to lookup the record by IP address. */
  436.         if (ip.s_addr != INADDR_NONE) {
  437.             if (GetHostByAddr(&hp, (char *) &ip, (int) sizeof(ip), AF_INET, hpbuf, sizeof(hpbuf)) == 0) {
  438.                 /* Maybe the host entry has the full name. */
  439.                 cp = strchr((char *) hp.h_name, '.');
  440.                 if ((cp != NULL) && (cp[1] != '\0')) {
  441.                     /* The 'name' field for the host entry had full name. */
  442.                     (void) Strncpy(host, (char *) hp.h_name, siz);
  443.                     rc = kGethostbyaddrFullyQualified;
  444.                     goto done;    /* Success */
  445.                 }
  446.  
  447.                 /* Now try the list of aliases, to see if any of those look real. */
  448.                 for (curAlias = hp.h_aliases; *curAlias != NULL; curAlias++) {
  449.                     cp = strchr(*curAlias, '.');
  450.                     if ((cp != NULL) && (cp[1] != '\0')) {
  451.                         (void) Strncpy(host, *curAlias, siz);
  452.                         rc = kGethostbyaddrHostAliasFullyQualified;
  453.                         goto done;    /* Success */
  454.                     }
  455.                 }
  456.             }
  457.         }
  458.     }
  459.  
  460.     /* Otherwise, we just have the node name.  See if we can get the
  461.      * domain name ourselves.
  462.      */
  463. #ifdef DOMAINNAME
  464.     (void) STRNCPY(domain, DOMAINNAME);
  465.     rc = kDomainnameHardCoded;
  466. #else
  467.     rc = kDomainnameUnknown;
  468.     domain[0] = '\0';
  469.  
  470. #    if defined(HAVE_RES_INIT) && defined(HAVE__RES_DEFDNAME)
  471.     if (domain[0] == '\0') {
  472.         res_init();
  473.         if ((_res.defdname != NULL) && (_res.defdname[0] != '\0')) {
  474.             STRNCPY(domain, _res.defdname);
  475.             rc = kResInitDomainnameFound;
  476.         }
  477.     }
  478. #    endif    /* HAVE_RES_INIT && HAVE__RES_DEFDNAME */
  479.     
  480.     if (domain[0] == '\0') {
  481.         FILE *fp;
  482.         char line[256];
  483.         char srch[128];
  484.         char *tok;
  485.  
  486.         fp = fopen("/etc/resolv.conf", "r");
  487.         if (fp != NULL) {
  488.             srch[0] = '\0';
  489.             memset(line, 0, sizeof(line));
  490.             while (fgets(line, sizeof(line) - 1, fp) != NULL) {
  491.                 if (!isalpha((int) line[0]))
  492.                     continue;    /* Skip comment lines. */
  493.                 ctext = NULL;
  494.                 tok = strtokc(line, " \t\n\r", &ctext);
  495.                 if (tok == NULL)
  496.                     continue;    /* Impossible */
  497.                 if (strcmp(tok, "domain") == 0) {
  498.                     tok = strtokc(NULL, " \t\n\r", &ctext);
  499.                     if (tok == NULL)
  500.                         continue;    /* syntax error */
  501.                     (void) STRNCPY(domain, tok);
  502.                     rc = kEtcResolvConfDomainFound;
  503.                     break;    /* Done. */
  504.                 } else if (strcmp(tok, "search") == 0) {
  505.                     tok = strtokc(NULL, " \t\n\r", &ctext);
  506.                     if (tok == NULL)
  507.                         continue;    /* syntax error */
  508.                     (void) STRNCPY(srch, tok);
  509.                     /* continue */
  510.                 }
  511.             }
  512.             (void) fclose(fp);
  513.  
  514.             if ((domain[0] == '\0') && (srch[0] != '\0')) {
  515.                 (void) STRNCPY(domain, srch);
  516.                 rc = kEtcResolvConfSearchFound;
  517.             }
  518.         }
  519.     }
  520.  
  521. #    if defined(HAVE_GETDOMAINNAME) || \
  522.         ((defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__))
  523.     if (domain[0] == '\0') {
  524.         if (getdomainname(domain, (gethostname_size_t) (sizeof(domain) - 1)) != 0) {
  525.             domain[0] = '\0';
  526.         } else if (strchr(domain, '.') == NULL) {
  527.             /* Probably a NIS domain, not a DNS domain name */
  528.             domain[0] = '\0';
  529.         }
  530.     }
  531. #    endif    /* HAVE_GETDOMAINNAME */
  532. #endif    /* DOMAINNAME */
  533.  
  534.     if (domain[0] != '\0') {
  535.         /* Supposedly, it's legal for a domain name with
  536.          * a period at the end.
  537.          */
  538.         cp = domain + strlen(domain) - 1;
  539.         if (*cp == '.')
  540.             *cp = '\0';
  541.         cp = domain;
  542.         dcp = host + strlen(host);
  543.         dlim = host + siz - 1;
  544.         if ((domain[0] != '.') && (dcp < dlim))
  545.             *dcp++ = '.';
  546.         while (*cp) {
  547.             if (dcp < dlim)
  548.                 *dcp++ = *cp;
  549.             cp++;
  550.         }
  551.         *dcp = '\0';
  552.     }
  553. done:
  554.     if (rc < 0)
  555.         memset(host, 0, siz);
  556.     if (host[siz - 1] != '\0') {
  557.         /* Hostname (most likely) couldn't fit.
  558.          * Return failure, but unlike other
  559.          * failures, leave what we had before
  560.          * it was truncated.
  561.          */
  562.         rc = kFullyQualifiedHostNameTooLongForBuffer;
  563.     }
  564.     return (rc);    /* Success */
  565. #endif    /* !HOSTNAME */
  566. }    /* GetOurHostName */
  567.