home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ncftp.com
/
ftp.ncftp.com.zip
/
ftp.ncftp.com
/
libncftp
/
older_versions
/
libncftp-3.2.2-src.tar.bz2
/
libncftp-3.2.2-src.tar
/
libncftp-3.2.2
/
sio
/
DNSUtil.c
< prev
next >
Wrap
C/C++ Source or Header
|
2005-11-21
|
14KB
|
567 lines
#include "syshdrs.h"
#ifdef PRAGMA_HDRSTOP
# pragma hdrstop
#endif
#ifndef STRNCPY
# define STRNCPY(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a) - 1] = '\0'
# define Strncpy(a,b,s) strncpy(a, b, s); a[s - 1] = '\0'
# define Strncat(a,b,s)\
{ \
size_t alen = strlen(a); \
if (alen < s) { \
strncpy(a + alen, b, s - alen); \
} \
a[s - 1] = '\0' \
}
#endif
#if (((defined(MACOSX)) && (MACOSX < 10300)) || (defined(AIX) && (AIX < 430)) || (defined(DIGITAL_UNIX)) || (defined(SOLARIS)) || (defined(SCO)) || (defined(HPUX)))
extern int getdomainname(char *name, gethostname_size_t namelen);
#endif
int
GetHostByName(struct hostent *const hp, const char *const name, char *const hpbuf, size_t hpbufsize)
{
#if defined(HAVE_GETHOSTBYNAME_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
struct hostent *h;
int h_errno_unused = 0;
memset(hpbuf, 0, hpbufsize);
h = gethostbyname_r(name, hp, hpbuf, hpbufsize, &h_errno_unused);
if (h != NULL)
return (0);
#elif defined(HAVE_GETHOSTBYNAME2_R) && defined(LINUX)
char *usehpbuf;
struct hostent *h;
int my_h_errno, rc;
usehpbuf = hpbuf;
forever {
errno = 0;
my_h_errno = 0;
h = NULL;
memset(usehpbuf, 0, hpbufsize);
rc = gethostbyname2_r(name, AF_INET, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
if ((rc == 0) && (h != NULL))
return (0);
if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
hpbufsize *= 2;
usehpbuf = alloca(hpbufsize);
if (usehpbuf == NULL) {
errno = ENOMEM;
return (-1);
}
}
if ((rc == 0) && (my_h_errno != 0))
errno = ENOENT;
break;
}
#elif defined(HAVE_GETHOSTBYNAME_R) && defined(LINUX)
char *usehpbuf;
struct hostent *h;
int my_h_errno, rc;
usehpbuf = hpbuf;
forever {
errno = 0;
my_h_errno = 0;
h = NULL;
memset(usehpbuf, 0, hpbufsize);
rc = gethostbyname_r(name, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
if ((rc == 0) && (my_h_errno == 0))
return (0);
if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
hpbufsize *= 2;
usehpbuf = alloca(hpbufsize);
if (usehpbuf == NULL) {
errno = ENOMEM;
return (-1);
}
}
if ((rc == 0) && (my_h_errno != 0))
errno = ENOENT;
break;
}
#elif defined(HAVE_GETHOSTBYNAME_R) && defined(AIX)
struct hostent_data hed;
memset(hpbuf, 0, hpbufsize);
memset(&hed, 0, sizeof(hed));
if (gethostbyname_r(name, hp, &hed) == 0)
return (0);
#else
/* Note: gethostbyname is already threadsafe on: HP-UX, Tru64 */
struct hostent *h;
h = gethostbyname(name);
if (h != NULL) {
memcpy(hp, h, sizeof(struct hostent));
return (0);
} else {
memset(hp, 0, sizeof(struct hostent));
memset(hpbuf, 0, hpbufsize);
}
#endif
return (-1);
} /* GetHostByName */
int
GetHostByAddr(struct hostent *const hp, void *addr, int asize, int atype, char *const hpbuf, size_t hpbufsize)
{
#if defined(HAVE_GETHOSTBYADDR_R) && (defined(SOLARIS) || defined(IRIX) || defined(BSDOS))
struct hostent *h;
int h_errno_unused = 0;
memset(hpbuf, 0, hpbufsize);
h = gethostbyaddr_r((gethost_addrptr_t) addr, asize, atype, hp, hpbuf, hpbufsize, &h_errno_unused);
if (h != NULL)
return (0);
#elif defined(HAVE_GETHOSTBYADDR_R) && defined(LINUX)
char *usehpbuf;
struct hostent *h;
int my_h_errno, rc;
usehpbuf = hpbuf;
forever {
errno = 0;
my_h_errno = 0;
h = NULL;
memset(usehpbuf, 0, hpbufsize);
rc = gethostbyaddr_r((gethost_addrptr_t) addr, asize, atype, hp, usehpbuf, hpbufsize, &h, &my_h_errno);
if ((rc == 0) && (h != NULL))
return (0);
if ((rc == ERANGE) || ((rc == -1) && (errno == ERANGE))) {
hpbufsize *= 2;
usehpbuf = alloca(hpbufsize);
if (usehpbuf == NULL) {
errno = ENOMEM;
return (-1);
}
}
if ((rc == 0) && (my_h_errno != 0))
errno = ENOENT;
break;
}
#elif defined(HAVE_GETHOSTBYADDR_R) && defined(AIX)
struct hostent_data hed;
memset(hpbuf, 0, hpbufsize);
memset(&hed, 0, sizeof(hed));
if (gethostbyaddr_r(addr, asize, atype, hp, &hed) == 0)
return (0);
#else
/* Note: gethostbyaddr is already threadsafe on: HP-UX, Tru64 */
struct hostent *h;
h = gethostbyaddr((gethost_addrptr_t) addr, asize, atype);
if (h != NULL) {
memcpy(hp, h, sizeof(struct hostent));
return (0);
} else {
memset(hp, 0, sizeof(struct hostent));
memset(hpbuf, 0, hpbufsize);
}
#endif
return (-1);
} /* GetHostByAddr */
/* On entry, you should have 'host' be set to a symbolic name (like
* cse.unl.edu), or set to a numeric address (like 129.93.3.1).
* If the function fails, it will return NULL, but if the host was
* a numeric style address, you'll have the ip_address to fall back on.
*/
int
GetHostEntry(struct hostent *const hp, const char *const host, struct in_addr *const ip_address, char *const hpbuf, size_t hpbufsize)
{
struct in_addr ip;
int rc = -1;
/* See if the host was given in the dotted IP format, like "36.44.0.2."
* If it was, inet_addr will convert that to a 32-bit binary value;
* if not, inet_addr will return (-1L).
*/
ip.s_addr = inet_addr(host);
if (ip.s_addr != INADDR_NONE) {
if (GetHostByAddr(hp, (char *) &ip, (int) sizeof(ip), AF_INET, hpbuf, hpbufsize) == 0) {
rc = 0;
if (ip_address != NULL)
(void) memcpy(&ip_address->s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
} else if (ip_address != NULL) {
(void) memcpy(ip_address, &ip, sizeof(struct in_addr));
}
} else {
/* No IP address, so it must be a hostname, like ftp.wustl.edu. */
if (ip_address != NULL)
ip_address->s_addr = INADDR_NONE;
if (GetHostByName(hp, host, hpbuf, hpbufsize) == 0) {
rc = 0;
if (ip_address != NULL)
(void) memcpy(&ip_address->s_addr, hp->h_addr_list[0], (size_t) hp->h_length);
}
}
return (rc);
} /* GetHostEntry */
static char *
strtokc(char *parsestr, const char *delims, char **context)
{
char *cp;
const char *cp2;
char c, c2;
char *start;
if (parsestr == NULL)
start = *context;
else
start = parsestr;
if ((start == NULL) || (delims == NULL)) {
*context = NULL;
return NULL;
}
/* Eat leading delimiters. */
for (cp = start; ; ) {
next1:
c = *cp++;
if (c == '\0') {
/* No more tokens. */
*context = NULL;
return (NULL);
}
for (cp2 = delims; ; ) {
c2 = (char) *cp2++;
if (c2 == '\0') {
/* This character was not a delimiter.
* The token starts here.
*/
start = cp - 1;
goto starttok;
}
if (c2 == c) {
/* This char was a delimiter. */
/* Skip it, look at next character. */
goto next1;
}
}
/*NOTREACHED*/
}
starttok:
for ( ; ; cp++) {
c = *cp;
if (c == '\0') {
/* Token is finished. */
*context = cp;
break;
}
for (cp2 = delims; ; ) {
c2 = (char) *cp2++;
if (c2 == '\0') {
/* This character was not a delimiter.
* Keep it as part of current token.
*/
break;
}
if (c2 == c) {
/* This char was a delimiter. */
/* End of token. */
*cp++ = '\0';
*context = cp;
return (start);
}
}
}
return (start);
} /* strtokc */
#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)
int
getdomainname(char *const domain, unsigned int dsize)
{
HKEY hkey;
DWORD rc;
DWORD valSize;
/* Works for Win NT/2000/XP */
rc = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
0,
KEY_READ,
&hkey
);
if (rc == ERROR_SUCCESS) {
valSize = (DWORD) (dsize - 1);
memset(domain, 0, dsize);
rc = RegQueryValueEx(
hkey,
"DhcpDomain",
NULL,
NULL,
(LPBYTE) domain,
&valSize
);
if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
RegCloseKey(hkey);
return (0);
}
valSize = (DWORD) (dsize - 1);
memset(domain, 0, dsize);
rc = RegQueryValueEx(
hkey,
"Domain",
NULL,
NULL,
(LPBYTE) domain,
&valSize
);
if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
RegCloseKey(hkey);
return (0);
}
RegCloseKey(hkey);
}
/* Works for Win 9x */
rc = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Services\\VxD\\MSTCP",
0,
KEY_READ,
&hkey
);
if (rc == ERROR_SUCCESS) {
valSize = (DWORD) (dsize - 1);
memset(domain, 0, dsize);
rc = RegQueryValueEx(
hkey,
"Domain",
NULL,
NULL,
(LPBYTE) domain,
&valSize
);
if ((rc == ERROR_SUCCESS) && (domain[0] != '\0')) {
RegCloseKey(hkey);
return (0);
}
RegCloseKey(hkey);
}
memset(domain, 0, dsize);
return (-1);
} /* getdomainname */
#endif /* WINDOWS */
/* Makes every effort to return a fully qualified domain name. */
int
GetOurHostName(char *const host, const size_t siz)
{
#ifdef HOSTNAME
/* You can hardcode in the name if this routine doesn't work
* the way you want it to.
*/
(void) Strncpy(host, HOSTNAME, siz);
return (kHostnameHardCoded); /* Success */
#else
struct hostent hp;
struct in_addr ip;
int result;
char **curAlias;
char domain[128];
char hpbuf[1024];
char *cp;
char *dlim, *dcp;
char *ctext;
int rc = 0;
memset(host, 0, siz);
result = gethostname(host, (gethostname_size_t) siz);
if ((result < 0) || (host[0] == '\0')) {
rc = kGethostnameFailed;
goto done; /* Failure */
}
if (strchr(host, '.') != NULL) {
/* gethostname returned full name (like "cse.unl.edu"), instead
* of just the node name (like "cse").
*/
rc = kGethostnameFullyQualified;
goto done; /* Success */
}
if ((GetHostByName(&hp, host, hpbuf, sizeof(hpbuf)) == 0) && (hp.h_name != NULL) && (hp.h_name[0] != '\0')) {
/* Maybe the host entry has the full name. */
cp = strchr((char *) hp.h_name, '.');
if ((cp != NULL) && (cp[1] != '\0')) {
/* The 'name' field for the host entry had full name. */
(void) Strncpy(host, (char *) hp.h_name, siz);
rc = kGethostbynameFullyQualified;
goto done; /* Success */
}
/* Make note of the IP address. */
ip = * ((struct in_addr **) hp.h_addr_list)[0];
/* Now try the list of aliases, to see if any of those look real. */
for (curAlias = hp.h_aliases; *curAlias != NULL; curAlias++) {
cp = strchr(*curAlias, '.');
if ((cp != NULL) && (cp[1] != '\0')) {
(void) Strncpy(host, *curAlias, siz);
rc = kGethostbynameHostAliasFullyQualified;
goto done; /* Success */
}
}
/* Use saved IP address to lookup the record by IP address. */
if (ip.s_addr != INADDR_NONE) {
if (GetHostByAddr(&hp, (char *) &ip, (int) sizeof(ip), AF_INET, hpbuf, sizeof(hpbuf)) == 0) {
/* Maybe the host entry has the full name. */
cp = strchr((char *) hp.h_name, '.');
if ((cp != NULL) && (cp[1] != '\0')) {
/* The 'name' field for the host entry had full name. */
(void) Strncpy(host, (char *) hp.h_name, siz);
rc = kGethostbyaddrFullyQualified;
goto done; /* Success */
}
/* Now try the list of aliases, to see if any of those look real. */
for (curAlias = hp.h_aliases; *curAlias != NULL; curAlias++) {
cp = strchr(*curAlias, '.');
if ((cp != NULL) && (cp[1] != '\0')) {
(void) Strncpy(host, *curAlias, siz);
rc = kGethostbyaddrHostAliasFullyQualified;
goto done; /* Success */
}
}
}
}
}
/* Otherwise, we just have the node name. See if we can get the
* domain name ourselves.
*/
#ifdef DOMAINNAME
(void) STRNCPY(domain, DOMAINNAME);
rc = kDomainnameHardCoded;
#else
rc = kDomainnameUnknown;
domain[0] = '\0';
# if defined(HAVE_RES_INIT) && defined(HAVE__RES_DEFDNAME)
if (domain[0] == '\0') {
res_init();
if ((_res.defdname != NULL) && (_res.defdname[0] != '\0')) {
STRNCPY(domain, _res.defdname);
rc = kResInitDomainnameFound;
}
}
# endif /* HAVE_RES_INIT && HAVE__RES_DEFDNAME */
if (domain[0] == '\0') {
FILE *fp;
char line[256];
char srch[128];
char *tok;
fp = fopen("/etc/resolv.conf", "r");
if (fp != NULL) {
srch[0] = '\0';
memset(line, 0, sizeof(line));
while (fgets(line, sizeof(line) - 1, fp) != NULL) {
if (!isalpha((int) line[0]))
continue; /* Skip comment lines. */
ctext = NULL;
tok = strtokc(line, " \t\n\r", &ctext);
if (tok == NULL)
continue; /* Impossible */
if (strcmp(tok, "domain") == 0) {
tok = strtokc(NULL, " \t\n\r", &ctext);
if (tok == NULL)
continue; /* syntax error */
(void) STRNCPY(domain, tok);
rc = kEtcResolvConfDomainFound;
break; /* Done. */
} else if (strcmp(tok, "search") == 0) {
tok = strtokc(NULL, " \t\n\r", &ctext);
if (tok == NULL)
continue; /* syntax error */
(void) STRNCPY(srch, tok);
/* continue */
}
}
(void) fclose(fp);
if ((domain[0] == '\0') && (srch[0] != '\0')) {
(void) STRNCPY(domain, srch);
rc = kEtcResolvConfSearchFound;
}
}
}
# if defined(HAVE_GETDOMAINNAME) || \
((defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__))
if (domain[0] == '\0') {
if (getdomainname(domain, (gethostname_size_t) (sizeof(domain) - 1)) != 0) {
domain[0] = '\0';
} else if (strchr(domain, '.') == NULL) {
/* Probably a NIS domain, not a DNS domain name */
domain[0] = '\0';
}
}
# endif /* HAVE_GETDOMAINNAME */
#endif /* DOMAINNAME */
if (domain[0] != '\0') {
/* Supposedly, it's legal for a domain name with
* a period at the end.
*/
cp = domain + strlen(domain) - 1;
if (*cp == '.')
*cp = '\0';
cp = domain;
dcp = host + strlen(host);
dlim = host + siz - 1;
if ((domain[0] != '.') && (dcp < dlim))
*dcp++ = '.';
while (*cp) {
if (dcp < dlim)
*dcp++ = *cp;
cp++;
}
*dcp = '\0';
}
done:
if (rc < 0)
memset(host, 0, siz);
if (host[siz - 1] != '\0') {
/* Hostname (most likely) couldn't fit.
* Return failure, but unlike other
* failures, leave what we had before
* it was truncated.
*/
rc = kFullyQualifiedHostNameTooLongForBuffer;
}
return (rc); /* Success */
#endif /* !HOSTNAME */
} /* GetOurHostName */