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 (wsaddrlensipx_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 (wsaddrlensin_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;