[PATCH 2/6] ws2_32: Move getnameinfo() to the Unix library.
Zebediah Figura
zfigura at codeweavers.com
Wed Aug 4 21:20:44 CDT 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/ws2_32/protocol.c | 89 +--------------
dlls/ws2_32/socket.c | 205 -----------------------------------
dlls/ws2_32/unixlib.c | 139 ++++++++++++++++++++++++
dlls/ws2_32/ws2_32_private.h | 14 +--
4 files changed, 142 insertions(+), 305 deletions(-)
diff --git a/dlls/ws2_32/protocol.c b/dlls/ws2_32/protocol.c
index 48e7e062d7f..8b39d5c3274 100644
--- a/dlls/ws2_32/protocol.c
+++ b/dlls/ws2_32/protocol.c
@@ -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 );
}
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index b7c1571b8b6..ca95a1e0321 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -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)
{
diff --git a/dlls/ws2_32/unixlib.c b/dlls/ws2_32/unixlib.c
index cde73198c16..240389aeeaa 100644
--- a/dlls/ws2_32/unixlib.c
+++ b/dlls/ws2_32/unixlib.c
@@ -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 )
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
index 973f24a10a9..923d92a58a5 100644
--- a/dlls/ws2_32/ws2_32_private.h
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -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;
--
2.32.0
More information about the wine-devel
mailing list