[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