4 * Copyright 2021 Zebediah Figura for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <sys/types.h>
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
44 #ifdef HAVE_NETINET_TCP_H
45 # include <netinet/tcp.h>
48 #ifdef HAVE_NETIPX_IPX_H
49 # include <netipx/ipx.h>
50 #elif defined(HAVE_LINUX_IPX_H)
51 # ifdef HAVE_ASM_TYPES_H
52 # include <asm/types.h>
54 # ifdef HAVE_LINUX_TYPES_H
55 # include <linux/types.h>
57 # include <linux/ipx.h>
59 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
63 #ifdef HAVE_LINUX_IRDA_H
64 # ifdef HAVE_LINUX_TYPES_H
65 # include <linux/types.h>
67 # include <linux/irda.h>
72 #define WIN32_NO_STATUS
84 #include "unix_private.h"
86 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
87 /* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */
88 #define TCP_KEEPIDLE TCP_KEEPALIVE
91 #if defined(linux) && !defined(IP_UNICAST_IF)
92 #define IP_UNICAST_IF 50
95 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
97 #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
99 static async_data_t
server_async( HANDLE handle
, struct async_fileio
*user
, HANDLE event
,
100 PIO_APC_ROUTINE apc
, void *apc_context
, IO_STATUS_BLOCK
*io
)
103 async
.handle
= wine_server_obj_handle( handle
);
104 async
.user
= wine_server_client_ptr( user
);
105 async
.iosb
= wine_server_client_ptr( io
);
106 async
.event
= wine_server_obj_handle( event
);
107 async
.apc
= wine_server_client_ptr( apc
);
108 async
.apc_context
= wine_server_client_ptr( apc_context
);
112 static NTSTATUS
wait_async( HANDLE handle
, BOOL alertable
)
114 return NtWaitForSingleObject( handle
, alertable
, NULL
);
119 struct sockaddr addr
;
120 struct sockaddr_in in
;
121 struct sockaddr_in6 in6
;
123 struct sockaddr_ipx ipx
;
126 struct sockaddr_irda irda
;
130 struct async_recv_ioctl
132 struct async_fileio io
;
134 struct WS_sockaddr
*addr
;
142 struct async_send_ioctl
144 struct async_fileio io
;
145 const struct WS_sockaddr
*addr
;
148 unsigned int sent_len
;
150 unsigned int iov_cursor
;
154 struct async_transmit_ioctl
156 struct async_fileio io
;
159 unsigned int buffer_size
; /* allocated size of buffer */
160 unsigned int read_len
; /* amount of valid data currently in the buffer */
161 unsigned int head_cursor
; /* amount of header data already sent */
162 unsigned int file_cursor
; /* amount of file data already sent */
163 unsigned int buffer_cursor
; /* amount of data currently in the buffer already sent */
164 unsigned int tail_cursor
; /* amount of tail data already sent */
165 unsigned int file_len
; /* total file length to send */
167 TRANSMIT_FILE_BUFFERS buffers
;
168 LARGE_INTEGER offset
;
171 static NTSTATUS
sock_errno_to_status( int err
)
175 case EBADF
: return STATUS_INVALID_HANDLE
;
176 case EBUSY
: return STATUS_DEVICE_BUSY
;
178 case EACCES
: return STATUS_ACCESS_DENIED
;
179 case EFAULT
: return STATUS_ACCESS_VIOLATION
;
180 case EINVAL
: return STATUS_INVALID_PARAMETER
;
182 case EMFILE
: return STATUS_TOO_MANY_OPENED_FILES
;
184 case EWOULDBLOCK
: return STATUS_DEVICE_NOT_READY
;
185 case EALREADY
: return STATUS_NETWORK_BUSY
;
186 case ENOTSOCK
: return STATUS_OBJECT_TYPE_MISMATCH
;
187 case EDESTADDRREQ
: return STATUS_INVALID_PARAMETER
;
188 case EMSGSIZE
: return STATUS_BUFFER_OVERFLOW
;
189 case EPROTONOSUPPORT
:
190 case ESOCKTNOSUPPORT
:
193 case EPROTOTYPE
: return STATUS_NOT_SUPPORTED
;
194 case ENOPROTOOPT
: return STATUS_INVALID_PARAMETER
;
195 case EOPNOTSUPP
: return STATUS_NOT_SUPPORTED
;
196 case EADDRINUSE
: return STATUS_SHARING_VIOLATION
;
197 case EADDRNOTAVAIL
: return STATUS_INVALID_PARAMETER
;
198 case ECONNREFUSED
: return STATUS_CONNECTION_REFUSED
;
199 case ESHUTDOWN
: return STATUS_PIPE_DISCONNECTED
;
200 case ENOTCONN
: return STATUS_INVALID_CONNECTION
;
201 case ETIMEDOUT
: return STATUS_IO_TIMEOUT
;
202 case ENETUNREACH
: return STATUS_NETWORK_UNREACHABLE
;
203 case EHOSTUNREACH
: return STATUS_HOST_UNREACHABLE
;
204 case ENETDOWN
: return STATUS_NETWORK_BUSY
;
206 case ECONNRESET
: return STATUS_CONNECTION_RESET
;
207 case ECONNABORTED
: return STATUS_CONNECTION_ABORTED
;
208 case EISCONN
: return STATUS_CONNECTION_ACTIVE
;
210 case 0: return STATUS_SUCCESS
;
212 FIXME( "unknown errno %d\n", err
);
213 return STATUS_UNSUCCESSFUL
;
217 static socklen_t
sockaddr_to_unix( const struct WS_sockaddr
*wsaddr
, int wsaddrlen
, union unix_sockaddr
*uaddr
)
219 memset( uaddr
, 0, sizeof(*uaddr
) );
221 switch (wsaddr
->sa_family
)
225 struct WS_sockaddr_in win
= {0};
227 if (wsaddrlen
< sizeof(win
)) return 0;
228 memcpy( &win
, wsaddr
, sizeof(win
) );
229 uaddr
->in
.sin_family
= AF_INET
;
230 uaddr
->in
.sin_port
= win
.sin_port
;
231 memcpy( &uaddr
->in
.sin_addr
, &win
.sin_addr
, sizeof(win
.sin_addr
) );
232 return sizeof(uaddr
->in
);
237 struct WS_sockaddr_in6 win
= {0};
239 if (wsaddrlen
< sizeof(win
)) return 0;
240 memcpy( &win
, wsaddr
, sizeof(win
) );
241 uaddr
->in6
.sin6_family
= AF_INET6
;
242 uaddr
->in6
.sin6_port
= win
.sin6_port
;
243 uaddr
->in6
.sin6_flowinfo
= win
.sin6_flowinfo
;
244 memcpy( &uaddr
->in6
.sin6_addr
, &win
.sin6_addr
, sizeof(win
.sin6_addr
) );
245 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
246 uaddr
->in6
.sin6_scope_id
= win
.sin6_scope_id
;
248 return sizeof(uaddr
->in6
);
254 struct WS_sockaddr_ipx win
= {0};
256 if (wsaddrlen
< sizeof(win
)) return 0;
257 memcpy( &win
, wsaddr
, sizeof(win
) );
258 uaddr
->ipx
.sipx_family
= AF_IPX
;
259 memcpy( &uaddr
->ipx
.sipx_network
, win
.sa_netnum
, sizeof(win
.sa_netnum
) );
260 memcpy( &uaddr
->ipx
.sipx_node
, win
.sa_nodenum
, sizeof(win
.sa_nodenum
) );
261 uaddr
->ipx
.sipx_port
= win
.sa_socket
;
262 return sizeof(uaddr
->ipx
);
269 SOCKADDR_IRDA win
= {0};
270 unsigned int lsap_sel
;
272 if (wsaddrlen
< sizeof(win
)) return 0;
273 memcpy( &win
, wsaddr
, sizeof(win
) );
274 uaddr
->irda
.sir_family
= AF_IRDA
;
275 if (sscanf( win
.irdaServiceName
, "LSAP-SEL%u", &lsap_sel
) == 1)
276 uaddr
->irda
.sir_lsap_sel
= lsap_sel
;
279 uaddr
->irda
.sir_lsap_sel
= LSAP_ANY
;
280 memcpy( uaddr
->irda
.sir_name
, win
.irdaServiceName
, sizeof(win
.irdaServiceName
) );
282 memcpy( &uaddr
->irda
.sir_addr
, win
.irdaDeviceID
, sizeof(win
.irdaDeviceID
) );
283 return sizeof(uaddr
->irda
);
290 default: /* likely an ipv4 address */
291 case sizeof(struct WS_sockaddr_in
):
292 return sizeof(uaddr
->in
);
295 case sizeof(struct WS_sockaddr_ipx
):
296 return sizeof(uaddr
->ipx
);
300 case sizeof(SOCKADDR_IRDA
):
301 return sizeof(uaddr
->irda
);
304 case sizeof(struct WS_sockaddr_in6
):
305 return sizeof(uaddr
->in6
);
309 FIXME( "unknown address family %u\n", wsaddr
->sa_family
);
314 static int sockaddr_from_unix( const union unix_sockaddr
*uaddr
, struct WS_sockaddr
*wsaddr
, socklen_t wsaddrlen
)
316 memset( wsaddr
, 0, wsaddrlen
);
318 switch (uaddr
->addr
.sa_family
)
322 struct WS_sockaddr_in win
= {0};
324 if (wsaddrlen
< sizeof(win
)) return -1;
325 win
.sin_family
= WS_AF_INET
;
326 win
.sin_port
= uaddr
->in
.sin_port
;
327 memcpy( &win
.sin_addr
, &uaddr
->in
.sin_addr
, sizeof(win
.sin_addr
) );
328 memcpy( wsaddr
, &win
, sizeof(win
) );
334 struct WS_sockaddr_in6 win
= {0};
336 if (wsaddrlen
< sizeof(win
)) return -1;
337 win
.sin6_family
= WS_AF_INET6
;
338 win
.sin6_port
= uaddr
->in6
.sin6_port
;
339 win
.sin6_flowinfo
= uaddr
->in6
.sin6_flowinfo
;
340 memcpy( &win
.sin6_addr
, &uaddr
->in6
.sin6_addr
, sizeof(win
.sin6_addr
) );
341 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
342 win
.sin6_scope_id
= uaddr
->in6
.sin6_scope_id
;
344 memcpy( wsaddr
, &win
, sizeof(win
) );
351 struct WS_sockaddr_ipx win
= {0};
353 if (wsaddrlen
< sizeof(win
)) return -1;
354 win
.sa_family
= WS_AF_IPX
;
355 memcpy( win
.sa_netnum
, &uaddr
->ipx
.sipx_network
, sizeof(win
.sa_netnum
) );
356 memcpy( win
.sa_nodenum
, &uaddr
->ipx
.sipx_node
, sizeof(win
.sa_nodenum
) );
357 win
.sa_socket
= uaddr
->ipx
.sipx_port
;
358 memcpy( wsaddr
, &win
, sizeof(win
) );
368 if (wsaddrlen
< sizeof(win
)) return -1;
369 win
.irdaAddressFamily
= WS_AF_IRDA
;
370 memcpy( win
.irdaDeviceID
, &uaddr
->irda
.sir_addr
, sizeof(win
.irdaDeviceID
) );
371 if (uaddr
->irda
.sir_lsap_sel
!= LSAP_ANY
)
372 snprintf( win
.irdaServiceName
, sizeof(win
.irdaServiceName
), "LSAP-SEL%u", uaddr
->irda
.sir_lsap_sel
);
374 memcpy( win
.irdaServiceName
, uaddr
->irda
.sir_name
, sizeof(win
.irdaServiceName
) );
375 memcpy( wsaddr
, &win
, sizeof(win
) );
384 FIXME( "unknown address family %d\n", uaddr
->addr
.sa_family
);
389 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
390 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
391 static WSACMSGHDR
*fill_control_message( int level
, int type
, WSACMSGHDR
*current
, ULONG
*maxsize
, void *data
, int len
)
393 ULONG msgsize
= sizeof(WSACMSGHDR
) + WSA_CMSG_ALIGN(len
);
394 char *ptr
= (char *) current
+ sizeof(WSACMSGHDR
);
396 if (msgsize
> *maxsize
)
399 current
->cmsg_len
= sizeof(WSACMSGHDR
) + len
;
400 current
->cmsg_level
= level
;
401 current
->cmsg_type
= type
;
402 memcpy(ptr
, data
, len
);
403 return (WSACMSGHDR
*)(ptr
+ WSA_CMSG_ALIGN(len
));
405 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
407 static int convert_control_headers(struct msghdr
*hdr
, WSABUF
*control
)
409 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
410 WSACMSGHDR
*cmsg_win
= (WSACMSGHDR
*)control
->buf
, *ptr
;
411 ULONG ctlsize
= control
->len
;
412 struct cmsghdr
*cmsg_unix
;
415 for (cmsg_unix
= CMSG_FIRSTHDR(hdr
); cmsg_unix
!= NULL
; cmsg_unix
= CMSG_NXTHDR(hdr
, cmsg_unix
))
417 switch (cmsg_unix
->cmsg_level
)
420 switch (cmsg_unix
->cmsg_type
)
422 #if defined(IP_PKTINFO)
425 const struct in_pktinfo
*data_unix
= (struct in_pktinfo
*)CMSG_DATA(cmsg_unix
);
426 struct WS_in_pktinfo data_win
;
428 memcpy( &data_win
.ipi_addr
, &data_unix
->ipi_addr
.s_addr
, 4 ); /* 4 bytes = 32 address bits */
429 data_win
.ipi_ifindex
= data_unix
->ipi_ifindex
;
430 ptr
= fill_control_message( WS_IPPROTO_IP
, WS_IP_PKTINFO
, ptr
, &ctlsize
,
431 (void *)&data_win
, sizeof(data_win
) );
432 if (!ptr
) goto error
;
435 #elif defined(IP_RECVDSTADDR)
438 const struct in_addr
*addr_unix
= (struct in_addr
*)CMSG_DATA(cmsg_unix
);
439 struct WS_in_pktinfo data_win
;
441 memcpy( &data_win
.ipi_addr
, &addr_unix
->s_addr
, 4 ); /* 4 bytes = 32 address bits */
442 data_win
.ipi_ifindex
= 0; /* FIXME */
443 ptr
= fill_control_message( WS_IPPROTO_IP
, WS_IP_PKTINFO
, ptr
, &ctlsize
,
444 (void *)&data_win
, sizeof(data_win
) );
445 if (!ptr
) goto error
;
448 #endif /* IP_PKTINFO */
450 FIXME("Unhandled IPPROTO_IP message header type %d\n", cmsg_unix
->cmsg_type
);
456 FIXME("Unhandled message header level %d\n", cmsg_unix
->cmsg_level
);
461 control
->len
= (char *)ptr
- (char *)cmsg_win
;
467 #else /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
470 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
472 #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
474 static NTSTATUS
try_recv( int fd
, struct async_recv_ioctl
*async
, ULONG_PTR
*size
)
476 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
477 char control_buffer
[512];
479 union unix_sockaddr unix_addr
;
484 memset( &hdr
, 0, sizeof(hdr
) );
487 hdr
.msg_name
= &unix_addr
.addr
;
488 hdr
.msg_namelen
= sizeof(unix_addr
);
490 hdr
.msg_iov
= async
->iov
;
491 hdr
.msg_iovlen
= async
->count
;
492 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
493 hdr
.msg_control
= control_buffer
;
494 hdr
.msg_controllen
= sizeof(control_buffer
);
496 while ((ret
= virtual_locked_recvmsg( fd
, &hdr
, async
->unix_flags
)) < 0 && errno
== EINTR
);
500 /* Unix-like systems return EINVAL when attempting to read OOB data from
501 * an empty socket buffer; Windows returns WSAEWOULDBLOCK. */
502 if ((async
->unix_flags
& MSG_OOB
) && errno
== EINVAL
)
505 if (errno
!= EWOULDBLOCK
) WARN( "recvmsg: %s\n", strerror( errno
) );
506 return sock_errno_to_status( errno
);
509 status
= (hdr
.msg_flags
& MSG_TRUNC
) ? STATUS_BUFFER_OVERFLOW
: STATUS_SUCCESS
;
511 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
514 ERR( "Message control headers cannot be properly supported on this system.\n" );
515 async
->control
->len
= 0;
518 if (async
->control
&& !convert_control_headers( &hdr
, async
->control
))
520 WARN( "Application passed insufficient room for control headers.\n" );
521 *async
->ret_flags
|= WS_MSG_CTRUNC
;
522 status
= STATUS_BUFFER_OVERFLOW
;
526 /* If this socket is connected, Linux doesn't give us msg_name and
527 * msg_namelen from recvmsg, but it does set msg_namelen to zero.
529 * MSDN says that the address is ignored for connection-oriented sockets, so
530 * don't try to translate it.
532 if (async
->addr
&& hdr
.msg_namelen
)
533 *async
->addr_len
= sockaddr_from_unix( &unix_addr
, async
->addr
, *async
->addr_len
);
539 static NTSTATUS
async_recv_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
541 struct async_recv_ioctl
*async
= user
;
542 ULONG_PTR information
= 0;
545 TRACE( "%#x\n", status
);
547 if (status
== STATUS_ALERTED
)
549 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
552 status
= try_recv( fd
, async
, &information
);
553 TRACE( "got status %#x, %#lx bytes read\n", status
, information
);
555 if (status
== STATUS_DEVICE_NOT_READY
)
556 status
= STATUS_PENDING
;
558 if (needs_close
) close( fd
);
560 if (status
!= STATUS_PENDING
)
563 release_fileio( &async
->io
);
568 static NTSTATUS
sock_recv( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
569 int fd
, const WSABUF
*buffers
, unsigned int count
, WSABUF
*control
,
570 struct WS_sockaddr
*addr
, int *addr_len
, DWORD
*ret_flags
, int unix_flags
, int force_async
)
572 struct async_recv_ioctl
*async
;
573 ULONG_PTR information
;
580 if (unix_flags
& MSG_OOB
)
583 socklen_t len
= sizeof(oobinline
);
584 if (!getsockopt( fd
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&oobinline
, &len
) && oobinline
)
585 return STATUS_INVALID_PARAMETER
;
588 for (i
= 0; i
< count
; ++i
)
590 if (!virtual_check_buffer_for_write( buffers
[i
].buf
, buffers
[i
].len
))
591 return STATUS_ACCESS_VIOLATION
;
594 async_size
= offsetof( struct async_recv_ioctl
, iov
[count
] );
596 if (!(async
= (struct async_recv_ioctl
*)alloc_fileio( async_size
, async_recv_proc
, handle
)))
597 return STATUS_NO_MEMORY
;
599 async
->count
= count
;
600 for (i
= 0; i
< count
; ++i
)
602 async
->iov
[i
].iov_base
= buffers
[i
].buf
;
603 async
->iov
[i
].iov_len
= buffers
[i
].len
;
605 async
->unix_flags
= unix_flags
;
606 async
->control
= control
;
608 async
->addr_len
= addr_len
;
609 async
->ret_flags
= ret_flags
;
611 status
= try_recv( fd
, async
, &information
);
613 if (status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_OVERFLOW
&& status
!= STATUS_DEVICE_NOT_READY
)
615 release_fileio( &async
->io
);
619 if (status
== STATUS_DEVICE_NOT_READY
&& force_async
)
620 status
= STATUS_PENDING
;
622 SERVER_START_REQ( recv_socket
)
624 req
->status
= status
;
625 req
->total
= information
;
626 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, io
);
627 req
->oob
= !!(unix_flags
& MSG_OOB
);
628 status
= wine_server_call( req
);
629 wait_handle
= wine_server_ptr_handle( reply
->wait
);
630 options
= reply
->options
;
631 if ((!NT_ERROR(status
) || wait_handle
) && status
!= STATUS_PENDING
)
634 io
->Information
= information
;
639 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
641 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
646 struct async_poll_ioctl
648 struct async_fileio io
;
650 struct afd_poll_params
*input
, *output
;
651 struct poll_socket_output sockets
[1];
654 static ULONG_PTR
fill_poll_output( struct async_poll_ioctl
*async
, NTSTATUS status
)
656 struct afd_poll_params
*input
= async
->input
, *output
= async
->output
;
657 unsigned int i
, count
= 0;
659 memcpy( output
, input
, offsetof( struct afd_poll_params
, sockets
[0] ) );
663 for (i
= 0; i
< async
->count
; ++i
)
665 if (async
->sockets
[i
].flags
)
667 output
->sockets
[count
].socket
= input
->sockets
[i
].socket
;
668 output
->sockets
[count
].flags
= async
->sockets
[i
].flags
;
669 output
->sockets
[count
].status
= async
->sockets
[i
].status
;
674 output
->count
= count
;
675 return offsetof( struct afd_poll_params
, sockets
[count
] );
678 static NTSTATUS
async_poll_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
680 struct async_poll_ioctl
*async
= user
;
681 ULONG_PTR information
= 0;
683 if (status
== STATUS_ALERTED
)
685 SERVER_START_REQ( get_async_result
)
687 req
->user_arg
= wine_server_client_ptr( async
);
688 wine_server_set_reply( req
, async
->sockets
, async
->count
* sizeof(async
->sockets
[0]) );
689 status
= wine_server_call( req
);
693 information
= fill_poll_output( async
, status
);
696 if (status
!= STATUS_PENDING
)
699 free( async
->input
);
700 release_fileio( &async
->io
);
706 /* we could handle this ioctl entirely on the server side, but the differing
707 * structure size makes it painful */
708 static NTSTATUS
sock_poll( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
709 void *in_buffer
, ULONG in_size
, void *out_buffer
, ULONG out_size
)
711 const struct afd_poll_params
*params
= in_buffer
;
712 struct poll_socket_input
*input
;
713 struct async_poll_ioctl
*async
;
720 if (in_size
< sizeof(*params
) || out_size
< in_size
|| !params
->count
721 || in_size
< offsetof( struct afd_poll_params
, sockets
[params
->count
] ))
722 return STATUS_INVALID_PARAMETER
;
724 TRACE( "timeout %s, count %u, unknown %#x, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
725 wine_dbgstr_longlong(params
->timeout
), params
->count
, params
->unknown
,
726 params
->padding
[0], params
->padding
[1], params
->padding
[2],
727 params
->sockets
[0].socket
, params
->sockets
[0].flags
);
729 if (params
->unknown
) FIXME( "unknown boolean is %#x\n", params
->unknown
);
730 if (params
->padding
[0]) FIXME( "padding[0] is %#x\n", params
->padding
[0] );
731 if (params
->padding
[1]) FIXME( "padding[1] is %#x\n", params
->padding
[1] );
732 if (params
->padding
[2]) FIXME( "padding[2] is %#x\n", params
->padding
[2] );
733 for (i
= 0; i
< params
->count
; ++i
)
735 if (params
->sockets
[i
].flags
& ~0x1ff)
736 FIXME( "unknown socket flags %#x\n", params
->sockets
[i
].flags
);
739 if (!(input
= malloc( params
->count
* sizeof(*input
) )))
740 return STATUS_NO_MEMORY
;
742 async_size
= offsetof( struct async_poll_ioctl
, sockets
[params
->count
] );
744 if (!(async
= (struct async_poll_ioctl
*)alloc_fileio( async_size
, async_poll_proc
, handle
)))
747 return STATUS_NO_MEMORY
;
750 if (!(async
->input
= malloc( in_size
)))
752 release_fileio( &async
->io
);
754 return STATUS_NO_MEMORY
;
756 memcpy( async
->input
, in_buffer
, in_size
);
758 async
->count
= params
->count
;
759 async
->output
= out_buffer
;
761 for (i
= 0; i
< params
->count
; ++i
)
763 input
[i
].socket
= params
->sockets
[i
].socket
;
764 input
[i
].flags
= params
->sockets
[i
].flags
;
767 SERVER_START_REQ( poll_socket
)
769 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, io
);
770 req
->timeout
= params
->timeout
;
771 wine_server_add_data( req
, input
, params
->count
* sizeof(*input
) );
772 wine_server_set_reply( req
, async
->sockets
, params
->count
* sizeof(async
->sockets
[0]) );
773 status
= wine_server_call( req
);
774 wait_handle
= wine_server_ptr_handle( reply
->wait
);
775 options
= reply
->options
;
776 if (wait_handle
&& status
!= STATUS_PENDING
)
779 io
->Information
= fill_poll_output( async
, status
);
786 if (status
!= STATUS_PENDING
)
788 free( async
->input
);
789 release_fileio( &async
->io
);
792 if (wait_handle
) status
= wait_async( wait_handle
, (options
& FILE_SYNCHRONOUS_IO_ALERT
) );
796 static NTSTATUS
try_send( int fd
, struct async_send_ioctl
*async
)
798 union unix_sockaddr unix_addr
;
802 memset( &hdr
, 0, sizeof(hdr
) );
805 hdr
.msg_name
= &unix_addr
;
806 hdr
.msg_namelen
= sockaddr_to_unix( async
->addr
, async
->addr_len
, &unix_addr
);
807 if (!hdr
.msg_namelen
)
809 ERR( "failed to convert address\n" );
810 return STATUS_ACCESS_VIOLATION
;
813 #if defined(HAS_IPX) && defined(SOL_IPX)
814 if (async
->addr
->sa_family
== WS_AF_IPX
)
817 socklen_t len
= sizeof(type
);
819 /* The packet type is stored at the IPX socket level. At least the
820 * linux kernel seems to do something with it in case hdr.msg_name
821 * is NULL. Nonetheless we can use it to store the packet type, and
822 * then we can retrieve it using getsockopt. After that we can set
823 * the IPX type in the sockaddr_ipx structure with the stored value.
825 if (getsockopt(fd
, SOL_IPX
, IPX_TYPE
, &type
, &len
) >= 0)
826 unix_addr
.ipx
.sipx_type
= type
;
831 hdr
.msg_iov
= async
->iov
+ async
->iov_cursor
;
832 hdr
.msg_iovlen
= async
->count
- async
->iov_cursor
;
834 while ((ret
= sendmsg( fd
, &hdr
, async
->unix_flags
)) == -1)
836 if (errno
== EISCONN
)
841 else if (errno
!= EINTR
)
843 if (errno
!= EWOULDBLOCK
) WARN( "sendmsg: %s\n", strerror( errno
) );
844 return sock_errno_to_status( errno
);
848 async
->sent_len
+= ret
;
850 while (async
->iov_cursor
< async
->count
&& ret
>= async
->iov
[async
->iov_cursor
].iov_len
)
851 ret
-= async
->iov
[async
->iov_cursor
++].iov_len
;
852 if (async
->iov_cursor
< async
->count
)
854 async
->iov
[async
->iov_cursor
].iov_base
= (char *)async
->iov
[async
->iov_cursor
].iov_base
+ ret
;
855 async
->iov
[async
->iov_cursor
].iov_len
-= ret
;
856 return STATUS_DEVICE_NOT_READY
;
858 return STATUS_SUCCESS
;
861 static NTSTATUS
async_send_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
863 struct async_send_ioctl
*async
= user
;
866 TRACE( "%#x\n", status
);
868 if (status
== STATUS_ALERTED
)
870 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
873 status
= try_send( fd
, async
);
874 TRACE( "got status %#x\n", status
);
876 if (status
== STATUS_DEVICE_NOT_READY
)
877 status
= STATUS_PENDING
;
879 if (needs_close
) close( fd
);
881 if (status
!= STATUS_PENDING
)
883 *info
= async
->sent_len
;
884 release_fileio( &async
->io
);
889 static NTSTATUS
sock_send( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
890 IO_STATUS_BLOCK
*io
, int fd
, const WSABUF
*buffers
, unsigned int count
,
891 const struct WS_sockaddr
*addr
, unsigned int addr_len
, int unix_flags
, int force_async
)
893 struct async_send_ioctl
*async
;
900 async_size
= offsetof( struct async_send_ioctl
, iov
[count
] );
902 if (!(async
= (struct async_send_ioctl
*)alloc_fileio( async_size
, async_send_proc
, handle
)))
903 return STATUS_NO_MEMORY
;
905 async
->count
= count
;
906 for (i
= 0; i
< count
; ++i
)
908 async
->iov
[i
].iov_base
= buffers
[i
].buf
;
909 async
->iov
[i
].iov_len
= buffers
[i
].len
;
911 async
->unix_flags
= unix_flags
;
913 async
->addr_len
= addr_len
;
914 async
->iov_cursor
= 0;
917 status
= try_send( fd
, async
);
919 if (status
!= STATUS_SUCCESS
&& status
!= STATUS_DEVICE_NOT_READY
)
921 release_fileio( &async
->io
);
925 if (status
== STATUS_DEVICE_NOT_READY
&& force_async
)
926 status
= STATUS_PENDING
;
928 SERVER_START_REQ( send_socket
)
930 req
->status
= status
;
931 req
->total
= async
->sent_len
;
932 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, io
);
933 status
= wine_server_call( req
);
934 wait_handle
= wine_server_ptr_handle( reply
->wait
);
935 options
= reply
->options
;
936 if ((!NT_ERROR(status
) || wait_handle
) && status
!= STATUS_PENDING
)
939 io
->Information
= async
->sent_len
;
944 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
946 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
950 static ssize_t
do_send( int fd
, const void *buffer
, size_t len
, int flags
)
953 while ((ret
= send( fd
, buffer
, len
, flags
)) < 0 && errno
== EINTR
);
954 if (ret
< 0 && errno
!= EWOULDBLOCK
) WARN( "send: %s\n", strerror( errno
) );
958 static NTSTATUS
try_transmit( int sock_fd
, int file_fd
, struct async_transmit_ioctl
*async
)
962 while (async
->head_cursor
< async
->buffers
.HeadLength
)
964 TRACE( "sending %u bytes of header data\n", async
->buffers
.HeadLength
- async
->head_cursor
);
965 ret
= do_send( sock_fd
, (char *)async
->buffers
.Head
+ async
->head_cursor
,
966 async
->buffers
.HeadLength
- async
->head_cursor
, 0 );
967 if (ret
< 0) return sock_errno_to_status( errno
);
968 TRACE( "send returned %zd\n", ret
);
969 async
->head_cursor
+= ret
;
972 while (async
->buffer_cursor
< async
->read_len
)
974 TRACE( "sending %u bytes of file data\n", async
->read_len
- async
->buffer_cursor
);
975 ret
= do_send( sock_fd
, async
->buffer
+ async
->buffer_cursor
,
976 async
->read_len
- async
->buffer_cursor
, 0 );
977 if (ret
< 0) return sock_errno_to_status( errno
);
978 TRACE( "send returned %zd\n", ret
);
979 async
->buffer_cursor
+= ret
;
980 async
->file_cursor
+= ret
;
983 if (async
->file
&& async
->buffer_cursor
== async
->read_len
)
985 unsigned int read_size
= async
->buffer_size
;
988 read_size
= min( read_size
, async
->file_len
- async
->file_cursor
);
990 TRACE( "reading %u bytes of file data\n", read_size
);
993 if (async
->offset
.QuadPart
== FILE_USE_FILE_POINTER_POSITION
)
994 ret
= read( file_fd
, async
->buffer
, read_size
);
996 ret
= pread( file_fd
, async
->buffer
, read_size
, async
->offset
.QuadPart
);
997 } while (ret
< 0 && errno
== EINTR
);
998 if (ret
< 0) return errno_to_status( errno
);
999 TRACE( "read returned %zd\n", ret
);
1001 async
->read_len
= ret
;
1002 async
->buffer_cursor
= 0;
1003 if (async
->offset
.QuadPart
!= FILE_USE_FILE_POINTER_POSITION
)
1004 async
->offset
.QuadPart
+= ret
;
1006 if (ret
< read_size
|| (async
->file_len
&& async
->file_cursor
== async
->file_len
))
1008 return STATUS_PENDING
; /* still more data to send */
1011 while (async
->tail_cursor
< async
->buffers
.TailLength
)
1013 TRACE( "sending %u bytes of tail data\n", async
->buffers
.TailLength
- async
->tail_cursor
);
1014 ret
= do_send( sock_fd
, (char *)async
->buffers
.Tail
+ async
->tail_cursor
,
1015 async
->buffers
.TailLength
- async
->tail_cursor
, 0 );
1016 if (ret
< 0) return sock_errno_to_status( errno
);
1017 TRACE( "send returned %zd\n", ret
);
1018 async
->tail_cursor
+= ret
;
1021 return STATUS_SUCCESS
;
1024 static NTSTATUS
async_transmit_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
1026 int sock_fd
, file_fd
= -1, sock_needs_close
= FALSE
, file_needs_close
= FALSE
;
1027 struct async_transmit_ioctl
*async
= user
;
1029 TRACE( "%#x\n", status
);
1031 if (status
== STATUS_ALERTED
)
1033 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &sock_fd
, &sock_needs_close
, NULL
, NULL
)))
1036 if (async
->file
&& (status
= server_get_unix_fd( async
->file
, 0, &file_fd
, &file_needs_close
, NULL
, NULL
)))
1038 if (sock_needs_close
) close( sock_fd
);
1042 status
= try_transmit( sock_fd
, file_fd
, async
);
1043 TRACE( "got status %#x\n", status
);
1045 if (status
== STATUS_DEVICE_NOT_READY
)
1046 status
= STATUS_PENDING
;
1048 if (sock_needs_close
) close( sock_fd
);
1049 if (file_needs_close
) close( file_fd
);
1051 if (status
!= STATUS_PENDING
)
1053 *info
= async
->head_cursor
+ async
->file_cursor
+ async
->tail_cursor
;
1054 release_fileio( &async
->io
);
1059 static NTSTATUS
sock_transmit( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
1060 IO_STATUS_BLOCK
*io
, int fd
, const struct afd_transmit_params
*params
)
1062 int file_fd
, file_needs_close
= FALSE
;
1063 struct async_transmit_ioctl
*async
;
1064 enum server_fd_type file_type
;
1065 union unix_sockaddr addr
;
1071 addr_len
= sizeof(addr
);
1072 if (getpeername( fd
, &addr
.addr
, &addr_len
) != 0)
1073 return STATUS_INVALID_CONNECTION
;
1077 if ((status
= server_get_unix_fd( params
->file
, 0, &file_fd
, &file_needs_close
, &file_type
, NULL
)))
1079 if (file_needs_close
) close( file_fd
);
1081 if (file_type
!= FD_TYPE_FILE
)
1083 FIXME( "unsupported file type %#x\n", file_type
);
1084 return STATUS_NOT_IMPLEMENTED
;
1088 if (!(async
= (struct async_transmit_ioctl
*)alloc_fileio( sizeof(*async
), async_transmit_proc
, handle
)))
1089 return STATUS_NO_MEMORY
;
1091 async
->file
= params
->file
;
1092 async
->buffer_size
= params
->buffer_size
? params
->buffer_size
: 65536;
1093 if (!(async
->buffer
= malloc( async
->buffer_size
)))
1095 release_fileio( &async
->io
);
1096 return STATUS_NO_MEMORY
;
1098 async
->read_len
= 0;
1099 async
->head_cursor
= 0;
1100 async
->file_cursor
= 0;
1101 async
->buffer_cursor
= 0;
1102 async
->tail_cursor
= 0;
1103 async
->file_len
= params
->file_len
;
1104 async
->flags
= params
->flags
;
1105 async
->buffers
= params
->buffers
;
1106 async
->offset
= params
->offset
;
1108 SERVER_START_REQ( send_socket
)
1110 req
->status
= STATUS_PENDING
;
1112 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, io
);
1113 status
= wine_server_call( req
);
1114 wait_handle
= wine_server_ptr_handle( reply
->wait
);
1115 options
= reply
->options
;
1116 /* In theory we'd fill the iosb here, as above in sock_send(), but it's
1117 * actually currently impossible to get STATUS_SUCCESS. The server will
1118 * either return STATUS_PENDING or an error code, and in neither case
1119 * should the iosb be filled. */
1123 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
1125 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
1129 static void complete_async( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
1130 IO_STATUS_BLOCK
*io
, NTSTATUS status
, ULONG_PTR information
)
1132 io
->Status
= status
;
1133 io
->Information
= information
;
1134 if (event
) NtSetEvent( event
, NULL
);
1135 if (apc
) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC
)apc
, (ULONG_PTR
)apc_user
, (ULONG_PTR
)io
, 0 );
1136 if (apc_user
) add_completion( handle
, (ULONG_PTR
)apc_user
, status
, information
, FALSE
);
1140 static NTSTATUS
do_getsockopt( HANDLE handle
, IO_STATUS_BLOCK
*io
, int level
,
1141 int option
, void *out_buffer
, ULONG out_size
)
1143 int fd
, needs_close
= FALSE
;
1144 socklen_t len
= out_size
;
1148 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1151 ret
= getsockopt( fd
, level
, option
, out_buffer
, &len
);
1152 if (needs_close
) close( fd
);
1153 if (ret
) return sock_errno_to_status( errno
);
1154 io
->Information
= len
;
1155 return STATUS_SUCCESS
;
1159 static NTSTATUS
do_setsockopt( HANDLE handle
, IO_STATUS_BLOCK
*io
, int level
,
1160 int option
, const void *optval
, socklen_t optlen
)
1162 int fd
, needs_close
= FALSE
;
1166 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1169 ret
= setsockopt( fd
, level
, option
, optval
, optlen
);
1170 if (needs_close
) close( fd
);
1171 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1175 NTSTATUS
sock_ioctl( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
1176 ULONG code
, void *in_buffer
, ULONG in_size
, void *out_buffer
, ULONG out_size
)
1178 int fd
, needs_close
= FALSE
;
1181 TRACE( "handle %p, code %#x, in_buffer %p, in_size %u, out_buffer %p, out_size %u\n",
1182 handle
, code
, in_buffer
, in_size
, out_buffer
, out_size
);
1186 case IOCTL_AFD_BIND
:
1188 const struct afd_bind_params
*params
= in_buffer
;
1190 if (params
->unknown
) FIXME( "bind: got unknown %#x\n", params
->unknown
);
1192 status
= STATUS_BAD_DEVICE_TYPE
;
1196 case IOCTL_AFD_GETSOCKNAME
:
1197 if (in_size
) FIXME( "unexpected input size %u\n", in_size
);
1199 status
= STATUS_BAD_DEVICE_TYPE
;
1202 case IOCTL_AFD_LISTEN
:
1204 const struct afd_listen_params
*params
= in_buffer
;
1206 TRACE( "backlog %u\n", params
->backlog
);
1207 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1208 if (params
->unknown1
) FIXME( "listen: got unknown1 %#x\n", params
->unknown1
);
1209 if (params
->unknown2
) FIXME( "listen: got unknown2 %#x\n", params
->unknown2
);
1211 status
= STATUS_BAD_DEVICE_TYPE
;
1215 case IOCTL_AFD_EVENT_SELECT
:
1217 const struct afd_event_select_params
*params
= in_buffer
;
1219 TRACE( "event %p, mask %#x\n", params
->event
, params
->mask
);
1220 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1222 status
= STATUS_BAD_DEVICE_TYPE
;
1226 case IOCTL_AFD_GET_EVENTS
:
1227 if (in_size
) FIXME( "unexpected input size %u\n", in_size
);
1229 status
= STATUS_BAD_DEVICE_TYPE
;
1232 case IOCTL_AFD_RECV
:
1234 const struct afd_recv_params
*params
= in_buffer
;
1237 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1240 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1242 if (in_size
< sizeof(struct afd_recv_params
))
1244 status
= STATUS_INVALID_PARAMETER
;
1248 if ((params
->msg_flags
& (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
)) == 0 ||
1249 (params
->msg_flags
& (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
)) == (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
))
1251 status
= STATUS_INVALID_PARAMETER
;
1255 if (params
->msg_flags
& ~(AFD_MSG_NOT_OOB
| AFD_MSG_OOB
| AFD_MSG_PEEK
| AFD_MSG_WAITALL
))
1256 FIXME( "unknown msg_flags %#x\n", params
->msg_flags
);
1257 if (params
->recv_flags
& ~AFD_RECV_FORCE_ASYNC
)
1258 FIXME( "unknown recv_flags %#x\n", params
->recv_flags
);
1260 if (params
->msg_flags
& AFD_MSG_OOB
)
1261 unix_flags
|= MSG_OOB
;
1262 if (params
->msg_flags
& AFD_MSG_PEEK
)
1263 unix_flags
|= MSG_PEEK
;
1264 if (params
->msg_flags
& AFD_MSG_WAITALL
)
1265 FIXME( "MSG_WAITALL is not supported\n" );
1267 status
= sock_recv( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
, NULL
,
1268 NULL
, NULL
, NULL
, unix_flags
, !!(params
->recv_flags
& AFD_RECV_FORCE_ASYNC
) );
1272 case IOCTL_AFD_WINE_RECVMSG
:
1274 struct afd_recvmsg_params
*params
= in_buffer
;
1277 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1280 if (in_size
< sizeof(*params
))
1282 status
= STATUS_BUFFER_TOO_SMALL
;
1286 if (*params
->ws_flags
& WS_MSG_OOB
)
1287 unix_flags
|= MSG_OOB
;
1288 if (*params
->ws_flags
& WS_MSG_PEEK
)
1289 unix_flags
|= MSG_PEEK
;
1290 if (*params
->ws_flags
& WS_MSG_WAITALL
)
1291 FIXME( "MSG_WAITALL is not supported\n" );
1293 status
= sock_recv( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
, params
->control
,
1294 params
->addr
, params
->addr_len
, params
->ws_flags
, unix_flags
, params
->force_async
);
1298 case IOCTL_AFD_WINE_SENDMSG
:
1300 const struct afd_sendmsg_params
*params
= in_buffer
;
1303 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1306 if (in_size
< sizeof(*params
))
1308 status
= STATUS_BUFFER_TOO_SMALL
;
1312 if (params
->ws_flags
& WS_MSG_OOB
)
1313 unix_flags
|= MSG_OOB
;
1314 if (params
->ws_flags
& WS_MSG_PARTIAL
)
1315 WARN( "ignoring MSG_PARTIAL\n" );
1316 if (params
->ws_flags
& ~(WS_MSG_OOB
| WS_MSG_PARTIAL
))
1317 FIXME( "unknown flags %#x\n", params
->ws_flags
);
1319 status
= sock_send( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
,
1320 params
->addr
, params
->addr_len
, unix_flags
, params
->force_async
);
1324 case IOCTL_AFD_WINE_TRANSMIT
:
1326 const struct afd_transmit_params
*params
= in_buffer
;
1328 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1331 if (in_size
< sizeof(*params
))
1333 status
= STATUS_BUFFER_TOO_SMALL
;
1337 status
= sock_transmit( handle
, event
, apc
, apc_user
, io
, fd
, params
);
1341 case IOCTL_AFD_WINE_COMPLETE_ASYNC
:
1343 if (in_size
!= sizeof(NTSTATUS
))
1344 return STATUS_BUFFER_TOO_SMALL
;
1346 status
= *(NTSTATUS
*)in_buffer
;
1347 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1351 case IOCTL_AFD_POLL
:
1352 status
= sock_poll( handle
, event
, apc
, apc_user
, io
, in_buffer
, in_size
, out_buffer
, out_size
);
1355 case IOCTL_AFD_WINE_FIONREAD
:
1359 if (out_size
< sizeof(int))
1361 status
= STATUS_BUFFER_TOO_SMALL
;
1365 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1370 socklen_t len
= sizeof(value
);
1372 /* FIONREAD on a listening socket always fails (see tcp(7)). */
1373 if (!getsockopt( fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &value
, &len
) && value
)
1375 *(int *)out_buffer
= 0;
1376 status
= STATUS_SUCCESS
;
1377 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1383 if ((ret
= ioctl( fd
, FIONREAD
, &value
)) < 0)
1385 status
= sock_errno_to_status( errno
);
1388 *(int *)out_buffer
= value
;
1389 status
= STATUS_SUCCESS
;
1390 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1394 case IOCTL_AFD_WINE_SIOCATMARK
:
1397 socklen_t len
= sizeof(value
);
1399 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1402 if (out_size
< sizeof(int))
1404 status
= STATUS_BUFFER_TOO_SMALL
;
1408 if (getsockopt( fd
, SOL_SOCKET
, SO_OOBINLINE
, &value
, &len
) < 0)
1410 status
= sock_errno_to_status( errno
);
1416 *(int *)out_buffer
= TRUE
;
1420 if ((ret
= ioctl( fd
, SIOCATMARK
, &value
)) < 0)
1422 status
= sock_errno_to_status( errno
);
1425 /* windows is reversed with respect to unix */
1426 *(int *)out_buffer
= !value
;
1428 status
= STATUS_SUCCESS
;
1429 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1433 case IOCTL_AFD_WINE_GET_INTERFACE_LIST
:
1435 #ifdef HAVE_GETIFADDRS
1436 INTERFACE_INFO
*info
= out_buffer
;
1437 struct ifaddrs
*ifaddrs
, *ifaddr
;
1438 unsigned int count
= 0;
1441 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1444 if (getifaddrs( &ifaddrs
) < 0)
1446 status
= sock_errno_to_status( errno
);
1450 for (ifaddr
= ifaddrs
; ifaddr
!= NULL
; ifaddr
= ifaddr
->ifa_next
)
1452 if (ifaddr
->ifa_addr
&& ifaddr
->ifa_addr
->sa_family
== AF_INET
) ++count
;
1455 ret_size
= count
* sizeof(*info
);
1456 if (out_size
< ret_size
)
1458 status
= STATUS_PENDING
;
1459 complete_async( handle
, event
, apc
, apc_user
, io
, STATUS_BUFFER_TOO_SMALL
, 0 );
1460 freeifaddrs( ifaddrs
);
1464 memset( out_buffer
, 0, ret_size
);
1467 for (ifaddr
= ifaddrs
; ifaddr
!= NULL
; ifaddr
= ifaddr
->ifa_next
)
1469 in_addr_t addr
, mask
;
1471 if (!ifaddr
->ifa_addr
|| ifaddr
->ifa_addr
->sa_family
!= AF_INET
)
1474 addr
= ((const struct sockaddr_in
*)ifaddr
->ifa_addr
)->sin_addr
.s_addr
;
1475 mask
= ((const struct sockaddr_in
*)ifaddr
->ifa_netmask
)->sin_addr
.s_addr
;
1477 info
[count
].iiFlags
= 0;
1478 if (ifaddr
->ifa_flags
& IFF_BROADCAST
)
1479 info
[count
].iiFlags
|= WS_IFF_BROADCAST
;
1480 if (ifaddr
->ifa_flags
& IFF_LOOPBACK
)
1481 info
[count
].iiFlags
|= WS_IFF_LOOPBACK
;
1482 if (ifaddr
->ifa_flags
& IFF_MULTICAST
)
1483 info
[count
].iiFlags
|= WS_IFF_MULTICAST
;
1484 #ifdef IFF_POINTTOPOINT
1485 if (ifaddr
->ifa_flags
& IFF_POINTTOPOINT
)
1486 info
[count
].iiFlags
|= WS_IFF_POINTTOPOINT
;
1488 if (ifaddr
->ifa_flags
& IFF_UP
)
1489 info
[count
].iiFlags
|= WS_IFF_UP
;
1491 info
[count
].iiAddress
.AddressIn
.sin_family
= WS_AF_INET
;
1492 info
[count
].iiAddress
.AddressIn
.sin_port
= 0;
1493 info
[count
].iiAddress
.AddressIn
.sin_addr
.WS_s_addr
= addr
;
1495 info
[count
].iiNetmask
.AddressIn
.sin_family
= WS_AF_INET
;
1496 info
[count
].iiNetmask
.AddressIn
.sin_port
= 0;
1497 info
[count
].iiNetmask
.AddressIn
.sin_addr
.WS_s_addr
= mask
;
1499 if (ifaddr
->ifa_flags
& IFF_BROADCAST
)
1501 info
[count
].iiBroadcastAddress
.AddressIn
.sin_family
= WS_AF_INET
;
1502 info
[count
].iiBroadcastAddress
.AddressIn
.sin_port
= 0;
1503 info
[count
].iiBroadcastAddress
.AddressIn
.sin_addr
.WS_s_addr
= addr
| ~mask
;
1509 freeifaddrs( ifaddrs
);
1510 status
= STATUS_PENDING
;
1511 complete_async( handle
, event
, apc
, apc_user
, io
, STATUS_SUCCESS
, ret_size
);
1513 FIXME( "Interface list queries are currently not supported on this platform.\n" );
1514 status
= STATUS_NOT_SUPPORTED
;
1519 case IOCTL_AFD_WINE_KEEPALIVE_VALS
:
1521 struct tcp_keepalive
*k
= in_buffer
;
1524 if (!in_buffer
|| in_size
< sizeof(struct tcp_keepalive
))
1525 return STATUS_BUFFER_TOO_SMALL
;
1526 keepalive
= !!k
->onoff
;
1528 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1531 if (setsockopt( fd
, SOL_SOCKET
, SO_KEEPALIVE
, &keepalive
, sizeof(int) ) < 0)
1533 status
= STATUS_INVALID_PARAMETER
;
1540 int idle
= max( 1, (k
->keepalivetime
+ 500) / 1000 );
1542 if (setsockopt( fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, &idle
, sizeof(int) ) < 0)
1544 status
= STATUS_INVALID_PARAMETER
;
1548 FIXME("ignoring keepalive timeout\n");
1554 #ifdef TCP_KEEPINTVL
1555 int interval
= max( 1, (k
->keepaliveinterval
+ 500) / 1000 );
1557 if (setsockopt( fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, &interval
, sizeof(int) ) < 0)
1558 status
= STATUS_INVALID_PARAMETER
;
1560 FIXME("ignoring keepalive interval\n");
1564 status
= STATUS_SUCCESS
;
1565 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1569 case IOCTL_AFD_WINE_GETPEERNAME
:
1571 union unix_sockaddr unix_addr
;
1572 socklen_t unix_len
= sizeof(unix_addr
);
1575 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1578 if (getpeername( fd
, &unix_addr
.addr
, &unix_len
) < 0)
1580 status
= sock_errno_to_status( errno
);
1584 len
= sockaddr_from_unix( &unix_addr
, out_buffer
, out_size
);
1587 status
= STATUS_BUFFER_TOO_SMALL
;
1590 io
->Information
= len
;
1591 status
= STATUS_SUCCESS
;
1595 case IOCTL_AFD_WINE_GET_SO_BROADCAST
:
1596 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_BROADCAST
, out_buffer
, out_size
);
1598 case IOCTL_AFD_WINE_SET_SO_BROADCAST
:
1599 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_BROADCAST
, in_buffer
, in_size
);
1601 case IOCTL_AFD_WINE_GET_SO_KEEPALIVE
:
1602 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_KEEPALIVE
, out_buffer
, out_size
);
1604 case IOCTL_AFD_WINE_SET_SO_KEEPALIVE
:
1605 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_KEEPALIVE
, in_buffer
, in_size
);
1607 case IOCTL_AFD_WINE_GET_SO_LINGER
:
1609 struct WS_linger
*ws_linger
= out_buffer
;
1610 struct linger unix_linger
;
1611 socklen_t len
= sizeof(unix_linger
);
1614 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1617 ret
= getsockopt( fd
, SOL_SOCKET
, SO_LINGER
, &unix_linger
, &len
);
1618 if (needs_close
) close( fd
);
1621 ws_linger
->l_onoff
= unix_linger
.l_onoff
;
1622 ws_linger
->l_linger
= unix_linger
.l_linger
;
1623 io
->Information
= sizeof(*ws_linger
);
1626 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1629 case IOCTL_AFD_WINE_SET_SO_LINGER
:
1631 const struct WS_linger
*ws_linger
= in_buffer
;
1632 struct linger unix_linger
;
1634 unix_linger
.l_onoff
= ws_linger
->l_onoff
;
1635 unix_linger
.l_linger
= ws_linger
->l_linger
;
1637 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_LINGER
, &unix_linger
, sizeof(unix_linger
) );
1640 case IOCTL_AFD_WINE_GET_SO_OOBINLINE
:
1641 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_OOBINLINE
, out_buffer
, out_size
);
1643 case IOCTL_AFD_WINE_SET_SO_OOBINLINE
:
1644 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_OOBINLINE
, in_buffer
, in_size
);
1646 case IOCTL_AFD_WINE_GET_SO_REUSEADDR
:
1647 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_REUSEADDR
, out_buffer
, out_size
);
1649 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics;
1650 * however, using it the BSD way fixes bug 8513 and seems to be what
1651 * most programmers assume, anyway */
1652 case IOCTL_AFD_WINE_SET_SO_REUSEADDR
:
1654 int fd
, needs_close
= FALSE
;
1658 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1661 ret
= setsockopt( fd
, SOL_SOCKET
, SO_REUSEADDR
, in_buffer
, in_size
);
1663 if (!ret
) ret
= setsockopt( fd
, SOL_SOCKET
, SO_REUSEPORT
, in_buffer
, in_size
);
1665 if (needs_close
) close( fd
);
1666 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1669 case IOCTL_AFD_WINE_SET_IP_ADD_MEMBERSHIP
:
1670 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, in_buffer
, in_size
);
1672 case IOCTL_AFD_WINE_SET_IP_ADD_SOURCE_MEMBERSHIP
:
1673 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_ADD_SOURCE_MEMBERSHIP
, in_buffer
, in_size
);
1675 case IOCTL_AFD_WINE_SET_IP_BLOCK_SOURCE
:
1676 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_BLOCK_SOURCE
, in_buffer
, in_size
);
1678 case IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT
:
1680 socklen_t len
= out_size
;
1683 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1687 ret
= getsockopt( fd
, IPPROTO_IP
, IP_DONTFRAG
, out_buffer
, &len
);
1688 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1692 len
= sizeof(value
);
1693 ret
= getsockopt( fd
, IPPROTO_IP
, IP_MTU_DISCOVER
, &value
, &len
);
1694 if (!ret
) *(DWORD
*)out_buffer
= (value
!= IP_PMTUDISC_DONT
);
1701 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
1702 ret
= 0; /* fake success */
1705 if (needs_close
) close( fd
);
1706 if (ret
) return sock_errno_to_status( errno
);
1707 io
->Information
= len
;
1708 return STATUS_SUCCESS
;
1711 case IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT
:
1713 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DONTFRAG
, in_buffer
, in_size
);
1714 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT)
1716 int value
= *(DWORD
*)in_buffer
? IP_PMTUDISC_DO
: IP_PMTUDISC_DONT
;
1718 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MTU_DISCOVER
, &value
, sizeof(value
) );
1725 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
1726 return STATUS_SUCCESS
; /* fake success */
1730 case IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP
:
1731 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, in_buffer
, in_size
);
1733 case IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP
:
1734 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DROP_SOURCE_MEMBERSHIP
, in_buffer
, in_size
);
1737 case IOCTL_AFD_WINE_GET_IP_HDRINCL
:
1738 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_HDRINCL
, out_buffer
, out_size
);
1740 case IOCTL_AFD_WINE_SET_IP_HDRINCL
:
1741 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_HDRINCL
, in_buffer
, in_size
);
1744 case IOCTL_AFD_WINE_GET_IP_MULTICAST_IF
:
1745 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_IF
, out_buffer
, out_size
);
1747 case IOCTL_AFD_WINE_SET_IP_MULTICAST_IF
:
1748 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_IF
, in_buffer
, in_size
);
1750 case IOCTL_AFD_WINE_GET_IP_MULTICAST_LOOP
:
1751 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_LOOP
, out_buffer
, out_size
);
1753 case IOCTL_AFD_WINE_SET_IP_MULTICAST_LOOP
:
1754 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_LOOP
, in_buffer
, in_size
);
1756 case IOCTL_AFD_WINE_GET_IP_MULTICAST_TTL
:
1757 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_TTL
, out_buffer
, out_size
);
1759 case IOCTL_AFD_WINE_SET_IP_MULTICAST_TTL
:
1760 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_TTL
, in_buffer
, in_size
);
1762 case IOCTL_AFD_WINE_GET_IP_OPTIONS
:
1763 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_OPTIONS
, out_buffer
, out_size
);
1765 case IOCTL_AFD_WINE_SET_IP_OPTIONS
:
1766 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_OPTIONS
, in_buffer
, in_size
);
1769 case IOCTL_AFD_WINE_GET_IP_PKTINFO
:
1770 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_PKTINFO
, out_buffer
, out_size
);
1772 case IOCTL_AFD_WINE_SET_IP_PKTINFO
:
1773 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_PKTINFO
, in_buffer
, in_size
);
1774 #elif defined(IP_RECVDSTADDR)
1775 case IOCTL_AFD_WINE_GET_IP_PKTINFO
:
1776 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_RECVDSTADDR
, out_buffer
, out_size
);
1778 case IOCTL_AFD_WINE_SET_IP_PKTINFO
:
1779 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_RECVDSTADDR
, in_buffer
, in_size
);
1782 case IOCTL_AFD_WINE_GET_IP_TOS
:
1783 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_TOS
, out_buffer
, out_size
);
1785 case IOCTL_AFD_WINE_SET_IP_TOS
:
1786 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_TOS
, in_buffer
, in_size
);
1788 case IOCTL_AFD_WINE_GET_IP_TTL
:
1789 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_TTL
, out_buffer
, out_size
);
1791 case IOCTL_AFD_WINE_SET_IP_TTL
:
1792 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_TTL
, in_buffer
, in_size
);
1794 case IOCTL_AFD_WINE_SET_IP_UNBLOCK_SOURCE
:
1795 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_UNBLOCK_SOURCE
, in_buffer
, in_size
);
1797 #ifdef IP_UNICAST_IF
1798 case IOCTL_AFD_WINE_GET_IP_UNICAST_IF
:
1799 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_UNICAST_IF
, out_buffer
, out_size
);
1801 case IOCTL_AFD_WINE_SET_IP_UNICAST_IF
:
1802 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_UNICAST_IF
, in_buffer
, in_size
);
1805 #ifdef IPV6_ADD_MEMBERSHIP
1806 case IOCTL_AFD_WINE_SET_IPV6_ADD_MEMBERSHIP
:
1807 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
, in_buffer
, in_size
);
1810 case IOCTL_AFD_WINE_GET_IPV6_DONTFRAG
:
1812 socklen_t len
= out_size
;
1815 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1818 #ifdef IPV6_DONTFRAG
1819 ret
= getsockopt( fd
, IPPROTO_IPV6
, IPV6_DONTFRAG
, out_buffer
, &len
);
1820 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
1824 len
= sizeof(value
);
1825 ret
= getsockopt( fd
, IPPROTO_IPV6
, IPV6_MTU_DISCOVER
, &value
, &len
);
1826 if (!ret
) *(DWORD
*)out_buffer
= (value
!= IPV6_PMTUDISC_DONT
);
1833 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
1834 ret
= 0; /* fake success */
1837 if (needs_close
) close( fd
);
1838 if (ret
) return sock_errno_to_status( errno
);
1839 io
->Information
= len
;
1840 return STATUS_SUCCESS
;
1843 case IOCTL_AFD_WINE_SET_IPV6_DONTFRAG
:
1844 #ifdef IPV6_DONTFRAG
1845 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_DONTFRAG
, in_buffer
, in_size
);
1846 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT)
1848 int value
= *(DWORD
*)in_buffer
? IPV6_PMTUDISC_DO
: IPV6_PMTUDISC_DONT
;
1850 return do_setsockopt( handle
, io
, IPPROTO_IP
, IPV6_MTU_DISCOVER
, &value
, sizeof(value
) );
1857 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
1858 return STATUS_SUCCESS
; /* fake success */
1862 #ifdef IPV6_DROP_MEMBERSHIP
1863 case IOCTL_AFD_WINE_SET_IPV6_DROP_MEMBERSHIP
:
1864 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_DROP_MEMBERSHIP
, in_buffer
, in_size
);
1867 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS
:
1868 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, out_buffer
, out_size
);
1870 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS
:
1871 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, in_buffer
, in_size
);
1873 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_IF
:
1874 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, out_buffer
, out_size
);
1876 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF
:
1877 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, in_buffer
, in_size
);
1879 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP
:
1880 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, out_buffer
, out_size
);
1882 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP
:
1883 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, in_buffer
, in_size
);
1885 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS
:
1886 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, out_buffer
, out_size
);
1888 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS
:
1889 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, in_buffer
, in_size
);
1891 #ifdef IPV6_UNICAST_IF
1892 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF
:
1893 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, out_buffer
, out_size
);
1895 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF
:
1896 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, in_buffer
, in_size
);
1899 case IOCTL_AFD_WINE_GET_IPV6_V6ONLY
:
1900 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_V6ONLY
, out_buffer
, out_size
);
1902 case IOCTL_AFD_WINE_SET_IPV6_V6ONLY
:
1904 int fd
, needs_close
= FALSE
;
1905 union unix_sockaddr addr
;
1906 socklen_t len
= sizeof(addr
);
1910 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1913 if (!getsockname( fd
, &addr
.addr
, &len
) && addr
.addr
.sa_family
== AF_INET
&& !addr
.in
.sin_port
)
1915 /* changing IPV6_V6ONLY succeeds on an unbound IPv4 socket */
1916 WARN( "ignoring IPV6_V6ONLY on an unbound IPv4 socket\n" );
1917 return STATUS_SUCCESS
;
1920 ret
= setsockopt( fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, in_buffer
, in_size
);
1921 if (needs_close
) close( fd
);
1922 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1926 case IOCTL_AFD_WINE_GET_IPX_PTYPE
:
1927 return do_getsockopt( handle
, io
, SOL_IPX
, IPX_TYPE
, out_buffer
, out_size
);
1929 case IOCTL_AFD_WINE_SET_IPX_PTYPE
:
1930 return do_setsockopt( handle
, io
, SOL_IPX
, IPX_TYPE
, in_buffer
, in_size
);
1931 #elif defined(SO_DEFAULT_HEADERS)
1932 case IOCTL_AFD_WINE_GET_IPX_PTYPE
:
1934 int fd
, needs_close
= FALSE
;
1936 socklen_t len
= sizeof(value
);
1939 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1942 ret
= getsockopt( fd
, 0, SO_DEFAULT_HEADERS
, &value
, &len
);
1943 if (needs_close
) close( fd
);
1944 if (ret
) return sock_errno_to_status( errno
);
1945 *(DWORD
*)out_buffer
= value
.ipx_pt
;
1946 return STATUS_SUCCESS
;
1949 case IOCTL_AFD_WINE_SET_IPX_PTYPE
:
1951 struct ipx value
= {0};
1953 /* FIXME: should we retrieve SO_DEFAULT_HEADERS first and modify it? */
1954 value
.ipx_pt
= *(DWORD
*)in_buffer
;
1955 return do_setsockopt( handle
, io
, 0, SO_DEFAULT_HEADERS
, &value
, sizeof(value
) );
1960 #define MAX_IRDA_DEVICES 10
1961 case IOCTL_AFD_WINE_GET_IRLMP_ENUMDEVICES
:
1963 char buffer
[offsetof( struct irda_device_list
, dev
[MAX_IRDA_DEVICES
] )];
1964 struct irda_device_list
*unix_list
= (struct irda_device_list
*)buffer
;
1965 socklen_t len
= sizeof(buffer
);
1966 DEVICELIST
*ws_list
= out_buffer
;
1967 int fd
, needs_close
= FALSE
;
1972 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1975 ret
= getsockopt( fd
, SOL_IRLMP
, IRLMP_ENUMDEVICES
, buffer
, &len
);
1976 if (needs_close
) close( fd
);
1977 if (ret
) return sock_errno_to_status( errno
);
1979 io
->Information
= offsetof( DEVICELIST
, unix_list
->len
);
1980 if (out_size
< io
->Information
)
1981 return STATUS_BUFFER_TOO_SMALL
;
1983 TRACE( "IRLMP_ENUMDEVICES: got %u devices:\n", unix_list
->len
);
1984 ws_list
->numDevice
= unix_list
->len
;
1985 for (i
= 0; i
< unix_list
->len
; ++i
)
1987 const struct irda_device_info
*unix_dev
= &unix_list
->dev
[i
];
1988 IRDA_DEVICE_INFO
*ws_dev
= &ws_list
->Device
[i
];
1990 TRACE( "saddr %#08x, daddr %#08x, info %s, hints 0x%02x%02x\n",
1991 unix_dev
->saddr
, unix_dev
->daddr
, unix_dev
->info
, unix_dev
->hints
[0], unix_dev
->hints
[1] );
1992 memcpy( ws_dev
->irdaDeviceID
, &unix_dev
->daddr
, sizeof(unix_dev
->daddr
) );
1993 memcpy( ws_dev
->irdaDeviceName
, unix_dev
->info
, sizeof(unix_dev
->info
) );
1994 ws_dev
->irdaDeviceHints1
= unix_dev
->hints
[0];
1995 ws_dev
->irdaDeviceHints2
= unix_dev
->hints
[1];
1996 ws_dev
->irdaCharSet
= unix_dev
->charset
;
1998 return STATUS_SUCCESS
;
2002 case IOCTL_AFD_WINE_GET_TCP_NODELAY
:
2003 return do_getsockopt( handle
, io
, IPPROTO_TCP
, TCP_NODELAY
, out_buffer
, out_size
);
2005 case IOCTL_AFD_WINE_SET_TCP_NODELAY
:
2006 return do_setsockopt( handle
, io
, IPPROTO_TCP
, TCP_NODELAY
, in_buffer
, in_size
);
2010 if ((code
>> 16) == FILE_DEVICE_NETWORK
)
2012 /* Wine-internal ioctl */
2013 status
= STATUS_BAD_DEVICE_TYPE
;
2017 FIXME( "Unknown ioctl %#x (device %#x, access %#x, function %#x, method %#x)\n",
2018 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3 );
2019 status
= STATUS_INVALID_DEVICE_REQUEST
;
2025 if (needs_close
) close( fd
);