📄 ns.c
字号:
}
}
}
WSASetLastError(res);
if (!res) return 0;
return SOCKET_ERROR;
}
void check_hostent(struct hostent **he)
{
struct hostent *new_he;
WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
if(!*he)
{
new_he = HeapAlloc(GlobalHeap,
0,
sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
new_he->h_name = (PCHAR)(new_he + 1);
new_he->h_aliases = 0;
new_he->h_addrtype = 0; // AF_INET
new_he->h_length = 0; // sizeof(in_addr)
new_he->h_addr_list = HeapAlloc(GlobalHeap,
0,
sizeof(char *) * 2);
RtlZeroMemory(new_he->h_addr_list,
sizeof(char *) * 2);
*he = new_he;
}
}
void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr)
{
ASSERT(he);
//he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
//he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
strncpy(he->h_name,
name,
MAX_HOSTNAME_LEN);
if( !he->h_aliases ) {
he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
he->h_aliases[0] = 0;
}
he->h_addrtype = AF_INET;
he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
if( he->h_addr_list[0] )
{
HeapFree(GlobalHeap,
0,
he->h_addr_list[0]);
}
he->h_addr_list[0] = HeapAlloc(GlobalHeap,
0,
MAX_HOSTNAME_LEN + 1);
WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
RtlCopyMemory(he->h_addr_list[0],
(char*)&addr.IpAddress,
sizeof(addr.IpAddress));
he->h_addr_list[1] = 0;
}
#define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
void free_hostent(struct hostent *he)
{
if(he)
{
char *next = 0;
HFREE(he->h_name);
if(he->h_aliases)
{
next = he->h_aliases[0];
while(next) { HFREE(next); next++; }
}
if(he->h_addr_list)
{
next = he->h_addr_list[0];
while(next) { HFREE(next); next++; }
}
HFREE(he->h_addr_list);
HFREE(he->h_aliases);
HFREE(he);
}
}
/* WinSock 1.1 compatible name resolution APIs */
/*
* @unimplemented
*/
LPHOSTENT
EXPORT
gethostbyaddr(IN CONST CHAR FAR* addr,
IN INT len,
IN INT type)
{
UNIMPLEMENTED
return (LPHOSTENT)NULL;
}
/*
Assumes rfc 1123 - adam *
addr[1] = 0;
addr[0] = inet_addr(name);
strcpy( hostname, name );
if(addr[0] == 0xffffffff) return NULL;
he.h_addr_list = (void *)addr;
he.h_name = hostname;
he.h_aliases = NULL;
he.h_addrtype = AF_INET;
he.h_length = sizeof(addr);
return &he;
<RANT>
From the MSDN Platform SDK: Windows Sockets 2
"The gethostbyname function cannot resolve IP address strings passed to it.
Such a request is treated exactly as if an unknown host name were passed."
</RANT>
Defferring to the the documented behaviour, rather than the unix behaviour
What if the hostname is in the HOSTS file? see getservbyname
* @implemented
*/
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
/* see ws2_32.h, winsock2.h*/
/*getnetworkparameters - iphlp api */
/*
REFERENCES
servent -- w32api/include/winsock2.h
PWINSOCK_THREAD_BLOCK -- ws2_32.h
dllmain.c -- threadlocal memory allocation / deallocation
lib/dnsapi
*/
/* lib/adns/src/adns.h XXX */
/*
struct hostent {
char *h_name;
char **h_aliases;
short h_addrtype;
short h_length;
char **h_addr_list;
#define h_addr h_addr_list[0]
};
struct servent {
char *s_name;
char **s_aliases;
short s_port;
char *s_proto;
};
struct hostent defined in w32api/include/winsock2.h
*/
void free_servent(struct servent* s)
{
HFREE(s->s_name);
char* next = s->s_aliases[0];
while(next) { HFREE(next); next++; }
s->s_port = 0;
HFREE(s->s_proto);
HFREE(s);
}
LPHOSTENT
EXPORT
gethostbyname(IN CONST CHAR FAR* name)
{
enum addr_type
{
GH_INVALID,
GH_IPV6,
GH_IPV4,
GH_RFC1123_DNS
};
typedef enum addr_type addr_type;
addr_type addr;
int ret = 0;
char* found = 0;
DNS_STATUS dns_status = {0};
/* include/WinDNS.h -- look up DNS_RECORD on MSDN */
PDNS_RECORD dp = 0;
addr = GH_INVALID;
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
if( !p )
{
WSASetLastError( WSANOTINITIALISED );
return NULL;
}
check_hostent(&p->Hostent); /*XXX alloc_hostent*/
/* Hostname NULL - behave like gethostname */
if(name == NULL)
{
ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
return p->Hostent;
}
if(ret)
{
WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ??
return NULL;
}
/* Is it an IPv6 address? */
found = strstr(name, ":");
if( found != NULL )
{
addr = GH_IPV6;
goto act;
}
/* Is it an IPv4 address? */
if (!isalpha(name[0]))
{
addr = GH_IPV4;
goto act;
}
addr = GH_RFC1123_DNS;
/* Broken out in case we want to get fancy later */
act:
switch(addr)
{
case GH_IPV6:
WSASetLastError(STATUS_NOT_IMPLEMENTED);
return NULL;
break;
case GH_INVALID:
WSASetLastError(WSAEFAULT);
return NULL;
break;
/* Note: If passed an IP address, MSDN says that gethostbyname()
treats it as an unknown host.
This is different from the unix implementation. Use inet_addr()
*/
case GH_IPV4:
case GH_RFC1123_DNS:
/* DNS_TYPE_A: include/WinDNS.h */
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
dns_status = DnsQuery_A(name,
DNS_TYPE_A,
DNS_QUERY_STANDARD,
0,
/* extra dns servers */ &dp,
0);
if(dns_status == 0)
{
//ASSERT(dp->wType == DNS_TYPE_A);
//ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
PDNS_RECORD curr;
for(curr=dp;
curr != NULL && curr->wType != DNS_TYPE_A;
curr = curr->pNext )
{
WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
/*empty */
}
if(curr)
{
WS_DbgPrint(MID_TRACE,("populating hostent\n"));
WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
DnsRecordListFree(dp, DnsFreeRecordList);
return p->Hostent;
}
else
{
DnsRecordListFree(dp, DnsFreeRecordList);
}
}
WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
dns_status));
WSASetLastError(WSAHOST_NOT_FOUND);
return NULL;
break;
default:
WSASetLastError(WSANO_RECOVERY);
return NULL;
break;
}
WSASetLastError(WSANO_RECOVERY);
return NULL;
}
/*
* @implemented
*/
INT
EXPORT
gethostname(OUT CHAR FAR* name,
IN INT namelen)
{
DWORD size = namelen;
int ret = GetComputerNameExA(ComputerNameDnsHostname,
name,
&size);
if(ret == 0)
{
WSASetLastError(WSAEFAULT);
return SOCKET_ERROR;
}
else
{
name[namelen-1] = '\0';
return 0;
}
}
/*
* XXX arty -- Partial implementation pending a better one. This one will
* do for normal purposes.#include <ws2_32.h>
*
* Return the address of a static LPPROTOENT corresponding to the named
* protocol. These structs aren't very interesting, so I'm not too ashamed
* to have this function work on builtins for now.
*
* @unimplemented
*/
LPPROTOENT
EXPORT
getprotobyname(IN CONST CHAR FAR* name)
{
static CHAR *udp_aliases = 0;
static PROTOENT udp = { "udp", &udp_aliases, 17 };
static CHAR *tcp_aliases = 0;
static PROTOENT tcp = { "tcp", &tcp_aliases, 6 };
if(!_stricmp(name, "udp"))
{
return &udp;
}
else if (!_stricmp( name, "tcp"))
{
return &tcp;
}
return 0;
}
/*
* @unimplemented
*/
LPPROTOENT
EXPORT
getprotobynumber(IN INT number)
{
UNIMPLEMENTED
return (LPPROTOENT)NULL;
}
#define SKIPWS(ptr,act) \
{while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
#define SKIPANDMARKSTR(ptr,act) \
{while(*ptr && !isspace(*ptr)) ptr++; \
if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
static BOOL
DecodeServEntFromString(IN PCHAR ServiceString,
OUT PCHAR *ServiceName,
OUT PCHAR *PortNumberStr,
OUT PCHAR *ProtocolStr,
IN PCHAR *Aliases,
IN DWORD MaxAlias)
{
UINT NAliases = 0;
WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
SKIPWS(ServiceString, return FALSE);
*ServiceName = ServiceString;
SKIPANDMARKSTR(ServiceString, return FALSE);
SKIPWS(ServiceString, return FALSE);
*PortNumberStr = ServiceString;
SKIPANDMARKSTR(ServiceString, ;);
while( *ServiceString && NAliases < MaxAlias - 1 )
{
SKIPWS(ServiceString, break);
if( *ServiceString )
{
SKIPANDMARKSTR(ServiceString, ;);
if( strlen(ServiceString) )
{
WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
*Aliases++ = ServiceString;
NAliases++;
}
}
}
*Aliases = NULL;
*ProtocolStr = strchr(*PortNumberStr,'/');
if( !*ProtocolStr ) return FALSE;
**ProtocolStr = 0; (*ProtocolStr)++;
WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
*ServiceName, *ProtocolStr, *PortNumberStr,
NAliases));
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -