Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 39 +--------------- server/sock.c | 105 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 102 insertions(+), 42 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 36215cc6eff..d7802cc9cd8 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -7601,41 +7601,6 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, /* convert the socket family, type and protocol */ unixaf = convert_af_w2u(af); unixtype = convert_socktype_w2u(type); - protocol = convert_proto_w2u(protocol); - - /* filter invalid parameters */ - if (protocol < 0) - { - /* the type could not be converted */ - if (type && unixtype < 0) - { - err = WSAESOCKTNOSUPPORT; - goto done; - } - - err = WSAEPROTONOSUPPORT; - goto done; - } - if (unixaf < 0) - { - /* both family and protocol can't be invalid */ - if (protocol <= 0) - { - err = WSAEINVAL; - goto done; - } - - /* family could not be converted and neither socket type */ - if (unixtype < 0 && af >= 0) - { - - err = WSAESOCKTNOSUPPORT; - goto done; - } - - err = WSAEAFNOSUPPORT; - goto done; - }
RtlInitUnicodeString(&string, afdW); InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL); @@ -7647,8 +7612,8 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, return INVALID_SOCKET; }
- create_params.family = unixaf; - create_params.type = unixtype; + create_params.family = af; + create_params.type = type; create_params.protocol = protocol; create_params.flags = flags & ~(WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, diff --git a/server/sock.c b/server/sock.c index 3bc4780f943..f0227c59067 100644 --- a/server/sock.c +++ b/server/sock.c @@ -30,6 +30,9 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif #ifdef HAVE_POLL_H # include <poll.h> #endif @@ -51,6 +54,29 @@ # include <linux/rtnetlink.h> #endif
+#ifdef HAVE_NETIPX_IPX_H +# include <netipx/ipx.h> +#elif defined(HAVE_LINUX_IPX_H) +# ifdef HAVE_ASM_TYPES_H +# include <asm/types.h> +# endif +# ifdef HAVE_LINUX_TYPES_H +# include <linux/types.h> +# endif +# include <linux/ipx.h> +#endif +#if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS) +# define HAS_IPX +#endif + +#ifdef HAVE_LINUX_IRDA_H +# ifdef HAVE_LINUX_TYPES_H +# include <linux/types.h> +# endif +# include <linux/irda.h> +# define HAS_IRDA +#endif + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -58,6 +84,7 @@ #include "winerror.h" #define USE_WS_PREFIX #include "winsock2.h" +#include "wsipx.h" #include "wine/afd.h"
#include "process.h" @@ -638,12 +665,80 @@ static struct sock *create_socket(void) return sock; }
+static int get_unix_family( int family ) +{ + switch (family) + { + case WS_AF_INET: return AF_INET; + case WS_AF_INET6: return AF_INET6; +#ifdef HAS_IPX + case WS_AF_IPX: return AF_IPX; +#endif +#ifdef AF_IRDA + case WS_AF_IRDA: return AF_IRDA; +#endif + case WS_AF_UNSPEC: return AF_UNSPEC; + default: return -1; + } +} + +static int get_unix_type( int type ) +{ + switch (type) + { + case WS_SOCK_DGRAM: return SOCK_DGRAM; + case WS_SOCK_RAW: return SOCK_RAW; + case WS_SOCK_STREAM: return SOCK_STREAM; + default: return -1; + } +} + +static int get_unix_protocol( int protocol ) +{ + if (protocol >= WS_NSPROTO_IPX && protocol <= WS_NSPROTO_IPX + 255) + return protocol; + + switch (protocol) + { + case WS_IPPROTO_ICMP: return IPPROTO_ICMP; + case WS_IPPROTO_IGMP: return IPPROTO_IGMP; + case WS_IPPROTO_IP: return IPPROTO_IP; + case WS_IPPROTO_IPIP: return IPPROTO_IPIP; + case WS_IPPROTO_IPV6: return IPPROTO_IPV6; + case WS_IPPROTO_RAW: return IPPROTO_RAW; + case WS_IPPROTO_TCP: return IPPROTO_TCP; + case WS_IPPROTO_UDP: return IPPROTO_UDP; + default: return -1; + } +} + static int init_socket( struct sock *sock, int family, int type, int protocol, unsigned int flags ) { unsigned int options = 0; - int sockfd; + int sockfd, unix_type, unix_family, unix_protocol; + + unix_family = get_unix_family( family ); + unix_type = get_unix_type( type ); + unix_protocol = get_unix_protocol( protocol ); + + if (unix_protocol < 0) + { + if (type && unix_type < 0) + set_win32_error( WSAESOCKTNOSUPPORT ); + else + set_win32_error( WSAEPROTONOSUPPORT ); + return -1; + } + if (unix_family < 0) + { + if (family >= 0 && unix_type < 0) + set_win32_error( WSAESOCKTNOSUPPORT ); + else + set_win32_error( WSAEAFNOSUPPORT ); + return -1; + }
- sockfd = socket( family, type, protocol ); + sockfd = socket( unix_family, unix_type, unix_protocol ); if (sockfd == -1) { if (errno == EINVAL) set_win32_error( WSAESOCKTNOSUPPORT ); @@ -653,9 +748,9 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->flags = flags; - sock->proto = protocol; - sock->type = type; - sock->family = family; + sock->proto = unix_protocol; + sock->type = unix_type; + sock->family = unix_family;
if (sock->fd) {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: remove diagnostic messages
dlls/ws2_32/socket.c | 39 -------------------------- server/sock.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 39 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index d7802cc9cd8..a187d2de8e7 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -7519,7 +7519,6 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, HANDLE handle; SOCKET ret; DWORD err; - int unixaf, unixtype, ipxptype = -1;
/* FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo, @@ -7590,18 +7589,6 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, } }
- /* - Windows has an extension to the IPX protocol that allows one to create sockets - and set the IPX packet type at the same time, to do that a caller will use - a protocol like NSPROTO_IPX + <PACKET TYPE> - */ - if (IS_IPX_PROTO(protocol)) - ipxptype = protocol - WS_NSPROTO_IPX; - - /* convert the socket family, type and protocol */ - unixaf = convert_af_w2u(af); - unixtype = convert_socktype_w2u(type); - RtlInitUnicodeString(&string, afdW); InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL); if ((status = NtOpenFile(&handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr, @@ -7636,32 +7623,6 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, ret = HANDLE2SOCKET(handle); TRACE("\tcreated %04lx\n", ret );
- if (ipxptype > 0) - set_ipx_packettype(ret, ipxptype); - - if (unixaf == AF_INET || unixaf == AF_INET6) - { - /* ensure IP_DONTFRAGMENT is disabled for SOCK_DGRAM and SOCK_RAW, enabled for SOCK_STREAM */ - if (unixtype == SOCK_DGRAM || unixtype == SOCK_RAW) /* in Linux the global default can be enabled */ - set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, FALSE); - else if (unixtype == SOCK_STREAM) - set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, TRUE); - } - -#ifdef IPV6_V6ONLY - if (unixaf == AF_INET6) - { - int fd = get_sock_fd(ret, 0, NULL); - if (fd != -1) - { - /* IPV6_V6ONLY is set by default on Windows */ - int enable = 1; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable))) - WARN("\tsetting IPV6_V6ONLY failed - errno = %i\n", errno); - release_sock_fd(ret, fd); - } - } -#endif if (!socket_list_add(ret)) { CloseHandle(handle); diff --git a/server/sock.c b/server/sock.c index f0227c59067..52e85b1e518 100644 --- a/server/sock.c +++ b/server/sock.c @@ -712,6 +712,36 @@ static int get_unix_protocol( int protocol ) } }
+static void set_dont_fragment( int fd, int level, int value ) +{ + int optname; + + if (level == IPPROTO_IP) + { +#ifdef IP_DONTFRAG + optname = IP_DONTFRAG; +#elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT) + optname = IP_MTU_DISCOVER; + value = value ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; +#else + return; +#endif + } + else + { +#ifdef IPV6_DONTFRAG + optname = IPV6_DONTFRAG; +#elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT) + optname = IPV6_MTU_DISCOVER; + value = value ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_DONT; +#else + return; +#endif + } + + setsockopt( fd, level, optname, &value, sizeof(value) ); +} + static int init_socket( struct sock *sock, int family, int type, int protocol, unsigned int flags ) { unsigned int options = 0; @@ -746,6 +776,41 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u return -1; } fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ + + if (family == WS_AF_IPX && protocol >= WS_NSPROTO_IPX && protocol <= WS_NSPROTO_IPX + 255) + { +#ifdef HAS_IPX + int ipx_type = protocol - WS_NSPROTO_IPX; + +#ifdef SOL_IPX + setsockopt( sockfd, SOL_IPX, IPX_TYPE, &ipx_type, sizeof(ipx_type) ); +#else + struct ipx val; + /* Should we retrieve val using a getsockopt call and then + * set the modified one? */ + val.ipx_pt = ipx_type; + setsockopt( sockfd, 0, SO_DEFAULT_HEADERS, &val, sizeof(val) ); +#endif +#endif + } + + if (unix_family == AF_INET || unix_family == AF_INET6) + { + /* ensure IP_DONTFRAGMENT is disabled for SOCK_DGRAM and SOCK_RAW, enabled for SOCK_STREAM */ + if (unix_type == SOCK_DGRAM || unix_type == SOCK_RAW) /* in Linux the global default can be enabled */ + set_dont_fragment( sockfd, unix_family == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, FALSE ); + else if (unix_type == SOCK_STREAM) + set_dont_fragment( sockfd, unix_family == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, TRUE ); + } + +#ifdef IPV6_V6ONLY + if (unix_family == AF_INET6) + { + static const int enable = 1; + setsockopt( sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable) ); + } +#endif + sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->flags = flags; sock->proto = unix_protocol;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 6 +++--- server/sock.c | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index a187d2de8e7..bc61b56667b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2306,9 +2306,9 @@ static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, i status = wine_server_call( req ); if (!status) { - address_family = convert_af_u2w(reply->family); - socket_type = convert_socktype_u2w(reply->type); - protocol = convert_proto_u2w(reply->protocol); + address_family = reply->family; + socket_type = reply->type; + protocol = reply->protocol; } } SERVER_END_REQ; diff --git a/server/sock.c b/server/sock.c index 52e85b1e518..4bafe35b890 100644 --- a/server/sock.c +++ b/server/sock.c @@ -456,7 +456,7 @@ static void sock_poll_event( struct fd *fd, int event ) else { /* normal data flow */ - if ( sock->type == SOCK_STREAM && ( event & POLLIN ) ) + if (sock->type == WS_SOCK_STREAM && (event & POLLIN)) { char dummy; int nr; @@ -546,8 +546,8 @@ static int sock_get_poll_events( struct fd *fd ) else if (smask & FD_READ || (sock->state & FD_WINE_LISTENING && mask & FD_ACCEPT)) ev |= POLLIN | POLLPRI; /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */ - else if ( sock->type == SOCK_STREAM && sock->state & FD_READ && mask & FD_CLOSE && - !(sock->hmask & FD_READ) ) + else if (sock->type == WS_SOCK_STREAM && (sock->state & FD_READ) && (mask & FD_CLOSE) && + !(sock->hmask & FD_READ)) ev |= POLLIN;
if (async_queued( &sock->write_q )) @@ -813,9 +813,9 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u
sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->flags = flags; - sock->proto = unix_protocol; - sock->type = unix_type; - sock->family = unix_family; + sock->proto = protocol; + sock->type = type; + sock->family = family;
if (sock->fd) { @@ -1540,7 +1540,7 @@ DECL_HANDLER(enable_socket_event) sock->hmask &= ~req->mask; sock->state |= req->sstate; sock->state &= ~req->cstate; - if ( sock->type != SOCK_STREAM ) sock->state &= ~STREAM_FLAG_MASK; + if (sock->type != WS_SOCK_STREAM) sock->state &= ~STREAM_FLAG_MASK;
sock_reselect( sock );
These are already done in accept_socket() and accept_into_socket() respectively.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/sock.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 4bafe35b890..f165e86b129 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1427,7 +1427,6 @@ DECL_HANDLER(accept_socket) { reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->attributes ); sock->wparam = reply->handle; /* wparam for message is the socket handle */ - sock_reselect( sock ); release_object( &sock->obj ); } } @@ -1450,10 +1449,7 @@ DECL_HANDLER(accept_into_socket) }
if (accept_into_socket( sock, acceptsock )) - { acceptsock->wparam = req->ahandle; /* wparam for message is the socket handle */ - sock_reselect( acceptsock ); - } release_object( acceptsock ); release_object( sock ); }