ws2_32: Move getnameinfo() to the Unix library.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-08-04 21:20:44 -05:00 committed by Alexandre Julliard
parent c1c3691bed
commit 01885acd5d
4 changed files with 142 additions and 305 deletions

View File

@ -31,49 +31,6 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY);
#define MAP_OPTION(opt) { WS_##opt, opt }
static const int ws_eai_map[][2] =
{
MAP_OPTION( EAI_AGAIN ),
MAP_OPTION( EAI_BADFLAGS ),
MAP_OPTION( EAI_FAIL ),
MAP_OPTION( EAI_FAMILY ),
MAP_OPTION( EAI_MEMORY ),
/* Note: EAI_NODATA is deprecated, but still used by Windows and Linux. We map
* the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
#ifdef EAI_NODATA
MAP_OPTION( EAI_NODATA ),
#endif
#ifdef EAI_NONAME
{ WS_EAI_NODATA, EAI_NONAME },
#endif
MAP_OPTION( EAI_SERVICE ),
MAP_OPTION( EAI_SOCKTYPE ),
{ 0, 0 }
};
int convert_eai_u2w( int unixret )
{
int i;
if (!unixret) return 0;
for (i = 0; ws_eai_map[i][0]; i++)
{
if (ws_eai_map[i][1] == unixret)
return ws_eai_map[i][0];
}
if (unixret == EAI_SYSTEM)
/* There are broken versions of glibc which return EAI_SYSTEM
* and set errno to 0 instead of returning EAI_NONAME. */
return errno ? sock_get_error( errno ) : WS_EAI_NONAME;
FIXME("Unhandled unix EAI_xxx ret %d\n", unixret);
return unixret;
}
static char *get_fqdn(void)
{
char *ret;
@ -592,60 +549,16 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
}
static const int ws_niflag_map[][2] =
{
MAP_OPTION( NI_NOFQDN ),
MAP_OPTION( NI_NUMERICHOST ),
MAP_OPTION( NI_NAMEREQD ),
MAP_OPTION( NI_NUMERICSERV ),
MAP_OPTION( NI_DGRAM ),
};
static int convert_niflag_w2u( int winflags )
{
unsigned int i;
int unixflags = 0;
for (i = 0; i < ARRAY_SIZE(ws_niflag_map); i++)
{
if (ws_niflag_map[i][0] & winflags)
{
unixflags |= ws_niflag_map[i][1];
winflags &= ~ws_niflag_map[i][0];
}
}
if (winflags)
FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags);
return unixflags;
}
/***********************************************************************
* getnameinfo (ws2_32.@)
*/
int WINAPI WS_getnameinfo( const SOCKADDR *addr, WS_socklen_t addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags )
{
#ifdef HAVE_GETNAMEINFO
int ret;
union generic_unix_sockaddr uaddr;
unsigned int uaddr_len;
TRACE( "addr %s, addr_len %d, host %p, host_len %u, serv %p, serv_len %d, flags %#x\n",
debugstr_sockaddr(addr), addr_len, host, host_len, serv, serv_len, flags );
uaddr_len = ws_sockaddr_ws2u( addr, addr_len, &uaddr );
if (!uaddr_len)
{
SetLastError( WSAEFAULT );
return WSA_NOT_ENOUGH_MEMORY;
}
ret = getnameinfo( &uaddr.addr, uaddr_len, host, host_len, serv, serv_len, convert_niflag_w2u(flags) );
return convert_eai_u2w( ret );
#else
FIXME( "getnameinfo() failed, not found during buildtime.\n" );
return EAI_FAIL;
#endif
return unix_funcs->getnameinfo( addr, addr_len, host, host_len, serv, serv_len, flags );
}

View File

