ws2_32: Move host lookup functions to protocol.c.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e30b16d738
commit
ec9f311930
|
@ -29,6 +29,8 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
|
||||
|
||||
#define MAP_OPTION(opt) { WS_##opt, opt }
|
||||
|
||||
static const int ws_aiflag_map[][2] =
|
||||
|
@ -66,6 +68,20 @@ static const int ws_eai_map[][2] =
|
|||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const int ws_af_map[][2] =
|
||||
{
|
||||
MAP_OPTION( AF_UNSPEC ),
|
||||
MAP_OPTION( AF_INET ),
|
||||
MAP_OPTION( AF_INET6 ),
|
||||
#ifdef HAS_IPX
|
||||
MAP_OPTION( AF_IPX ),
|
||||
#endif
|
||||
#ifdef AF_IRDA
|
||||
MAP_OPTION( AF_IRDA ),
|
||||
#endif
|
||||
{FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
|
||||
};
|
||||
|
||||
static const int ws_proto_map[][2] =
|
||||
{
|
||||
MAP_OPTION( IPPROTO_IP ),
|
||||
|
@ -81,6 +97,32 @@ static const int ws_proto_map[][2] =
|
|||
|
||||
#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
|
||||
|
||||
static int convert_af_w2u( int family )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
|
||||
{
|
||||
if (ws_af_map[i][0] == family)
|
||||
return ws_af_map[i][1];
|
||||
}
|
||||
FIXME( "unhandled Windows address family %d\n", family );
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int convert_af_u2w( int family )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
|
||||
{
|
||||
if (ws_af_map[i][1] == family)
|
||||
return ws_af_map[i][0];
|
||||
}
|
||||
FIXME( "unhandled UNIX address family %d\n", family );
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int convert_proto_w2u( int protocol )
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -810,3 +852,452 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
|
|||
ai = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static UINT host_errno_from_unix( int err )
|
||||
{
|
||||
WARN( "%d\n", err );
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
|
||||
case TRY_AGAIN: return WSATRY_AGAIN;
|
||||
case NO_RECOVERY: return WSANO_RECOVERY;
|
||||
case NO_DATA: return WSANO_DATA;
|
||||
case ENOBUFS: return WSAENOBUFS;
|
||||
case 0: return 0;
|
||||
default:
|
||||
WARN( "Unknown h_errno %d!\n", err );
|
||||
return WSAEOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static struct WS_hostent *get_hostent_buffer( unsigned int size )
|
||||
{
|
||||
struct per_thread_data *data = get_per_thread_data();
|
||||
if (data->he_buffer)
|
||||
{
|
||||
if (data->he_len >= size) return data->he_buffer;
|
||||
HeapFree( GetProcessHeap(), 0, data->he_buffer );
|
||||
}
|
||||
data->he_buffer = HeapAlloc( GetProcessHeap(), 0, (data->he_len = size) );
|
||||
if (!data->he_buffer) SetLastError(WSAENOBUFS);
|
||||
return data->he_buffer;
|
||||
}
|
||||
|
||||
/* create a hostent entry
|
||||
*
|
||||
* Creates the entry with enough memory for the name, aliases
|
||||
* addresses, and the address pointers. Also copies the name
|
||||
* and sets up all the pointers.
|
||||
*
|
||||
* NOTE: The alias and address lists must be allocated with room
|
||||
* for the NULL item terminating the list. This is true even if
|
||||
* the list has no items ("aliases" and "addresses" must be
|
||||
* at least "1", a truly empty list is invalid).
|
||||
*/
|
||||
static struct WS_hostent *create_hostent( char *name, int alias_count, int aliases_size,
|
||||
int address_count, int address_length )
|
||||
{
|
||||
struct WS_hostent *p_to;
|
||||
char *p;
|
||||
unsigned int size = sizeof(struct WS_hostent), i;
|
||||
|
||||
size += strlen(name) + 1;
|
||||
size += alias_count * sizeof(char *);
|
||||
size += aliases_size;
|
||||
size += address_count * sizeof(char *);
|
||||
size += (address_count - 1) * address_length;
|
||||
|
||||
if (!(p_to = get_hostent_buffer( size ))) return NULL;
|
||||
memset( p_to, 0, size );
|
||||
|
||||
/* Use the memory in the same way winsock does.
|
||||
* First set the pointer for aliases, second set the pointers for addresses.
|
||||
* Third fill the addresses indexes, fourth jump aliases names size.
|
||||
* Fifth fill the hostname.
|
||||
* NOTE: This method is valid for OS versions >= XP.
|
||||
*/
|
||||
p = (char *)(p_to + 1);
|
||||
p_to->h_aliases = (char **)p;
|
||||
p += alias_count * sizeof(char *);
|
||||
|
||||
p_to->h_addr_list = (char **)p;
|
||||
p += address_count * sizeof(char *);
|
||||
|
||||
for (i = 0, address_count--; i < address_count; i++, p += address_length)
|
||||
p_to->h_addr_list[i] = p;
|
||||
|
||||
/* h_aliases must be filled in manually because we don't know each string
|
||||
* size. Leave these pointers NULL (already set to NULL by memset earlier).
|
||||
*/
|
||||
p += aliases_size;
|
||||
|
||||
p_to->h_name = p;
|
||||
strcpy( p, name );
|
||||
|
||||
return p_to;
|
||||
}
|
||||
|
||||
static struct WS_hostent *hostent_from_unix( const struct hostent *p_he )
|
||||
{
|
||||
int i, addresses = 0, alias_size = 0;
|
||||
struct WS_hostent *p_to;
|
||||
char *p;
|
||||
|
||||
for (i = 0; p_he->h_aliases[i]; i++)
|
||||
alias_size += strlen( p_he->h_aliases[i] ) + 1;
|
||||
while (p_he->h_addr_list[addresses])
|
||||
addresses++;
|
||||
|
||||
p_to = create_hostent( p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length );
|
||||
|
||||
if (!p_to) return NULL;
|
||||
p_to->h_addrtype = convert_af_u2w( p_he->h_addrtype );
|
||||
p_to->h_length = p_he->h_length;
|
||||
|
||||
for (i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
|
||||
memcpy( p, p_he->h_addr_list[i], p_to->h_length );
|
||||
|
||||
/* Fill the aliases after the IP data */
|
||||
for (i = 0; p_he->h_aliases[i]; i++)
|
||||
{
|
||||
p_to->h_aliases[i] = p;
|
||||
strcpy( p, p_he->h_aliases[i] );
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
|
||||
return p_to;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* gethostbyaddr (ws2_32.51)
|
||||
*/
|
||||
struct WS_hostent * WINAPI WS_gethostbyaddr( const char *addr, int len, int type )
|
||||
{
|
||||
struct WS_hostent *retval = NULL;
|
||||
struct hostent *host;
|
||||
int unixtype = convert_af_w2u(type);
|
||||
const char *paddr = addr;
|
||||
unsigned long loopback;
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
char *extrabuf;
|
||||
int ebufsize = 1024;
|
||||
struct hostent hostentry;
|
||||
int locerr = ENOBUFS;
|
||||
#endif
|
||||
|
||||
/* convert back the magic loopback address if necessary */
|
||||
if (unixtype == AF_INET && len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
|
||||
{
|
||||
loopback = htonl( INADDR_LOOPBACK );
|
||||
paddr = (char *)&loopback;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
host = NULL;
|
||||
extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
|
||||
while (extrabuf)
|
||||
{
|
||||
int res = gethostbyaddr_r( paddr, len, unixtype, &hostentry, extrabuf, ebufsize, &host, &locerr );
|
||||
if (res != ERANGE) break;
|
||||
ebufsize *= 2;
|
||||
extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
|
||||
}
|
||||
if (host)
|
||||
retval = hostent_from_unix( host );
|
||||
else
|
||||
SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
|
||||
HeapFree( GetProcessHeap(), 0, extrabuf );
|
||||
#else
|
||||
EnterCriticalSection( &csWSgetXXXbyYYY );
|
||||
host = gethostbyaddr( paddr, len, unixtype );
|
||||
if (host)
|
||||
retval = hostent_from_unix( host );
|
||||
else
|
||||
SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
|
||||
LeaveCriticalSection( &csWSgetXXXbyYYY );
|
||||
#endif
|
||||
|
||||
TRACE( "ptr %p, len %d, type %d ret %p\n", addr, len, type, retval );
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
struct route
|
||||
{
|
||||
struct in_addr addr;
|
||||
IF_INDEX interface;
|
||||
DWORD metric, default_route;
|
||||
};
|
||||
|
||||
static int compare_routes_by_metric_asc( const void *left, const void *right )
|
||||
{
|
||||
const struct route *a = left, *b = right;
|
||||
if (a->default_route && b->default_route)
|
||||
return a->default_route - b->default_route;
|
||||
if (a->default_route && !b->default_route)
|
||||
return -1;
|
||||
if (b->default_route && !a->default_route)
|
||||
return 1;
|
||||
return a->metric - b->metric;
|
||||
}
|
||||
|
||||
/* Returns the list of local IP addresses by going through the network
|
||||
* adapters and using the local routing table to sort the addresses
|
||||
* from highest routing priority to lowest routing priority. This
|
||||
* functionality is inferred from the description for obtaining local
|
||||
* IP addresses given in the Knowledge Base Article Q160215.
|
||||
*
|
||||
* Please note that the returned hostent is only freed when the thread
|
||||
* closes and is replaced if another hostent is requested.
|
||||
*/
|
||||
static struct WS_hostent *get_local_ips( char *hostname )
|
||||
{
|
||||
int numroutes = 0, i, j, default_routes = 0;
|
||||
IP_ADAPTER_INFO *adapters = NULL, *k;
|
||||
struct WS_hostent *hostlist = NULL;
|
||||
MIB_IPFORWARDTABLE *routes = NULL;
|
||||
struct route *route_addrs = NULL;
|
||||
DWORD adap_size, route_size, n;
|
||||
|
||||
/* Obtain the size of the adapter list and routing table, also allocate memory */
|
||||
if (GetAdaptersInfo( NULL, &adap_size ) != ERROR_BUFFER_OVERFLOW)
|
||||
return NULL;
|
||||
if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
|
||||
return NULL;
|
||||
|
||||
adapters = HeapAlloc( GetProcessHeap(), 0, adap_size );
|
||||
routes = HeapAlloc( GetProcessHeap(), 0, route_size );
|
||||
if (!adapters || !routes)
|
||||
goto cleanup;
|
||||
|
||||
/* Obtain the adapter list and the full routing table */
|
||||
if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
|
||||
goto cleanup;
|
||||
if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
|
||||
goto cleanup;
|
||||
|
||||
/* Store the interface associated with each route */
|
||||
for (n = 0; n < routes->dwNumEntries; n++)
|
||||
{
|
||||
IF_INDEX ifindex;
|
||||
DWORD ifmetric, ifdefault = 0;
|
||||
BOOL exists = FALSE;
|
||||
|
||||
/* Check if this is a default route (there may be more than one) */
|
||||
if (!routes->table[n].dwForwardDest)
|
||||
ifdefault = ++default_routes;
|
||||
else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
|
||||
continue;
|
||||
ifindex = routes->table[n].dwForwardIfIndex;
|
||||
ifmetric = routes->table[n].dwForwardMetric1;
|
||||
/* Only store the lowest valued metric for an interface */
|
||||
for (j = 0; j < numroutes; j++)
|
||||
{
|
||||
if (route_addrs[j].interface == ifindex)
|
||||
{
|
||||
if (route_addrs[j].metric > ifmetric)
|
||||
route_addrs[j].metric = ifmetric;
|
||||
exists = TRUE;
|
||||
}
|
||||
}
|
||||
if (exists)
|
||||
continue;
|
||||
route_addrs = heap_realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
|
||||
if (!route_addrs)
|
||||
goto cleanup;
|
||||
route_addrs[numroutes].interface = ifindex;
|
||||
route_addrs[numroutes].metric = ifmetric;
|
||||
route_addrs[numroutes].default_route = ifdefault;
|
||||
/* If no IP is found in the next step (for whatever reason)
|
||||
* then fall back to the magic loopback address.
|
||||
*/
|
||||
memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
|
||||
numroutes++;
|
||||
}
|
||||
if (numroutes == 0)
|
||||
goto cleanup; /* No routes, fall back to the Magic IP */
|
||||
|
||||
/* Find the IP address associated with each found interface */
|
||||
for (i = 0; i < numroutes; i++)
|
||||
{
|
||||
for (k = adapters; k != NULL; k = k->Next)
|
||||
{
|
||||
char *ip = k->IpAddressList.IpAddress.String;
|
||||
|
||||
if (route_addrs[i].interface == k->Index)
|
||||
route_addrs[i].addr.s_addr = inet_addr(ip);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a hostent and enough memory for all the IPs,
|
||||
* including the NULL at the end of the list.
|
||||
*/
|
||||
hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
|
||||
if (hostlist == NULL)
|
||||
goto cleanup;
|
||||
hostlist->h_addr_list[numroutes] = NULL;
|
||||
hostlist->h_aliases[0] = NULL;
|
||||
hostlist->h_addrtype = AF_INET;
|
||||
hostlist->h_length = sizeof(struct in_addr);
|
||||
|
||||
/* Reorder the entries before placing them in the host list. Windows expects
|
||||
* the IP list in order from highest priority to lowest (the critical thing
|
||||
* is that most applications expect the first IP to be the default route).
|
||||
*/
|
||||
if (numroutes > 1)
|
||||
qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
|
||||
|
||||
for (i = 0; i < numroutes; i++)
|
||||
*(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
|
||||
|
||||
cleanup:
|
||||
HeapFree( GetProcessHeap(), 0, route_addrs );
|
||||
HeapFree( GetProcessHeap(), 0, adapters );
|
||||
HeapFree( GetProcessHeap(), 0, routes );
|
||||
return hostlist;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* gethostbyname (ws2_32.52)
|
||||
*/
|
||||
struct WS_hostent * WINAPI WS_gethostbyname( const char *name )
|
||||
{
|
||||
struct WS_hostent *retval = NULL;
|
||||
struct hostent *host;
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
char *extrabuf;
|
||||
int ebufsize = 1024;
|
||||
struct hostent hostentry;
|
||||
int locerr = ENOBUFS;
|
||||
#endif
|
||||
char hostname[100];
|
||||
|
||||
if (!num_startup)
|
||||
{
|
||||
SetLastError( WSANOTINITIALISED );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gethostname( hostname, 100 ) == -1)
|
||||
{
|
||||
SetLastError( WSAENOBUFS );
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!name || !name[0])
|
||||
name = hostname;
|
||||
|
||||
/* If the hostname of the local machine is requested then return the
|
||||
* complete list of local IP addresses */
|
||||
if (!strcmp( name, hostname ))
|
||||
retval = get_local_ips( hostname );
|
||||
|
||||
/* If any other hostname was requested (or the routing table lookup failed)
|
||||
* then return the IP found by the host OS */
|
||||
if (!retval)
|
||||
{
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
host = NULL;
|
||||
extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
|
||||
while (extrabuf)
|
||||
{
|
||||
int res = gethostbyname_r( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
|
||||
if (res != ERANGE) break;
|
||||
ebufsize *= 2;
|
||||
extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
|
||||
}
|
||||
if (!host) SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
|
||||
#else
|
||||
EnterCriticalSection( &csWSgetXXXbyYYY );
|
||||
host = gethostbyname( name );
|
||||
if (!host) SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
|
||||
#endif
|
||||
if (host) retval = hostent_from_unix( host );
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
HeapFree( GetProcessHeap(), 0, extrabuf );
|
||||
#else
|
||||
LeaveCriticalSection( &csWSgetXXXbyYYY );
|
||||
#endif
|
||||
}
|
||||
|
||||
if (retval && retval->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
|
||||
{
|
||||
/* hostname != "localhost" but has loopback address. replace by our
|
||||
* special address.*/
|
||||
memcpy( retval->h_addr_list[0], magic_loopback_addr, 4 );
|
||||
}
|
||||
|
||||
TRACE( "%s ret %p\n", debugstr_a(name), retval );
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* gethostname (ws2_32.57)
|
||||
*/
|
||||
int WINAPI WS_gethostname( char *name, int namelen )
|
||||
{
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
TRACE( "name %p, len %d\n", name, namelen );
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError( WSAEFAULT );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gethostname( buf, sizeof(buf) ) != 0)
|
||||
{
|
||||
SetLastError( sock_get_error( errno ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
TRACE( "<- %s\n", debugstr_a(buf) );
|
||||
len = strlen( buf );
|
||||
if (len > 15)
|
||||
WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
|
||||
if (namelen <= len)
|
||||
{
|
||||
SetLastError( WSAEFAULT );
|
||||
return -1;
|
||||
}
|
||||
strcpy( name, buf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetHostNameW (ws2_32.@)
|
||||
*/
|
||||
int WINAPI GetHostNameW( WCHAR *name, int namelen )
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
TRACE( "name %p, len %d\n", name, namelen );
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError( WSAEFAULT );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gethostname( buf, sizeof(buf) ))
|
||||
{
|
||||
SetLastError( sock_get_error( errno ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
|
||||
{
|
||||
SetLastError( WSAEFAULT );
|
||||
return -1;
|
||||
}
|
||||
MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -225,13 +225,6 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
|||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
|
||||
LPWSABUF lpControlBuffer );
|
||||
|
||||
#define DECLARE_CRITICAL_SECTION(cs) \
|
||||
static CRITICAL_SECTION cs; \
|
||||
static CRITICAL_SECTION_DEBUG cs##_debug = \
|
||||
{ 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
|
||||
static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
|
||||
|
||||
DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
|
||||
DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
|
||||
DECLARE_CRITICAL_SECTION(cs_socket_list);
|
||||
|
@ -618,35 +611,10 @@ typedef struct /* WSAAsyncSelect() control struct */
|
|||
#define WS_MAX_UDP_DATAGRAM 1024
|
||||
static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
|
||||
|
||||
/* hostent's, servent's and protent's are stored in one buffer per thread,
|
||||
* as documented on MSDN for the functions that return any of the buffers */
|
||||
struct per_thread_data
|
||||
{
|
||||
int opentype;
|
||||
struct WS_hostent *he_buffer;
|
||||
struct WS_servent *se_buffer;
|
||||
struct WS_protoent *pe_buffer;
|
||||
struct pollfd *fd_cache;
|
||||
unsigned int fd_count;
|
||||
int he_len;
|
||||
int se_len;
|
||||
int pe_len;
|
||||
char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
|
||||
};
|
||||
|
||||
/* internal: routing description information */
|
||||
struct route {
|
||||
struct in_addr addr;
|
||||
IF_INDEX interface;
|
||||
DWORD metric, default_route;
|
||||
};
|
||||
|
||||
static INT num_startup; /* reference counter */
|
||||
int num_startup;
|
||||
static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
|
||||
|
||||
/* function prototypes */
|
||||
static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length);
|
||||
static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
|
||||
static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot );
|
||||
static struct WS_servent *WS_dup_se(const struct servent* p_se);
|
||||
static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
|
||||
|
@ -741,20 +709,6 @@ static const int ws_ipv6_map[][2] =
|
|||
#endif
|
||||
};
|
||||
|
||||
static const int ws_af_map[][2] =
|
||||
{
|
||||
MAP_OPTION( AF_UNSPEC ),
|
||||
MAP_OPTION( AF_INET ),
|
||||
MAP_OPTION( AF_INET6 ),
|
||||
#ifdef HAS_IPX
|
||||
MAP_OPTION( AF_IPX ),
|
||||
#endif
|
||||
#ifdef AF_IRDA
|
||||
MAP_OPTION( AF_IRDA ),
|
||||
#endif
|
||||
{FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
|
||||
};
|
||||
|
||||
static const int ws_socktype_map[][2] =
|
||||
{
|
||||
MAP_OPTION( SOCK_DGRAM ),
|
||||
|
@ -783,8 +737,6 @@ static const int ws_poll_map[][2] =
|
|||
{ WS_POLLRDBAND, POLLPRI }
|
||||
};
|
||||
|
||||
static const char magic_loopback_addr[] = {127, 12, 34, 56};
|
||||
|
||||
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
|
||||
#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
|
||||
static inline WSACMSGHDR *fill_control_message(int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
|
||||
|
@ -1003,25 +955,6 @@ static NTSTATUS wsaErrStatus(void)
|
|||
return sock_get_ntstatus(loc_errno);
|
||||
}
|
||||
|
||||
static UINT wsaHerrno(int loc_errno)
|
||||
{
|
||||
WARN("h_errno %d.\n", loc_errno);
|
||||
|
||||
switch(loc_errno)
|
||||
{
|
||||
case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
|
||||
case TRY_AGAIN: return WSATRY_AGAIN;
|
||||
case NO_RECOVERY: return WSANO_RECOVERY;
|
||||
case NO_DATA: return WSANO_DATA;
|
||||
case ENOBUFS: return WSAENOBUFS;
|
||||
|
||||
case 0: return 0;
|
||||
default:
|
||||
WARN("Unknown h_errno %d!\n", loc_errno);
|
||||
return WSAEOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS sock_error_to_ntstatus( DWORD err )
|
||||
{
|
||||
switch (err)
|
||||
|
@ -1298,7 +1231,7 @@ static BOOL get_dont_fragment(SOCKET s, int level, BOOL *out)
|
|||
return value;
|
||||
}
|
||||
|
||||
static struct per_thread_data *get_per_thread_data(void)
|
||||
struct per_thread_data *get_per_thread_data(void)
|
||||
{
|
||||
struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
|
||||
/* lazy initialization */
|
||||
|
@ -1486,28 +1419,6 @@ static inline int do_block( int fd, int events, int timeout )
|
|||
return pfd.revents;
|
||||
}
|
||||
|
||||
int
|
||||
convert_af_w2u(int windowsaf) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
|
||||
if (ws_af_map[i][0] == windowsaf)
|
||||
return ws_af_map[i][1];
|
||||
FIXME("unhandled Windows address family %d\n", windowsaf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
convert_af_u2w(int unixaf) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ws_af_map); i++)
|
||||
if (ws_af_map[i][1] == unixaf)
|
||||
return ws_af_map[i][0];
|
||||
FIXME("unhandled UNIX address family %d\n", unixaf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
convert_socktype_w2u(int windowssocktype) {
|
||||
unsigned int i;
|
||||
|
@ -1669,19 +1580,6 @@ void WINAPI WSASetLastError(INT iError) {
|
|||
SetLastError(iError);
|
||||
}
|
||||
|
||||
static struct WS_hostent *check_buffer_he(int size)
|
||||
{
|
||||
struct per_thread_data * ptb = get_per_thread_data();
|
||||
if (ptb->he_buffer)
|
||||
{
|
||||
if (ptb->he_len >= size ) return ptb->he_buffer;
|
||||
HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
|
||||
}
|
||||
ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
|
||||
if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
|
||||
return ptb->he_buffer;
|
||||
}
|
||||
|
||||
static struct WS_servent *check_buffer_se(int size)
|
||||
{
|
||||
struct per_thread_data * ptb = get_per_thread_data();
|
||||
|
@ -5854,256 +5752,6 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* gethostbyaddr (WS2_32.51)
|
||||
*/
|
||||
struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
|
||||
{
|
||||
struct WS_hostent *retval = NULL;
|
||||
struct hostent* host;
|
||||
int unixtype = convert_af_w2u(type);
|
||||
const char *paddr = addr;
|
||||
unsigned long loopback;
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
char *extrabuf;
|
||||
int ebufsize = 1024;
|
||||
struct hostent hostentry;
|
||||
int locerr = ENOBUFS;
|
||||
#endif
|
||||
|
||||
/* convert back the magic loopback address if necessary */
|
||||
if (unixtype == AF_INET && len == 4 && !memcmp(addr, magic_loopback_addr, 4))
|
||||
{
|
||||
loopback = htonl(INADDR_LOOPBACK);
|
||||
paddr = (char*) &loopback;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
host = NULL;
|
||||
extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
|
||||
while(extrabuf) {
|
||||
int res = gethostbyaddr_r(paddr, len, unixtype,
|
||||
&hostentry, extrabuf, ebufsize, &host, &locerr);
|
||||
if (res != ERANGE) break;
|
||||
ebufsize *=2;
|
||||
extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
|
||||
}
|
||||
if (host) retval = WS_dup_he(host);
|
||||
else SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
|
||||
HeapFree(GetProcessHeap(),0,extrabuf);
|
||||
#else
|
||||
EnterCriticalSection( &csWSgetXXXbyYYY );
|
||||
host = gethostbyaddr(paddr, len, unixtype);
|
||||
if (host) retval = WS_dup_he(host);
|
||||
else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
|
||||
LeaveCriticalSection( &csWSgetXXXbyYYY );
|
||||
#endif
|
||||
TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WS_compare_routes_by_metric_asc (INTERNAL)
|
||||
*
|
||||
* Comparison function for qsort(), for sorting two routes (struct route)
|
||||
* by metric in ascending order.
|
||||
*/
|
||||
static int WS_compare_routes_by_metric_asc(const void *left, const void *right)
|
||||
{
|
||||
const struct route *a = left, *b = right;
|
||||
if (a->default_route && b->default_route)
|
||||
return a->default_route - b->default_route;
|
||||
if (a->default_route && !b->default_route)
|
||||
return -1;
|
||||
if (b->default_route && !a->default_route)
|
||||
return 1;
|
||||
return a->metric - b->metric;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WS_get_local_ips (INTERNAL)
|
||||
*
|
||||
* Returns the list of local IP addresses by going through the network
|
||||
* adapters and using the local routing table to sort the addresses
|
||||
* from highest routing priority to lowest routing priority. This
|
||||
* functionality is inferred from the description for obtaining local
|
||||
* IP addresses given in the Knowledge Base Article Q160215.
|
||||
*
|
||||
* Please note that the returned hostent is only freed when the thread
|
||||
* closes and is replaced if another hostent is requested.
|
||||
*/
|
||||
static struct WS_hostent* WS_get_local_ips( char *hostname )
|
||||
{
|
||||
int numroutes = 0, i, j, default_routes = 0;
|
||||
DWORD n;
|
||||
PIP_ADAPTER_INFO adapters = NULL, k;
|
||||
struct WS_hostent *hostlist = NULL;
|
||||
PMIB_IPFORWARDTABLE routes = NULL;
|
||||
struct route *route_addrs = NULL;
|
||||
DWORD adap_size, route_size;
|
||||
|
||||
/* Obtain the size of the adapter list and routing table, also allocate memory */
|
||||
if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
|
||||
return NULL;
|
||||
if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
return NULL;
|
||||
adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
|
||||
routes = HeapAlloc(GetProcessHeap(), 0, route_size);
|
||||
if (adapters == NULL || routes == NULL)
|
||||
goto cleanup;
|
||||
/* Obtain the adapter list and the full routing table */
|
||||
if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
|
||||
goto cleanup;
|
||||
if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
|
||||
goto cleanup;
|
||||
/* Store the interface associated with each route */
|
||||
for (n = 0; n < routes->dwNumEntries; n++)
|
||||
{
|
||||
IF_INDEX ifindex;
|
||||
DWORD ifmetric, ifdefault = 0;
|
||||
BOOL exists = FALSE;
|
||||
|
||||
/* Check if this is a default route (there may be more than one) */
|
||||
if (!routes->table[n].dwForwardDest)
|
||||
ifdefault = ++default_routes;
|
||||
else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
|
||||
continue;
|
||||
ifindex = routes->table[n].dwForwardIfIndex;
|
||||
ifmetric = routes->table[n].dwForwardMetric1;
|
||||
/* Only store the lowest valued metric for an interface */
|
||||
for (j = 0; j < numroutes; j++)
|
||||
{
|
||||
if (route_addrs[j].interface == ifindex)
|
||||
{
|
||||
if (route_addrs[j].metric > ifmetric)
|
||||
route_addrs[j].metric = ifmetric;
|
||||
exists = TRUE;
|
||||
}
|
||||
}
|
||||
if (exists)
|
||||
continue;
|
||||
route_addrs = heap_realloc(route_addrs, (numroutes+1)*sizeof(struct route));
|
||||
if (route_addrs == NULL)
|
||||
goto cleanup; /* Memory allocation error, fail gracefully */
|
||||
route_addrs[numroutes].interface = ifindex;
|
||||
route_addrs[numroutes].metric = ifmetric;
|
||||
route_addrs[numroutes].default_route = ifdefault;
|
||||
/* If no IP is found in the next step (for whatever reason)
|
||||
* then fall back to the magic loopback address.
|
||||
*/
|
||||
memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
|
||||
numroutes++;
|
||||
}
|
||||
if (numroutes == 0)
|
||||
goto cleanup; /* No routes, fall back to the Magic IP */
|
||||
/* Find the IP address associated with each found interface */
|
||||
for (i = 0; i < numroutes; i++)
|
||||
{
|
||||
for (k = adapters; k != NULL; k = k->Next)
|
||||
{
|
||||
char *ip = k->IpAddressList.IpAddress.String;
|
||||
|
||||
if (route_addrs[i].interface == k->Index)
|
||||
route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
|
||||
}
|
||||
}
|
||||
/* Allocate a hostent and enough memory for all the IPs,
|
||||
* including the NULL at the end of the list.
|
||||
*/
|
||||
hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
|
||||
if (hostlist == NULL)
|
||||
goto cleanup; /* Failed to allocate a hostent for the list of IPs */
|
||||
hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
|
||||
hostlist->h_aliases[0] = NULL; /* NULL-terminate the alias list */
|
||||
hostlist->h_addrtype = AF_INET;
|
||||
hostlist->h_length = sizeof(struct in_addr); /* = 4 */
|
||||
/* Reorder the entries before placing them in the host list. Windows expects
|
||||
* the IP list in order from highest priority to lowest (the critical thing
|
||||
* is that most applications expect the first IP to be the default route).
|
||||
*/
|
||||
if (numroutes > 1)
|
||||
qsort(route_addrs, numroutes, sizeof(struct route), WS_compare_routes_by_metric_asc);
|
||||
|
||||
for (i = 0; i < numroutes; i++)
|
||||
(*(struct in_addr *) hostlist->h_addr_list[i]) = route_addrs[i].addr;
|
||||
|
||||
/* Cleanup all allocated memory except the address list,
|
||||
* the address list is used by the calling app.
|
||||
*/
|
||||
cleanup:
|
||||
HeapFree(GetProcessHeap(), 0, route_addrs);
|
||||
HeapFree(GetProcessHeap(), 0, adapters);
|
||||
HeapFree(GetProcessHeap(), 0, routes);
|
||||
return hostlist;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* gethostbyname (WS2_32.52)
|
||||
*/
|
||||
struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
|
||||
{
|
||||
struct WS_hostent *retval = NULL;
|
||||
struct hostent* host;
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
char *extrabuf;
|
||||
int ebufsize=1024;
|
||||
struct hostent hostentry;
|
||||
int locerr = ENOBUFS;
|
||||
#endif
|
||||
char hostname[100];
|
||||
if(!num_startup) {
|
||||
SetLastError(WSANOTINITIALISED);
|
||||
return NULL;
|
||||
}
|
||||
if( gethostname( hostname, 100) == -1) {
|
||||
SetLastError(WSAENOBUFS); /* appropriate ? */
|
||||
return retval;
|
||||
}
|
||||
if( !name || !name[0]) {
|
||||
name = hostname;
|
||||
}
|
||||
/* If the hostname of the local machine is requested then return the
|
||||
* complete list of local IP addresses */
|
||||
if(strcmp(name, hostname) == 0)
|
||||
retval = WS_get_local_ips(hostname);
|
||||
/* If any other hostname was requested (or the routing table lookup failed)
|
||||
* then return the IP found by the host OS */
|
||||
if(retval == NULL)
|
||||
{
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
host = NULL;
|
||||
extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
|
||||
while(extrabuf) {
|
||||
int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
|
||||
if( res != ERANGE) break;
|
||||
ebufsize *=2;
|
||||
extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
|
||||
}
|
||||
if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
|
||||
#else
|
||||
EnterCriticalSection( &csWSgetXXXbyYYY );
|
||||
host = gethostbyname(name);
|
||||
if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
|
||||
#endif
|
||||
if (host) retval = WS_dup_he(host);
|
||||
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
|
||||
HeapFree(GetProcessHeap(),0,extrabuf);
|
||||
#else
|
||||
LeaveCriticalSection( &csWSgetXXXbyYYY );
|
||||
#endif
|
||||
}
|
||||
if (retval && retval->h_addr_list[0][0] == 127 &&
|
||||
strcmp(name, "localhost") != 0)
|
||||
{
|
||||
/* hostname != "localhost" but has loopback address. replace by our
|
||||
* special address.*/
|
||||
memcpy(retval->h_addr_list[0], magic_loopback_addr, 4);
|
||||
}
|
||||
TRACE( "%s ret %p\n", debugstr_a(name), retval );
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static const struct { int prot; const char *names[3]; } protocols[] =
|
||||
{
|
||||
{ 0, { "ip", "IP" }},
|
||||
|
@ -6303,77 +5951,6 @@ struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* gethostname (WS2_32.57)
|
||||
*/
|
||||
int WINAPI WS_gethostname(char *name, int namelen)
|
||||
{
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
TRACE("name %p, len %d\n", name, namelen);
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError(WSAEFAULT);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
if (gethostname(buf, sizeof(buf)) != 0)
|
||||
{
|
||||
SetLastError(wsaErrno());
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
TRACE("<- '%s'\n", buf);
|
||||
len = strlen(buf);
|
||||
if (len > 15)
|
||||
WARN("Windows supports NetBIOS name length up to 15 bytes!\n");
|
||||
if (namelen <= len)
|
||||
{
|
||||
SetLastError(WSAEFAULT);
|
||||
WARN("<- not enough space for hostname, required %d, got %d!\n", len + 1, namelen);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
strcpy(name, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetHostNameW (WS2_32.@)
|
||||
*/
|
||||
int WINAPI GetHostNameW(WCHAR *name, int namelen)
|
||||
{
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
TRACE("name %p, len %d\n", name, namelen);
|
||||
|
||||
if (!name)
|
||||
{
|
||||
SetLastError(WSAEFAULT);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
if (gethostname(buf, sizeof(buf)))
|
||||
{
|
||||
SetLastError(wsaErrno());
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
if ((len = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0)) > namelen)
|
||||
{
|
||||
SetLastError(WSAEFAULT);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
MultiByteToWideChar(CP_ACP, 0, buf, -1, name, namelen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------- Windows sockets extensions -- *
|
||||
* *
|
||||
* ------------------------------------------------------------------- */
|
||||
|
||||
/***********************************************************************
|
||||
* WSAEnumNetworkEvents (WS2_32.36)
|
||||
*/
|
||||
|
@ -6815,95 +6392,6 @@ static int list_dup(char** l_src, char** l_to, int item_size)
|
|||
return p - (char *)l_to;
|
||||
}
|
||||
|
||||
/* ----- hostent */
|
||||
|
||||
/* create a hostent entry
|
||||
*
|
||||
* Creates the entry with enough memory for the name, aliases
|
||||
* addresses, and the address pointers. Also copies the name
|
||||
* and sets up all the pointers.
|
||||
*
|
||||
* NOTE: The alias and address lists must be allocated with room
|
||||
* for the NULL item terminating the list. This is true even if
|
||||
* the list has no items ("aliases" and "addresses" must be
|
||||
* at least "1", a truly empty list is invalid).
|
||||
*/
|
||||
static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
|
||||
{
|
||||
struct WS_hostent *p_to;
|
||||
char *p;
|
||||
int size = (sizeof(struct WS_hostent) +
|
||||
strlen(name) + 1 +
|
||||
sizeof(char *) * aliases +
|
||||
aliases_size +
|
||||
sizeof(char *) * addresses +
|
||||
address_length * (addresses - 1)), i;
|
||||
|
||||
if (!(p_to = check_buffer_he(size))) return NULL;
|
||||
memset(p_to, 0, size);
|
||||
|
||||
/* Use the memory in the same way winsock does.
|
||||
* First set the pointer for aliases, second set the pointers for addresses.
|
||||
* Third fill the addresses indexes, fourth jump aliases names size.
|
||||
* Fifth fill the hostname.
|
||||
* NOTE: This method is valid for OS versions >= XP.
|
||||
*/
|
||||
p = (char *)(p_to + 1);
|
||||
p_to->h_aliases = (char **)p;
|
||||
p += sizeof(char *)*aliases;
|
||||
|
||||
p_to->h_addr_list = (char **)p;
|
||||
p += sizeof(char *)*addresses;
|
||||
|
||||
for (i = 0, addresses--; i < addresses; i++, p += address_length)
|
||||
p_to->h_addr_list[i] = p;
|
||||
|
||||
/* NOTE: h_aliases must be filled in manually because we don't know each string
|
||||
* size, leave these pointers NULL (already set to NULL by memset earlier).
|
||||
*/
|
||||
p += aliases_size;
|
||||
|
||||
p_to->h_name = p;
|
||||
strcpy(p, name);
|
||||
|
||||
return p_to;
|
||||
}
|
||||
|
||||
/* duplicate hostent entry
|
||||
* and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
|
||||
* Ditto for protoent and servent.
|
||||
*/
|
||||
static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
|
||||
{
|
||||
int i, addresses = 0, alias_size = 0;
|
||||
struct WS_hostent *p_to;
|
||||
char *p;
|
||||
|
||||
for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
|
||||
while (p_he->h_addr_list[addresses]) addresses++;
|
||||
|
||||
p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
|
||||
|
||||
if (!p_to) return NULL;
|
||||
p_to->h_addrtype = convert_af_u2w(p_he->h_addrtype);
|
||||
p_to->h_length = p_he->h_length;
|
||||
|
||||
for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
|
||||
memcpy(p, p_he->h_addr_list[i], p_to->h_length);
|
||||
|
||||
/* Fill the aliases after the IP data */
|
||||
for(i = 0; p_he->h_aliases[i]; i++)
|
||||
{
|
||||
p_to->h_aliases[i] = p;
|
||||
strcpy(p, p_he->h_aliases[i]);
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
|
||||
return p_to;
|
||||
}
|
||||
|
||||
/* ----- protoent */
|
||||
|
||||
static struct WS_protoent *WS_create_pe( const char *name, char **aliases, int prot )
|
||||
{
|
||||
struct WS_protoent *ret;
|
||||
|
|
|
@ -152,8 +152,15 @@
|
|||
#include "wine/unicode.h"
|
||||
#include "wine/heap.h"
|
||||
|
||||
int convert_af_u2w( int family ) DECLSPEC_HIDDEN;
|
||||
int convert_af_w2u( int family ) DECLSPEC_HIDDEN;
|
||||
#define DECLARE_CRITICAL_SECTION(cs) \
|
||||
static CRITICAL_SECTION cs; \
|
||||
static CRITICAL_SECTION_DEBUG cs##_debug = \
|
||||
{ 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
|
||||
static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
|
||||
|
||||
static const char magic_loopback_addr[] = {127, 12, 34, 56};
|
||||
|
||||
int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
|
||||
int convert_socktype_u2w( int type ) DECLSPEC_HIDDEN;
|
||||
int convert_socktype_w2u( int type ) DECLSPEC_HIDDEN;
|
||||
|
@ -164,4 +171,22 @@ const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
|
|||
|
||||
UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
|
||||
|
||||
struct per_thread_data
|
||||
{
|
||||
int opentype;
|
||||
struct WS_hostent *he_buffer;
|
||||
struct WS_servent *se_buffer;
|
||||
struct WS_protoent *pe_buffer;
|
||||
struct pollfd *fd_cache;
|
||||
unsigned int fd_count;
|
||||
int he_len;
|
||||
int se_len;
|
||||
int pe_len;
|
||||
char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */
|
||||
};
|
||||
|
||||
extern int num_startup;
|
||||
|
||||
struct per_thread_data *get_per_thread_data(void) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue