home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / older_versions / ncftp-3.2.2-src.tar.bz2 / ncftp-3.2.2-src.tar / ncftp-3.2.2 / sio / DNSUtil.c < prev    next >
C/C++ Source or Header  |  2008-07-13  |  14KB  |  572 lines

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