Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This is inspired by Jacek's work on the console device. The idea is, similarly, to replace most direct server calls with ioctls.
It may also make sense to move the socket ioctls (as well as send/recv) handled in the client to ntdll.so, in the event that they can't be moved to the server due to performance concerns. In that case they would be handled much like cdrom/serial/tape ioctls. This would allow us to move all unix I/O out of ws2_32, as well as get rid of some of the effectively duplicated code dealing with overlapped I/O.
server/directory.c | 6 ++++- server/file.h | 1 + server/sock.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/server/directory.c b/server/directory.c index 198fc48ece2..c66d10b1928 100644 --- a/server/directory.c +++ b/server/directory.c @@ -373,10 +373,12 @@ void init_directories(void) static const WCHAR mailslotW[] = {'M','a','i','l','S','l','o','t'}; static const WCHAR condrvW[] = {'C','o','n','D','r','v'}; static const WCHAR nullW[] = {'N','u','l','l'}; + static const WCHAR afdW[] = {'A','f','d'}; static const struct unicode_str named_pipe_str = {named_pipeW, sizeof(named_pipeW)}; static const struct unicode_str mailslot_str = {mailslotW, sizeof(mailslotW)}; static const struct unicode_str condrv_str = {condrvW, sizeof(condrvW)}; static const struct unicode_str null_str = {nullW, sizeof(nullW)}; + static const struct unicode_str afd_str = {afdW, sizeof(afdW)};
/* events */ static const WCHAR event_low_memW[] = {'L','o','w','M','e','m','o','r','y','C','o','n','d','i','t','i','o','n'}; @@ -404,7 +406,7 @@ void init_directories(void) struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel; struct object *link_dosdev, *link_global, *link_nul, *link_pipe, *link_mailslot; struct object *link_conin, *link_conout, *link_con; - struct object *named_pipe_device, *mailslot_device, *null_device, *user_data_mapping, *console_device; + struct object *named_pipe_device, *mailslot_device, *null_device, *user_data_mapping, *console_device, *socket_device; struct keyed_event *keyed_event; unsigned int i;
@@ -422,11 +424,13 @@ void init_directories(void) named_pipe_device = create_named_pipe_device( &dir_device->obj, &named_pipe_str ); mailslot_device = create_mailslot_device( &dir_device->obj, &mailslot_str ); console_device = create_console_device( &dir_device->obj, &condrv_str ); + socket_device = create_socket_device( &dir_device->obj, &afd_str ); null_device = create_unix_device( &dir_device->obj, &null_str, "/dev/null" ); make_object_static( named_pipe_device ); make_object_static( mailslot_device ); make_object_static( null_device ); make_object_static( console_device ); + make_object_static( socket_device );
/* sessions */ create_session( 0 ); diff --git a/server/file.h b/server/file.h index b02c9fe6037..5fb4e5614b9 100644 --- a/server/file.h +++ b/server/file.h @@ -179,6 +179,7 @@ extern struct object *create_user_data_mapping( struct object *root, const struc extern struct object *create_named_pipe_device( struct object *root, const struct unicode_str *name ); extern struct object *create_mailslot_device( struct object *root, const struct unicode_str *name ); extern struct object *create_console_device( struct object *root, const struct unicode_str *name ); +extern struct object *create_socket_device( struct object *root, const struct unicode_str *name ); extern struct object *create_unix_device( struct object *root, const struct unicode_str *name, const char *unix_path );
diff --git a/server/sock.c b/server/sock.c index 1a53ce4b091..115448574ee 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1164,6 +1164,64 @@ static void sock_release_ifchange( struct sock *sock ) } }
+static struct object_type *socket_device_get_type( struct object *obj ); +static void socket_device_dump( struct object *obj, int verbose ); +static struct object *socket_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr ); +static struct object *socket_device_open_file( struct object *obj, unsigned int access, + unsigned int sharing, unsigned int options ); + +static const struct object_ops socket_device_ops = +{ + sizeof(struct ifchange), /* size */ + socket_device_dump, /* dump */ + socket_device_get_type, /* get_type */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + no_satisfied, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + default_fd_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + socket_device_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + socket_device_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + no_destroy /* destroy */ +}; + +static struct object_type *socket_device_get_type( struct object *obj ) +{ + static const WCHAR name[] = {'D','e','v','i','c','e'}; + static const struct unicode_str str = { name, sizeof(name) }; + return get_object_type( &str ); +} + +static void socket_device_dump( struct object *obj, int verbose ) +{ + fputs( "Socket device\n", stderr ); +} + +static struct object *socket_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr ) +{ + return NULL; +} + +static struct object *socket_device_open_file( struct object *obj, unsigned int access, + unsigned int sharing, unsigned int options ) +{ + set_error( STATUS_NOT_IMPLEMENTED ); + return NULL; +} + +struct object *create_socket_device( struct object *root, const struct unicode_str *name ) +{ + return create_named_object( root, &socket_device_ops, name, 0, NULL ); +} + /* create a socket */ DECL_HANDLER(create_socket) {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This patch, together with the next, creates a pseudo-fd object and subsequently replaces it with a newly created anonymous unix-based fd object. This is done on the model of accept_into_socket().
server/sock.c | 63 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 23 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 115448574ee..0448519df2a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -542,6 +542,8 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
assert( sock->obj.ops == &sock_ops );
+ if (get_unix_fd( fd ) == -1) return 0; + switch(code) { case WS_SIO_ADDRESS_LIST_CHANGE: @@ -631,14 +633,19 @@ static void sock_destroy( struct object *obj ) } }
-static void init_sock(struct sock *sock) +static struct sock *create_socket(void) { - sock->state = 0; + struct sock *sock; + + if (!(sock = alloc_object( &sock_ops ))) return NULL; + sock->fd = NULL; + sock->state = 0; sock->mask = 0; sock->hmask = 0; sock->pmask = 0; sock->polling = 0; sock->flags = 0; + sock->proto = 0; sock->type = 0; sock->family = 0; sock->event = NULL; @@ -652,12 +659,11 @@ static void init_sock(struct sock *sock) init_async_queue( &sock->write_q ); init_async_queue( &sock->ifchange_q ); memset( sock->errors, 0, sizeof(sock->errors) ); + return sock; }
-/* create a new and unconnected socket */ -static struct object *create_socket( int family, int type, int protocol, unsigned int flags ) +static int init_socket( struct sock *sock, int family, int type, int protocol, unsigned int flags ) { - struct sock *sock; int sockfd;
sockfd = socket( family, type, protocol ); @@ -665,15 +671,9 @@ static struct object *create_socket( int family, int type, int protocol, unsigne { if (errno == EINVAL) set_win32_error( WSAESOCKTNOSUPPORT ); else set_win32_error( sock_get_error( errno )); - return NULL; + return -1; } fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ - if (!(sock = alloc_object( &sock_ops ))) - { - close( sockfd ); - return NULL; - } - init_sock( sock ); sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->flags = flags; sock->proto = protocol; @@ -683,12 +683,11 @@ static struct object *create_socket( int family, int type, int protocol, unsigne if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) { - release_object( sock ); - return NULL; + return -1; } sock_reselect( sock ); clear_error(); - return &sock->obj; + return 0; }
/* accepts a socket and inits it */ @@ -720,6 +719,8 @@ static struct sock *accept_socket( obj_handle_t handle ) if (!sock) return NULL;
+ if (get_unix_fd( sock->fd ) == -1) return NULL; + if ( sock->deferred ) { acceptsock = sock->deferred; @@ -732,14 +733,13 @@ static struct sock *accept_socket( obj_handle_t handle ) release_object( sock ); return NULL; } - if (!(acceptsock = alloc_object( &sock_ops ))) + if (!(acceptsock = create_socket())) { close( acceptfd ); release_object( sock ); return NULL; }
- init_sock( acceptsock ); /* newly created socket gets the same properties of the listening socket */ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE; if (sock->state & FD_WINE_NONBLOCKING) @@ -773,6 +773,9 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock ) { int acceptfd; struct fd *newfd; + + if (get_unix_fd( sock->fd ) == -1) return FALSE; + if ( sock->deferred ) { newfd = dup_fd_object( sock->deferred->fd, 0, 0, @@ -1213,8 +1216,15 @@ static struct object *socket_device_lookup_name( struct object *obj, struct unic static struct object *socket_device_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { - set_error( STATUS_NOT_IMPLEMENTED ); - return NULL; + struct sock *sock; + + if (!(sock = create_socket())) return NULL; + if (!(sock->fd = alloc_pseudo_fd( &sock_fd_ops, &sock->obj, options ))) + { + release_object( sock ); + return NULL; + } + return &sock->obj; }
struct object *create_socket_device( struct object *root, const struct unicode_str *name ) @@ -1225,13 +1235,14 @@ struct object *create_socket_device( struct object *root, const struct unicode_s /* create a socket */ DECL_HANDLER(create_socket) { - struct object *obj; + struct sock *sock;
reply->handle = 0; - if ((obj = create_socket( req->family, req->type, req->protocol, req->flags )) != NULL) + if ((sock = create_socket()) != NULL) { - reply->handle = alloc_handle( current->process, obj, req->access, req->attributes ); - release_object( obj ); + if (!init_socket( sock, req->family, req->type, req->protocol, req->flags )) + reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->attributes ); + release_object( sock ); } }
@@ -1284,6 +1295,7 @@ DECL_HANDLER(set_socket_event)
if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES, &sock_ops))) return; + if (get_unix_fd( sock->fd ) == -1) return; old_event = sock->event; sock->mask = req->mask; sock->hmask &= ~req->mask; /* re-enable held events */ @@ -1316,6 +1328,7 @@ DECL_HANDLER(get_socket_event)
if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_READ_ATTRIBUTES, &sock_ops ))) return; + if (get_unix_fd( sock->fd ) == -1) return; reply->mask = sock->mask; reply->pmask = sock->pmask; reply->state = sock->state; @@ -1348,6 +1361,8 @@ DECL_HANDLER(enable_socket_event) FILE_WRITE_ATTRIBUTES, &sock_ops))) return;
+ if (get_unix_fd( sock->fd ) == -1) return; + /* for event-based notification, windows erases stale events */ sock->pmask &= ~req->mask;
@@ -1386,6 +1401,8 @@ DECL_HANDLER(get_socket_info) sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_READ_ATTRIBUTES, &sock_ops ); if (!sock) return;
+ if (get_unix_fd( sock->fd ) == -1) return; + reply->family = sock->family; reply->type = sock->type; reply->protocol = sock->proto;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 34 ++++++++++++++++++++++++++++++++++ server/sock.c | 19 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 include/wine/afd.h
diff --git a/include/wine/afd.h b/include/wine/afd.h new file mode 100644 index 00000000000..60f7ad6e1d7 --- /dev/null +++ b/include/wine/afd.h @@ -0,0 +1,34 @@ +/* + * Socket driver ioctls + * + * Copyright 2020 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINE_AFD_H +#define __WINE_WINE_AFD_H + +#include <winioctl.h> + +#define IOCTL_AFD_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +struct afd_create_params +{ + int family, type, protocol; + unsigned int flags; +}; + +#endif diff --git a/server/sock.c b/server/sock.c index 0448519df2a..2b6e02907ee 100644 --- a/server/sock.c +++ b/server/sock.c @@ -58,6 +58,7 @@ #include "winerror.h" #define USE_WS_PREFIX #include "winsock2.h" +#include "wine/afd.h"
#include "process.h" #include "file.h" @@ -133,6 +134,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static void sock_queue_async( struct fd *fd, struct async *async, int type, int count ); static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
+static int init_socket( struct sock *sock, int family, int type, int protocol, unsigned int flags ); static int sock_get_ntstatus( int err ); static unsigned int sock_get_error( int err );
@@ -542,10 +544,23 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
assert( sock->obj.ops == &sock_ops );
- if (get_unix_fd( fd ) == -1) return 0; + if (get_unix_fd( fd ) == -1 && code != IOCTL_AFD_CREATE) return 0;
switch(code) { + case IOCTL_AFD_CREATE: + { + const struct afd_create_params *params = get_req_data(); + + if (get_req_data_size() != sizeof(*params)) + { + set_error( STATUS_INVALID_PARAMETER ); + return 0; + } + init_socket( sock, params->family, params->type, params->protocol, params->flags ); + return 0; + } + case WS_SIO_ADDRESS_LIST_CHANGE: if ((sock->state & FD_WINE_NONBLOCKING) && async_is_blocking( async )) { @@ -680,6 +695,8 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u sock->type = type; sock->family = family;
+ if (sock->fd) release_object( sock->fd ); + if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) {
Zebediah Figura z.figura12@gmail.com writes:
+#include <winioctl.h>
+#define IOCTL_AFD_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+struct afd_create_params +{
- int family, type, protocol;
- unsigned int flags;
+};
Do we really need yet another set of Wine-specific ioctls?
Note that (FILE_DEVICE_NETWORK,0) is already used for the documented IOCTL_TCP_QUERY_INFORMATION_EX, it may be better to avoid it.
On 9/18/20 4:31 AM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
+#include <winioctl.h>
+#define IOCTL_AFD_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+struct afd_create_params +{
- int family, type, protocol;
- unsigned int flags;
+};
Do we really need yet another set of Wine-specific ioctls?
I assumed that at least it'd be preferable to a set of Wine-specific server calls; is this not the case? In particular it lets us use the ntdll infrastructure for asynchronous I/O, instead of half-duplicating it in ws2_32. I don't know what would be better here.
Unless the proposal is to use native ioctls, but I couldn't easily find them and I don't know how to safely reverse-engineer them.
Note that (FILE_DEVICE_NETWORK,0) is already used for the documented IOCTL_TCP_QUERY_INFORMATION_EX, it may be better to avoid it.
Zebediah Figura zfigura@codeweavers.com writes:
On 9/18/20 4:31 AM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
+#include <winioctl.h>
+#define IOCTL_AFD_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+struct afd_create_params +{
- int family, type, protocol;
- unsigned int flags;
+};
Do we really need yet another set of Wine-specific ioctls?
I assumed that at least it'd be preferable to a set of Wine-specific server calls; is this not the case? In particular it lets us use the ntdll infrastructure for asynchronous I/O, instead of half-duplicating it in ws2_32. I don't know what would be better here.
Sure, moving things to ntdll is still an improvement.
Unless the proposal is to use native ioctls, but I couldn't easily find them and I don't know how to safely reverse-engineer them.
Yes, I was hoping that there would be a more compatible way of doing that. But if it's all undocumented, maybe that's the best we can do for now...
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: Check for WSAEACCES after the call that actually returns it; thanks Jacek.
dlls/ws2_32/socket.c | 109 +++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 46 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 246a0e2819b..717fb133dc1 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -155,6 +155,7 @@ #define USE_WC_PREFIX /* For CMSG_DATA */ #include "iphlpapi.h" #include "ip2string.h" +#include "wine/afd.h" #include "wine/server.h" #include "wine/debug.h" #include "wine/exception.h" @@ -7589,8 +7590,15 @@ SOCKET WINAPI WSASocketA(int af, int type, int protocol, */ SOCKET WINAPI WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, - GROUP g, DWORD dwFlags) + GROUP g, DWORD flags) { + static const WCHAR afdW[] = {'\','D','e','v','i','c','e','\','A','f','d',0}; + struct afd_create_params create_params; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE handle; SOCKET ret; DWORD err; int unixaf, unixtype, ipxptype = -1; @@ -7601,7 +7609,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, */
TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n", - af, type, protocol, lpProtocolInfo, g, dwFlags ); + af, type, protocol, lpProtocolInfo, g, flags );
if (!num_startup) { @@ -7702,62 +7710,71 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, goto done; }
- SERVER_START_REQ( create_socket ) + 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, &io, 0, 0))) { - req->family = unixaf; - req->type = unixtype; - req->protocol = protocol; - req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE; - req->attributes = (dwFlags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT; - req->flags = dwFlags & ~WSA_FLAG_NO_HANDLE_INHERIT; - err = NtStatusToWSAError( wine_server_call( req ) ); - ret = HANDLE2SOCKET( wine_server_ptr_handle( reply->handle )); + WARN("Failed to create socket, status %#x.\n", status); + WSASetLastError(NtStatusToWSAError(status)); + return INVALID_SOCKET; } - SERVER_END_REQ; - if (ret) - { - TRACE("\tcreated %04lx\n", ret ); - if (ipxptype > 0) - set_ipx_packettype(ret, ipxptype);
- if (unixaf == AF_INET || unixaf == AF_INET6) + create_params.family = unixaf; + create_params.type = unixtype; + create_params.protocol = protocol; + create_params.flags = flags & ~WSA_FLAG_NO_HANDLE_INHERIT; + if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_AFD_CREATE, &create_params, sizeof(create_params), NULL, 0))) + { + WARN("Failed to initialize socket, status %#x.\n", status); + err = NtStatusToWSAError(status); + if (err == WSAEACCES) /* raw socket denied */ { - /* 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); + if (type == SOCK_RAW) + ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n"); + else + ERR_(winediag)("Failed to create socket, this requires special permissions.\n"); } + WSASetLastError(err); + NtClose(handle); + return INVALID_SOCKET; + } + + 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)) + if (unixaf == AF_INET6) + { + int fd = get_sock_fd(ret, 0, NULL); + if (fd != -1) { - CloseHandle(SOCKET2HANDLE(ret)); - return INVALID_SOCKET; + /* 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); } - return ret; } - - if (err == WSAEACCES) /* raw socket denied */ +#endif + if (!socket_list_add(ret)) { - if (type == SOCK_RAW) - ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n"); - else - ERR_(winediag)("Failed to create socket, this requires special permissions.\n"); + CloseHandle(handle); + return INVALID_SOCKET; } + return ret;
done: WARN("\t\tfailed, error %d!\n", err);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/protocol.def | 13 ------------- server/sock.c | 14 -------------- 2 files changed, 27 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 92290af701c..a8790d2609e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1380,19 +1380,6 @@ enum server_fd_type @END
-/* Create a socket */ -@REQ(create_socket) - unsigned int access; /* wanted access rights */ - unsigned int attributes; /* object attributes */ - int family; /* family, see socket manpage */ - int type; /* type, see socket manpage */ - int protocol; /* protocol, see socket manpage */ - unsigned int flags; /* socket flags */ -@REPLY - obj_handle_t handle; /* handle to the new socket */ -@END - - /* Accept a socket */ @REQ(accept_socket) obj_handle_t lhandle; /* handle to the listening socket */ diff --git a/server/sock.c b/server/sock.c index 2b6e02907ee..23faadb2e3b 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1249,20 +1249,6 @@ struct object *create_socket_device( struct object *root, const struct unicode_s return create_named_object( root, &socket_device_ops, name, 0, NULL ); }
-/* create a socket */ -DECL_HANDLER(create_socket) -{ - struct sock *sock; - - reply->handle = 0; - if ((sock = create_socket()) != NULL) - { - if (!init_socket( sock, req->family, req->type, req->protocol, req->flags )) - reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->attributes ); - release_object( sock ); - } -} - /* accept a socket */ DECL_HANDLER(accept_socket) {