@ -31,11 +31,6 @@
#include "ws2_32_private.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
# define sipx_network sipx_addr.x_net
# define sipx_node sipx_addr.x_host.c_host
#endif /* __FreeBSD__ */
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
@ -428,76 +423,6 @@ static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* function prototypes */
static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size);
#define MAP_OPTION(opt) { WS_##opt, opt }
UINT sock_get_error( int err )
{
switch(err)
{
case EINTR: return WSAEINTR;
case EPERM:
case EACCES: return WSAEACCES;
case EFAULT: return WSAEFAULT;
case EINVAL: return WSAEINVAL;
case EMFILE: return WSAEMFILE;
case EINPROGRESS:
case EWOULDBLOCK: return WSAEWOULDBLOCK;
case EALREADY: return WSAEALREADY;
case EBADF:
case ENOTSOCK: return WSAENOTSOCK;
case EDESTADDRREQ: return WSAEDESTADDRREQ;
case EMSGSIZE: return WSAEMSGSIZE;
case EPROTOTYPE: return WSAEPROTOTYPE;
case ENOPROTOOPT: return WSAENOPROTOOPT;
case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
case EOPNOTSUPP: return WSAEOPNOTSUPP;
case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
case EADDRINUSE: return WSAEADDRINUSE;
case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
case ENETDOWN: return WSAENETDOWN;
case ENETUNREACH: return WSAENETUNREACH;
case ENETRESET: return WSAENETRESET;
case ECONNABORTED: return WSAECONNABORTED;
case EPIPE:
case ECONNRESET: return WSAECONNRESET;
case ENOBUFS: return WSAENOBUFS;
case EISCONN: return WSAEISCONN;
case ENOTCONN: return WSAENOTCONN;
case ESHUTDOWN: return WSAESHUTDOWN;
case ETOOMANYREFS: return WSAETOOMANYREFS;
case ETIMEDOUT: return WSAETIMEDOUT;
case ECONNREFUSED: return WSAECONNREFUSED;
case ELOOP: return WSAELOOP;
case ENAMETOOLONG: return WSAENAMETOOLONG;
case EHOSTDOWN: return WSAEHOSTDOWN;
case EHOSTUNREACH: return WSAEHOSTUNREACH;
case ENOTEMPTY: return WSAENOTEMPTY;
#ifdef EPROCLIM
case EPROCLIM: return WSAEPROCLIM;
#endif
#ifdef EUSERS
case EUSERS: return WSAEUSERS;
#endif
#ifdef EDQUOT
case EDQUOT: return WSAEDQUOT;
#endif
#ifdef ESTALE
case ESTALE: return WSAESTALE;
#endif
#ifdef EREMOTE
case EREMOTE: return WSAEREMOTE;
#endif
/* just in case we ever get here and there are no problems */
case 0: return 0;
default:
WARN("Unknown errno %d!\n", err);
return WSAEOPNOTSUPP;
}
}
static DWORD NtStatusToWSAError( NTSTATUS status )
{
static const struct
@ -705,136 +630,6 @@ void WINAPI WSASetLastError(INT iError) {
SetLastError(iError);
}
/**********************************************************************/
/* Returns the length of the converted address if successful, 0 if it was too
* small to start with or unknown family or invalid address buffer.
*/
unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *wsaddr, int wsaddrlen,
union generic_unix_sockaddr *uaddr )
{
unsigned int uaddrlen = 0;
if (!wsaddr)
return 0;
switch (wsaddr->sa_family)
{
#ifdef HAS_IPX
case WS_AF_IPX:
{
const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
struct sockaddr_ipx* uipx = (struct sockaddr_ipx *)uaddr;
if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
return 0;
uaddrlen = sizeof(struct sockaddr_ipx);
memset( uaddr, 0, uaddrlen );
uipx->sipx_family=AF_IPX;
uipx->sipx_port=wsipx->sa_socket;
/* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
* in one go
*/
memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
#ifdef IPX_FRAME_NONE
uipx->sipx_type=IPX_FRAME_NONE;
#endif
break;
}
#endif
case WS_AF_INET6: {
struct sockaddr_in6* uin6 = (struct sockaddr_in6 *)uaddr;
const struct WS_sockaddr_in6* win6 = (const struct WS_sockaddr_in6*)wsaddr;
/* Note: Windows has 2 versions of the sockaddr_in6 struct, one with
* scope_id, one without.
*/
if (wsaddrlen >= sizeof(struct WS_sockaddr_in6)) {
uaddrlen = sizeof(struct sockaddr_in6);
memset( uaddr, 0, uaddrlen );
uin6->sin6_family = AF_INET6;
uin6->sin6_port = win6->sin6_port;
uin6->sin6_flowinfo = win6->sin6_flowinfo;
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
uin6->sin6_scope_id = win6->sin6_scope_id;
#endif
memcpy(&uin6->sin6_addr,&win6->sin6_addr,16); /* 16 bytes = 128 address bits */
break;
}
FIXME("bad size %d for WS_sockaddr_in6\n",wsaddrlen);
return 0;
}
case WS_AF_INET: {
struct sockaddr_in* uin = (struct sockaddr_in *)uaddr;
const struct WS_sockaddr_in* win = (const struct WS_sockaddr_in*)wsaddr;
if (wsaddrlen<sizeof(struct WS_sockaddr_in))
return 0;
uaddrlen = sizeof(struct sockaddr_in);
memset( uaddr, 0, uaddrlen );
uin->sin_family = AF_INET;
uin->sin_port = win->sin_port;
memcpy(&uin->sin_addr,&win->sin_addr,4); /* 4 bytes = 32 address bits */
break;
}
#ifdef HAS_IRDA
case WS_AF_IRDA: {
struct sockaddr_irda *uin = (struct sockaddr_irda *)uaddr;
const SOCKADDR_IRDA *win = (const SOCKADDR_IRDA *)wsaddr;
if (wsaddrlen < sizeof(SOCKADDR_IRDA))
return 0;
uaddrlen = sizeof(struct sockaddr_irda);
memset( uaddr, 0, uaddrlen );
uin->sir_family = AF_IRDA;
if (!strncmp( win->irdaServiceName, "LSAP-SEL", strlen( "LSAP-SEL" ) ))
{
unsigned int lsap_sel = 0;
sscanf( win->irdaServiceName, "LSAP-SEL%u", &lsap_sel );
uin->sir_lsap_sel = lsap_sel;
}
else
{
uin->sir_lsap_sel = LSAP_ANY;
memcpy( uin->sir_name, win->irdaServiceName, 25 );
}
memcpy( &uin->sir_addr, win->irdaDeviceID, sizeof(uin->sir_addr) );
break;
}
#endif
case WS_AF_UNSPEC: {
/* Try to determine the needed space by the passed windows sockaddr space */
switch (wsaddrlen) {
default: /* likely an ipv4 address */
case sizeof(struct WS_sockaddr_in):
uaddrlen = sizeof(struct sockaddr_in);
break;
#ifdef HAS_IPX
case sizeof(struct WS_sockaddr_ipx):
uaddrlen = sizeof(struct sockaddr_ipx);
break;
#endif
#ifdef HAS_IRDA
case sizeof(SOCKADDR_IRDA):
uaddrlen = sizeof(struct sockaddr_irda);
break;
#endif
case sizeof(struct WS_sockaddr_in6):
case sizeof(struct WS_sockaddr_in6_old):
uaddrlen = sizeof(struct sockaddr_in6);
break;
}
memset( uaddr, 0, uaddrlen );
break;
}
default:
FIXME("Unknown address family %d, return NULL.\n", wsaddr->sa_family);
return 0;
}
return uaddrlen;
}
static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo)
{

View File

@ -98,6 +98,15 @@ static const int addrinfo_flag_map[][2] =
MAP( AI_ADDRCONFIG ),
};
static const int nameinfo_flag_map[][2] =
{
MAP( NI_DGRAM ),
MAP( NI_NAMEREQD ),
MAP( NI_NOFQDN ),
MAP( NI_NUMERICHOST ),
MAP( NI_NUMERICSERV ),
};
static const int family_map[][2] =
{
MAP( AF_UNSPEC ),
@ -170,6 +179,25 @@ static int addrinfo_flags_to_unix( int flags )
return unix_flags;
}
static int nameinfo_flags_to_unix( int flags )
{
int unix_flags = 0;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(nameinfo_flag_map); ++i)
{
if (flags & nameinfo_flag_map[i][0])
{
unix_flags |= nameinfo_flag_map[i][1];
flags &= ~nameinfo_flag_map[i][0];
}
}
if (flags)
FIXME( "unhandled flags %#x\n", flags );
return unix_flags;
}
static int family_from_unix( int family )
{
unsigned int i;
@ -471,6 +499,103 @@ static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_socka
}
}
static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrlen, union unix_sockaddr *uaddr )
{
memset( uaddr, 0, sizeof(*uaddr) );
switch (wsaddr->sa_family)
{
case WS_AF_INET:
{
struct WS_sockaddr_in win = {0};
if (wsaddrlen < sizeof(win)) return 0;
memcpy( &win, wsaddr, sizeof(win) );
uaddr->in.sin_family = AF_INET;
uaddr->in.sin_port = win.sin_port;
memcpy( &uaddr->in.sin_addr, &win.sin_addr, sizeof(win.sin_addr) );
return sizeof(uaddr->in);
}
case WS_AF_INET6:
{
struct WS_sockaddr_in6 win = {0};
if (wsaddrlen < sizeof(win)) return 0;
memcpy( &win, wsaddr, sizeof(win) );
uaddr->in6.sin6_family = AF_INET6;
uaddr->in6.sin6_port = win.sin6_port;
uaddr->in6.sin6_flowinfo = win.sin6_flowinfo;
memcpy( &uaddr->in6.sin6_addr, &win.sin6_addr, sizeof(win.sin6_addr) );
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
uaddr->in6.sin6_scope_id = win.sin6_scope_id;
#endif
return sizeof(uaddr->in6);
}
#ifdef HAS_IPX
case WS_AF_IPX:
{
struct WS_sockaddr_ipx win = {0};
if (wsaddrlen < sizeof(win)) return 0;
memcpy( &win, wsaddr, sizeof(win) );
uaddr->ipx.sipx_family = AF_IPX;
memcpy( &uaddr->ipx.sipx_network, win.sa_netnum, sizeof(win.sa_netnum) );
memcpy( &uaddr->ipx.sipx_node, win.sa_nodenum, sizeof(win.sa_nodenum) );
uaddr->ipx.sipx_port = win.sa_socket;
return sizeof(uaddr->ipx);
}
#endif
#ifdef HAS_IRDA
case WS_AF_IRDA:
{
SOCKADDR_IRDA win = {0};
unsigned int lsap_sel;
if (wsaddrlen < sizeof(win)) return 0;
memcpy( &win, wsaddr, sizeof(win) );
uaddr->irda.sir_family = AF_IRDA;
if (sscanf( win.irdaServiceName, "LSAP-SEL%u", &lsap_sel ) == 1)
uaddr->irda.sir_lsap_sel = lsap_sel;
else
{
uaddr->irda.sir_lsap_sel = LSAP_ANY;
memcpy( uaddr->irda.sir_name, win.irdaServiceName, sizeof(win.irdaServiceName) );
}
memcpy( &uaddr->irda.sir_addr, win.irdaDeviceID, sizeof(win.irdaDeviceID) );
return sizeof(uaddr->irda);
}
#endif
case WS_AF_UNSPEC:
switch (wsaddrlen)
{
default: /* likely an ipv4 address */
case sizeof(struct WS_sockaddr_in):
return sizeof(uaddr->in);
#ifdef HAS_IPX
case sizeof(struct WS_sockaddr_ipx):
return sizeof(uaddr->ipx);
#endif
#ifdef HAS_IRDA
case sizeof(SOCKADDR_IRDA):
return sizeof(uaddr->irda);
#endif
case sizeof(struct WS_sockaddr_in6):
return sizeof(uaddr->in6);
}
default:
FIXME( "unknown address family %u\n", wsaddr->sa_family );
return 0;
}
}
static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
{
const struct WS_addrinfo *cursor = list;
@ -798,12 +923,26 @@ static int CDECL unix_gethostname( char *name, int len )
}
static int CDECL unix_getnameinfo( const struct WS(sockaddr) *addr, int addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags )
{
union unix_sockaddr unix_addr;
socklen_t unix_addr_len;
unix_addr_len = sockaddr_to_unix( addr, addr_len, &unix_addr );
return addrinfo_err_from_unix( getnameinfo( &unix_addr.addr, unix_addr_len, host, host_len,
serv, serv_len, nameinfo_flags_to_unix( flags ) ) );
}
static const struct unix_funcs funcs =
{
unix_getaddrinfo,
unix_gethostbyaddr,
unix_gethostbyname,
unix_gethostname,
unix_getnameinfo,
};
NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )

View File

@ -165,20 +165,8 @@
static const char magic_loopback_addr[] = {127, 12, 34, 56};
union generic_unix_sockaddr
{
struct sockaddr addr;
char data[128]; /* should be big enough for all families */
};
int convert_eai_u2w( int ret ) DECLSPEC_HIDDEN;
unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *win_addr, int win_addr_len,
union generic_unix_sockaddr *unix_addr ) DECLSPEC_HIDDEN;
const char *debugstr_sockaddr( const struct WS_sockaddr *addr ) DECLSPEC_HIDDEN;
UINT sock_get_error( int err ) DECLSPEC_HIDDEN;
struct per_thread_data
{
HANDLE sync_event; /* event to wait on for synchronous ioctls */
@ -204,6 +192,8 @@ struct unix_funcs
struct WS(hostent) *host, unsigned int *size );
int (CDECL *gethostbyname)( const char *name, struct WS(hostent) *host, unsigned int *size );
int (CDECL *gethostname)( char *name, int len );
int (CDECL *getnameinfo)( const struct WS(sockaddr) *addr, int addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags );
};
extern const struct unix_funcs *unix_funcs;