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
26 #define _GNU_SOURCE /* for struct in6_pktinfo */
28 #include <sys/types.h>
36 #ifdef HAVE_SYS_IOCTL_H
37 # include <sys/ioctl.h>
39 #ifdef HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
42 #ifdef HAVE_NETINET_IN_H
43 # define __APPLE_USE_RFC_3542
44 # include <netinet/in.h>
46 #ifdef HAVE_NETINET_TCP_H
47 # include <netinet/tcp.h>
50 #ifdef HAVE_NETIPX_IPX_H
51 # include <netipx/ipx.h>
52 #elif defined(HAVE_LINUX_IPX_H)
53 # ifdef HAVE_ASM_TYPES_H
54 # include <asm/types.h>
56 # ifdef HAVE_LINUX_TYPES_H
57 # include <linux/types.h>
59 # include <linux/ipx.h>
61 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
65 #ifdef HAVE_LINUX_IRDA_H
66 # ifdef HAVE_LINUX_TYPES_H
67 # include <linux/types.h>
69 # include <linux/irda.h>
74 #define WIN32_NO_STATUS
86 #include "unix_private.h"
88 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
89 /* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */
90 #define TCP_KEEPIDLE TCP_KEEPALIVE
93 #if defined(linux) && !defined(IP_UNICAST_IF)
94 #define IP_UNICAST_IF 50
97 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
101 struct sockaddr addr
;
102 struct sockaddr_in in
;
103 struct sockaddr_in6 in6
;
105 struct sockaddr_ipx ipx
;
108 struct sockaddr_irda irda
;
112 struct async_recv_ioctl
114 struct async_fileio io
;
116 struct WS_sockaddr
*addr
;
124 struct async_send_ioctl
126 struct async_fileio io
;
127 const struct WS_sockaddr
*addr
;
130 unsigned int sent_len
;
132 unsigned int iov_cursor
;
136 struct async_transmit_ioctl
138 struct async_fileio io
;
141 unsigned int buffer_size
; /* allocated size of buffer */
142 unsigned int read_len
; /* amount of valid data currently in the buffer */
143 unsigned int head_cursor
; /* amount of header data already sent */
144 unsigned int file_cursor
; /* amount of file data already sent */
145 unsigned int buffer_cursor
; /* amount of data currently in the buffer already sent */
146 unsigned int tail_cursor
; /* amount of tail data already sent */
147 unsigned int file_len
; /* total file length to send */
149 TRANSMIT_FILE_BUFFERS buffers
;
150 LARGE_INTEGER offset
;
153 static NTSTATUS
sock_errno_to_status( int err
)
157 case EBADF
: return STATUS_INVALID_HANDLE
;
158 case EBUSY
: return STATUS_DEVICE_BUSY
;
160 case EACCES
: return STATUS_ACCESS_DENIED
;
161 case EFAULT
: return STATUS_ACCESS_VIOLATION
;
162 case EINVAL
: return STATUS_INVALID_PARAMETER
;
164 case EMFILE
: return STATUS_TOO_MANY_OPENED_FILES
;
166 case EWOULDBLOCK
: return STATUS_DEVICE_NOT_READY
;
167 case EALREADY
: return STATUS_NETWORK_BUSY
;
168 case ENOTSOCK
: return STATUS_OBJECT_TYPE_MISMATCH
;
169 case EDESTADDRREQ
: return STATUS_INVALID_PARAMETER
;
170 case EMSGSIZE
: return STATUS_BUFFER_OVERFLOW
;
171 case EPROTONOSUPPORT
:
172 case ESOCKTNOSUPPORT
:
175 case EPROTOTYPE
: return STATUS_NOT_SUPPORTED
;
176 case ENOPROTOOPT
: return STATUS_INVALID_PARAMETER
;
177 case EOPNOTSUPP
: return STATUS_NOT_SUPPORTED
;
178 case EADDRINUSE
: return STATUS_SHARING_VIOLATION
;
179 case EADDRNOTAVAIL
: return STATUS_INVALID_PARAMETER
;
180 case ECONNREFUSED
: return STATUS_CONNECTION_REFUSED
;
181 case ESHUTDOWN
: return STATUS_PIPE_DISCONNECTED
;
182 case ENOTCONN
: return STATUS_INVALID_CONNECTION
;
183 case ETIMEDOUT
: return STATUS_IO_TIMEOUT
;
184 case ENETUNREACH
: return STATUS_NETWORK_UNREACHABLE
;
185 case EHOSTUNREACH
: return STATUS_HOST_UNREACHABLE
;
186 case ENETDOWN
: return STATUS_NETWORK_BUSY
;
188 case ECONNRESET
: return STATUS_CONNECTION_RESET
;
189 case ECONNABORTED
: return STATUS_CONNECTION_ABORTED
;
190 case EISCONN
: return STATUS_CONNECTION_ACTIVE
;
192 case 0: return STATUS_SUCCESS
;
194 FIXME( "unknown errno %d\n", err
);
195 return STATUS_UNSUCCESSFUL
;
199 static socklen_t
sockaddr_to_unix( const struct WS_sockaddr
*wsaddr
, int wsaddrlen
, union unix_sockaddr
*uaddr
)
201 memset( uaddr
, 0, sizeof(*uaddr
) );
203 switch (wsaddr
->sa_family
)
207 struct WS_sockaddr_in win
= {0};
209 if (wsaddrlen
< sizeof(win
)) return 0;
210 memcpy( &win
, wsaddr
, sizeof(win
) );
211 uaddr
->in
.sin_family
= AF_INET
;
212 uaddr
->in
.sin_port
= win
.sin_port
;
213 memcpy( &uaddr
->in
.sin_addr
, &win
.sin_addr
, sizeof(win
.sin_addr
) );
214 return sizeof(uaddr
->in
);
219 struct WS_sockaddr_in6 win
= {0};
221 if (wsaddrlen
< sizeof(win
)) return 0;
222 memcpy( &win
, wsaddr
, sizeof(win
) );
223 uaddr
->in6
.sin6_family
= AF_INET6
;
224 uaddr
->in6
.sin6_port
= win
.sin6_port
;
225 uaddr
->in6
.sin6_flowinfo
= win
.sin6_flowinfo
;
226 memcpy( &uaddr
->in6
.sin6_addr
, &win
.sin6_addr
, sizeof(win
.sin6_addr
) );
227 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
228 uaddr
->in6
.sin6_scope_id
= win
.sin6_scope_id
;
230 return sizeof(uaddr
->in6
);
236 struct WS_sockaddr_ipx win
= {0};
238 if (wsaddrlen
< sizeof(win
)) return 0;
239 memcpy( &win
, wsaddr
, sizeof(win
) );
240 uaddr
->ipx
.sipx_family
= AF_IPX
;
241 memcpy( &uaddr
->ipx
.sipx_network
, win
.sa_netnum
, sizeof(win
.sa_netnum
) );
242 memcpy( &uaddr
->ipx
.sipx_node
, win
.sa_nodenum
, sizeof(win
.sa_nodenum
) );
243 uaddr
->ipx
.sipx_port
= win
.sa_socket
;
244 return sizeof(uaddr
->ipx
);
251 SOCKADDR_IRDA win
= {0};
252 unsigned int lsap_sel
;
254 if (wsaddrlen
< sizeof(win
)) return 0;
255 memcpy( &win
, wsaddr
, sizeof(win
) );
256 uaddr
->irda
.sir_family
= AF_IRDA
;
257 if (sscanf( win
.irdaServiceName
, "LSAP-SEL%u", &lsap_sel
) == 1)
258 uaddr
->irda
.sir_lsap_sel
= lsap_sel
;
261 uaddr
->irda
.sir_lsap_sel
= LSAP_ANY
;
262 memcpy( uaddr
->irda
.sir_name
, win
.irdaServiceName
, sizeof(win
.irdaServiceName
) );
264 memcpy( &uaddr
->irda
.sir_addr
, win
.irdaDeviceID
, sizeof(win
.irdaDeviceID
) );
265 return sizeof(uaddr
->irda
);
272 default: /* likely an ipv4 address */
273 case sizeof(struct WS_sockaddr_in
):
274 return sizeof(uaddr
->in
);
277 case sizeof(struct WS_sockaddr_ipx
):
278 return sizeof(uaddr
->ipx
);
282 case sizeof(SOCKADDR_IRDA
):
283 return sizeof(uaddr
->irda
);
286 case sizeof(struct WS_sockaddr_in6
):
287 return sizeof(uaddr
->in6
);
291 FIXME( "unknown address family %u\n", wsaddr
->sa_family
);
296 static int sockaddr_from_unix( const union unix_sockaddr
*uaddr
, struct WS_sockaddr
*wsaddr
, socklen_t wsaddrlen
)
298 memset( wsaddr
, 0, wsaddrlen
);
300 switch (uaddr
->addr
.sa_family
)
304 struct WS_sockaddr_in win
= {0};
306 if (wsaddrlen
< sizeof(win
)) return -1;
307 win
.sin_family
= WS_AF_INET
;
308 win
.sin_port
= uaddr
->in
.sin_port
;
309 memcpy( &win
.sin_addr
, &uaddr
->in
.sin_addr
, sizeof(win
.sin_addr
) );
310 memcpy( wsaddr
, &win
, sizeof(win
) );
316 struct WS_sockaddr_in6 win
= {0};
318 if (wsaddrlen
< sizeof(win
)) return -1;
319 win
.sin6_family
= WS_AF_INET6
;
320 win
.sin6_port
= uaddr
->in6
.sin6_port
;
321 win
.sin6_flowinfo
= uaddr
->in6
.sin6_flowinfo
;
322 memcpy( &win
.sin6_addr
, &uaddr
->in6
.sin6_addr
, sizeof(win
.sin6_addr
) );
323 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
324 win
.sin6_scope_id
= uaddr
->in6
.sin6_scope_id
;
326 memcpy( wsaddr
, &win
, sizeof(win
) );
333 struct WS_sockaddr_ipx win
= {0};
335 if (wsaddrlen
< sizeof(win
)) return -1;
336 win
.sa_family
= WS_AF_IPX
;
337 memcpy( win
.sa_netnum
, &uaddr
->ipx
.sipx_network
, sizeof(win
.sa_netnum
) );
338 memcpy( win
.sa_nodenum
, &uaddr
->ipx
.sipx_node
, sizeof(win
.sa_nodenum
) );
339 win
.sa_socket
= uaddr
->ipx
.sipx_port
;
340 memcpy( wsaddr
, &win
, sizeof(win
) );
350 if (wsaddrlen
< sizeof(win
)) return -1;
351 win
.irdaAddressFamily
= WS_AF_IRDA
;
352 memcpy( win
.irdaDeviceID
, &uaddr
->irda
.sir_addr
, sizeof(win
.irdaDeviceID
) );
353 if (uaddr
->irda
.sir_lsap_sel
!= LSAP_ANY
)
354 snprintf( win
.irdaServiceName
, sizeof(win
.irdaServiceName
), "LSAP-SEL%u", uaddr
->irda
.sir_lsap_sel
);
356 memcpy( win
.irdaServiceName
, uaddr
->irda
.sir_name
, sizeof(win
.irdaServiceName
) );
357 memcpy( wsaddr
, &win
, sizeof(win
) );
366 FIXME( "unknown address family %d\n", uaddr
->addr
.sa_family
);
371 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
372 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
373 static WSACMSGHDR
*fill_control_message( int level
, int type
, WSACMSGHDR
*current
, ULONG
*maxsize
, void *data
, int len
)
375 ULONG msgsize
= sizeof(WSACMSGHDR
) + WSA_CMSG_ALIGN(len
);
376 char *ptr
= (char *) current
+ sizeof(WSACMSGHDR
);
378 if (msgsize
> *maxsize
)
381 current
->cmsg_len
= sizeof(WSACMSGHDR
) + len
;
382 current
->cmsg_level
= level
;
383 current
->cmsg_type
= type
;
384 memcpy(ptr
, data
, len
);
385 return (WSACMSGHDR
*)(ptr
+ WSA_CMSG_ALIGN(len
));
387 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
389 static int convert_control_headers(struct msghdr
*hdr
, WSABUF
*control
)
391 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
392 WSACMSGHDR
*cmsg_win
= (WSACMSGHDR
*)control
->buf
, *ptr
;
393 ULONG ctlsize
= control
->len
;
394 struct cmsghdr
*cmsg_unix
;
397 for (cmsg_unix
= CMSG_FIRSTHDR(hdr
); cmsg_unix
!= NULL
; cmsg_unix
= CMSG_NXTHDR(hdr
, cmsg_unix
))
399 switch (cmsg_unix
->cmsg_level
)
402 switch (cmsg_unix
->cmsg_type
)
404 #if defined(IP_PKTINFO)
407 const struct in_pktinfo
*data_unix
= (struct in_pktinfo
*)CMSG_DATA(cmsg_unix
);
408 struct WS_in_pktinfo data_win
;
410 memcpy( &data_win
.ipi_addr
, &data_unix
->ipi_addr
.s_addr
, 4 ); /* 4 bytes = 32 address bits */
411 data_win
.ipi_ifindex
= data_unix
->ipi_ifindex
;
412 ptr
= fill_control_message( WS_IPPROTO_IP
, WS_IP_PKTINFO
, ptr
, &ctlsize
,
413 (void *)&data_win
, sizeof(data_win
) );
414 if (!ptr
) goto error
;
417 #elif defined(IP_RECVDSTADDR)
420 const struct in_addr
*addr_unix
= (struct in_addr
*)CMSG_DATA(cmsg_unix
);
421 struct WS_in_pktinfo data_win
;
423 memcpy( &data_win
.ipi_addr
, &addr_unix
->s_addr
, 4 ); /* 4 bytes = 32 address bits */
424 data_win
.ipi_ifindex
= 0; /* FIXME */
425 ptr
= fill_control_message( WS_IPPROTO_IP
, WS_IP_PKTINFO
, ptr
, &ctlsize
,
426 (void *)&data_win
, sizeof(data_win
) );
427 if (!ptr
) goto error
;
430 #endif /* IP_PKTINFO */
432 FIXME("Unhandled IPPROTO_IP message header type %d\n", cmsg_unix
->cmsg_type
);
438 switch (cmsg_unix
->cmsg_type
)
440 #if defined(IPV6_HOPLIMIT)
443 ptr
= fill_control_message( WS_IPPROTO_IPV6
, WS_IPV6_HOPLIMIT
, ptr
, &ctlsize
,
444 CMSG_DATA(cmsg_unix
), sizeof(INT
) );
445 if (!ptr
) goto error
;
448 #endif /* IPV6_HOPLIMIT */
450 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO_IPI6_ADDR)
453 struct in6_pktinfo
*data_unix
= (struct in6_pktinfo
*)CMSG_DATA(cmsg_unix
);
454 struct WS_in6_pktinfo data_win
;
456 memcpy(&data_win
.ipi6_addr
, &data_unix
->ipi6_addr
.s6_addr
, 16);
457 data_win
.ipi6_ifindex
= data_unix
->ipi6_ifindex
;
458 ptr
= fill_control_message( WS_IPPROTO_IPV6
, WS_IPV6_PKTINFO
, ptr
, &ctlsize
,
459 (void *)&data_win
, sizeof(data_win
) );
460 if (!ptr
) goto error
;
463 #endif /* IPV6_PKTINFO */
465 #if defined(IPV6_TCLASS)
468 ptr
= fill_control_message( WS_IPPROTO_IPV6
, WS_IPV6_TCLASS
, ptr
, &ctlsize
,
469 CMSG_DATA(cmsg_unix
), sizeof(INT
) );
470 if (!ptr
) goto error
;
473 #endif /* IPV6_TCLASS */
476 FIXME("Unhandled IPPROTO_IPV6 message header type %d\n", cmsg_unix
->cmsg_type
);
482 FIXME("Unhandled message header level %d\n", cmsg_unix
->cmsg_level
);
487 control
->len
= (char *)ptr
- (char *)cmsg_win
;
493 #else /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
496 #endif /* defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) */
498 #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
500 static NTSTATUS
try_recv( int fd
, struct async_recv_ioctl
*async
, ULONG_PTR
*size
)
502 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
503 char control_buffer
[512];
505 union unix_sockaddr unix_addr
;
510 memset( &hdr
, 0, sizeof(hdr
) );
513 hdr
.msg_name
= &unix_addr
.addr
;
514 hdr
.msg_namelen
= sizeof(unix_addr
);
516 hdr
.msg_iov
= async
->iov
;
517 hdr
.msg_iovlen
= async
->count
;
518 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
519 hdr
.msg_control
= control_buffer
;
520 hdr
.msg_controllen
= sizeof(control_buffer
);
522 while ((ret
= virtual_locked_recvmsg( fd
, &hdr
, async
->unix_flags
)) < 0 && errno
== EINTR
);
526 /* Unix-like systems return EINVAL when attempting to read OOB data from
527 * an empty socket buffer; Windows returns WSAEWOULDBLOCK. */
528 if ((async
->unix_flags
& MSG_OOB
) && errno
== EINVAL
)
531 if (errno
!= EWOULDBLOCK
) WARN( "recvmsg: %s\n", strerror( errno
) );
532 return sock_errno_to_status( errno
);
535 status
= (hdr
.msg_flags
& MSG_TRUNC
) ? STATUS_BUFFER_OVERFLOW
: STATUS_SUCCESS
;
537 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
540 ERR( "Message control headers cannot be properly supported on this system.\n" );
541 async
->control
->len
= 0;
544 if (async
->control
&& !convert_control_headers( &hdr
, async
->control
))
546 WARN( "Application passed insufficient room for control headers.\n" );
547 *async
->ret_flags
|= WS_MSG_CTRUNC
;
548 status
= STATUS_BUFFER_OVERFLOW
;
552 /* If this socket is connected, Linux doesn't give us msg_name and
553 * msg_namelen from recvmsg, but it does set msg_namelen to zero.
555 * MSDN says that the address is ignored for connection-oriented sockets, so
556 * don't try to translate it.
558 if (async
->addr
&& hdr
.msg_namelen
)
559 *async
->addr_len
= sockaddr_from_unix( &unix_addr
, async
->addr
, *async
->addr_len
);
565 static NTSTATUS
async_recv_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
567 struct async_recv_ioctl
*async
= user
;
568 ULONG_PTR information
= 0;
571 TRACE( "%#x\n", status
);
573 if (status
== STATUS_ALERTED
)
575 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
578 status
= try_recv( fd
, async
, &information
);
579 TRACE( "got status %#x, %#lx bytes read\n", status
, information
);
581 if (status
== STATUS_DEVICE_NOT_READY
)
582 status
= STATUS_PENDING
;
584 if (needs_close
) close( fd
);
586 if (status
!= STATUS_PENDING
)
589 release_fileio( &async
->io
);
594 static NTSTATUS
sock_recv( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
595 int fd
, const WSABUF
*buffers
, unsigned int count
, WSABUF
*control
,
596 struct WS_sockaddr
*addr
, int *addr_len
, DWORD
*ret_flags
, int unix_flags
, int force_async
)
598 struct async_recv_ioctl
*async
;
599 ULONG_PTR information
;
606 if (unix_flags
& MSG_OOB
)
609 socklen_t len
= sizeof(oobinline
);
610 if (!getsockopt( fd
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&oobinline
, &len
) && oobinline
)
611 return STATUS_INVALID_PARAMETER
;
614 for (i
= 0; i
< count
; ++i
)
616 if (!virtual_check_buffer_for_write( buffers
[i
].buf
, buffers
[i
].len
))
617 return STATUS_ACCESS_VIOLATION
;
620 async_size
= offsetof( struct async_recv_ioctl
, iov
[count
] );
622 if (!(async
= (struct async_recv_ioctl
*)alloc_fileio( async_size
, async_recv_proc
, handle
)))
623 return STATUS_NO_MEMORY
;
625 async
->count
= count
;
626 for (i
= 0; i
< count
; ++i
)
628 async
->iov
[i
].iov_base
= buffers
[i
].buf
;
629 async
->iov
[i
].iov_len
= buffers
[i
].len
;
631 async
->unix_flags
= unix_flags
;
632 async
->control
= control
;
634 async
->addr_len
= addr_len
;
635 async
->ret_flags
= ret_flags
;
637 status
= try_recv( fd
, async
, &information
);
639 if (status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_OVERFLOW
&& status
!= STATUS_DEVICE_NOT_READY
)
641 release_fileio( &async
->io
);
645 if (status
== STATUS_DEVICE_NOT_READY
&& force_async
)
646 status
= STATUS_PENDING
;
648 SERVER_START_REQ( recv_socket
)
650 req
->status
= status
;
651 req
->total
= information
;
652 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, iosb_client_ptr(io
) );
653 req
->oob
= !!(unix_flags
& MSG_OOB
);
654 status
= wine_server_call( req
);
655 wait_handle
= wine_server_ptr_handle( reply
->wait
);
656 options
= reply
->options
;
657 if ((!NT_ERROR(status
) || wait_handle
) && status
!= STATUS_PENDING
)
660 io
->Information
= information
;
665 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
667 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
672 struct async_poll_ioctl
674 struct async_fileio io
;
676 struct afd_poll_params
*input
, *output
;
677 struct poll_socket_output sockets
[1];
680 static ULONG_PTR
fill_poll_output( struct async_poll_ioctl
*async
, NTSTATUS status
)
682 struct afd_poll_params
*input
= async
->input
, *output
= async
->output
;
683 unsigned int i
, count
= 0;
685 memcpy( output
, input
, offsetof( struct afd_poll_params
, sockets
[0] ) );
689 for (i
= 0; i
< async
->count
; ++i
)
691 if (async
->sockets
[i
].flags
)
693 output
->sockets
[count
].socket
= input
->sockets
[i
].socket
;
694 output
->sockets
[count
].flags
= async
->sockets
[i
].flags
;
695 output
->sockets
[count
].status
= async
->sockets
[i
].status
;
700 output
->count
= count
;
701 return offsetof( struct afd_poll_params
, sockets
[count
] );
704 static NTSTATUS
async_poll_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
706 struct async_poll_ioctl
*async
= user
;
707 ULONG_PTR information
= 0;
709 if (status
== STATUS_ALERTED
)
711 SERVER_START_REQ( get_async_result
)
713 req
->user_arg
= wine_server_client_ptr( async
);
714 wine_server_set_reply( req
, async
->sockets
, async
->count
* sizeof(async
->sockets
[0]) );
715 status
= wine_server_call( req
);
719 information
= fill_poll_output( async
, status
);
722 if (status
!= STATUS_PENDING
)
725 free( async
->input
);
726 release_fileio( &async
->io
);
732 /* we could handle this ioctl entirely on the server side, but the differing
733 * structure size makes it painful */
734 static NTSTATUS
sock_poll( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
735 void *in_buffer
, ULONG in_size
, void *out_buffer
, ULONG out_size
)
737 const struct afd_poll_params
*params
= in_buffer
;
738 struct poll_socket_input
*input
;
739 struct async_poll_ioctl
*async
;
746 if (in_size
< sizeof(*params
) || out_size
< in_size
|| !params
->count
747 || in_size
< offsetof( struct afd_poll_params
, sockets
[params
->count
] ))
748 return STATUS_INVALID_PARAMETER
;
750 TRACE( "timeout %s, count %u, unknown %#x, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
751 wine_dbgstr_longlong(params
->timeout
), params
->count
, params
->unknown
,
752 params
->padding
[0], params
->padding
[1], params
->padding
[2],
753 params
->sockets
[0].socket
, params
->sockets
[0].flags
);
755 if (params
->unknown
) FIXME( "unknown boolean is %#x\n", params
->unknown
);
756 if (params
->padding
[0]) FIXME( "padding[0] is %#x\n", params
->padding
[0] );
757 if (params
->padding
[1]) FIXME( "padding[1] is %#x\n", params
->padding
[1] );
758 if (params
->padding
[2]) FIXME( "padding[2] is %#x\n", params
->padding
[2] );
759 for (i
= 0; i
< params
->count
; ++i
)
761 if (params
->sockets
[i
].flags
& ~0x1ff)
762 FIXME( "unknown socket flags %#x\n", params
->sockets
[i
].flags
);
765 if (!(input
= malloc( params
->count
* sizeof(*input
) )))
766 return STATUS_NO_MEMORY
;
768 async_size
= offsetof( struct async_poll_ioctl
, sockets
[params
->count
] );
770 if (!(async
= (struct async_poll_ioctl
*)alloc_fileio( async_size
, async_poll_proc
, handle
)))
773 return STATUS_NO_MEMORY
;
776 if (!(async
->input
= malloc( in_size
)))
778 release_fileio( &async
->io
);
780 return STATUS_NO_MEMORY
;
782 memcpy( async
->input
, in_buffer
, in_size
);
784 async
->count
= params
->count
;
785 async
->output
= out_buffer
;
787 for (i
= 0; i
< params
->count
; ++i
)
789 input
[i
].socket
= params
->sockets
[i
].socket
;
790 input
[i
].flags
= params
->sockets
[i
].flags
;
793 SERVER_START_REQ( poll_socket
)
795 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, iosb_client_ptr(io
) );
796 req
->timeout
= params
->timeout
;
797 wine_server_add_data( req
, input
, params
->count
* sizeof(*input
) );
798 wine_server_set_reply( req
, async
->sockets
, params
->count
* sizeof(async
->sockets
[0]) );
799 status
= wine_server_call( req
);
800 wait_handle
= wine_server_ptr_handle( reply
->wait
);
801 options
= reply
->options
;
802 if (wait_handle
&& status
!= STATUS_PENDING
)
805 io
->Information
= fill_poll_output( async
, status
);
812 if (status
!= STATUS_PENDING
)
814 free( async
->input
);
815 release_fileio( &async
->io
);
818 if (wait_handle
) status
= wait_async( wait_handle
, (options
& FILE_SYNCHRONOUS_IO_ALERT
) );
822 static NTSTATUS
try_send( int fd
, struct async_send_ioctl
*async
)
824 union unix_sockaddr unix_addr
;
828 memset( &hdr
, 0, sizeof(hdr
) );
831 hdr
.msg_name
= &unix_addr
;
832 hdr
.msg_namelen
= sockaddr_to_unix( async
->addr
, async
->addr_len
, &unix_addr
);
833 if (!hdr
.msg_namelen
)
835 ERR( "failed to convert address\n" );
836 return STATUS_ACCESS_VIOLATION
;
839 #if defined(HAS_IPX) && defined(SOL_IPX)
840 if (async
->addr
->sa_family
== WS_AF_IPX
)
843 socklen_t len
= sizeof(type
);
845 /* The packet type is stored at the IPX socket level. At least the
846 * linux kernel seems to do something with it in case hdr.msg_name
847 * is NULL. Nonetheless we can use it to store the packet type, and
848 * then we can retrieve it using getsockopt. After that we can set
849 * the IPX type in the sockaddr_ipx structure with the stored value.
851 if (getsockopt(fd
, SOL_IPX
, IPX_TYPE
, &type
, &len
) >= 0)
852 unix_addr
.ipx
.sipx_type
= type
;
857 hdr
.msg_iov
= async
->iov
+ async
->iov_cursor
;
858 hdr
.msg_iovlen
= async
->count
- async
->iov_cursor
;
860 while ((ret
= sendmsg( fd
, &hdr
, async
->unix_flags
)) == -1)
862 if (errno
== EISCONN
)
867 else if (errno
!= EINTR
)
869 if (errno
!= EWOULDBLOCK
) WARN( "sendmsg: %s\n", strerror( errno
) );
870 return sock_errno_to_status( errno
);
874 async
->sent_len
+= ret
;
876 while (async
->iov_cursor
< async
->count
&& ret
>= async
->iov
[async
->iov_cursor
].iov_len
)
877 ret
-= async
->iov
[async
->iov_cursor
++].iov_len
;
878 if (async
->iov_cursor
< async
->count
)
880 async
->iov
[async
->iov_cursor
].iov_base
= (char *)async
->iov
[async
->iov_cursor
].iov_base
+ ret
;
881 async
->iov
[async
->iov_cursor
].iov_len
-= ret
;
882 return STATUS_DEVICE_NOT_READY
;
884 return STATUS_SUCCESS
;
887 static NTSTATUS
async_send_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
889 struct async_send_ioctl
*async
= user
;
892 TRACE( "%#x\n", status
);
894 if (status
== STATUS_ALERTED
)
896 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
899 status
= try_send( fd
, async
);
900 TRACE( "got status %#x\n", status
);
902 if (status
== STATUS_DEVICE_NOT_READY
)
903 status
= STATUS_PENDING
;
905 if (needs_close
) close( fd
);
907 if (status
!= STATUS_PENDING
)
909 *info
= async
->sent_len
;
910 release_fileio( &async
->io
);
915 static NTSTATUS
sock_send( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
916 IO_STATUS_BLOCK
*io
, int fd
, const WSABUF
*buffers
, unsigned int count
,
917 const struct WS_sockaddr
*addr
, unsigned int addr_len
, int unix_flags
, int force_async
)
919 struct async_send_ioctl
*async
;
926 async_size
= offsetof( struct async_send_ioctl
, iov
[count
] );
928 if (!(async
= (struct async_send_ioctl
*)alloc_fileio( async_size
, async_send_proc
, handle
)))
929 return STATUS_NO_MEMORY
;
931 async
->count
= count
;
932 for (i
= 0; i
< count
; ++i
)
934 async
->iov
[i
].iov_base
= buffers
[i
].buf
;
935 async
->iov
[i
].iov_len
= buffers
[i
].len
;
937 async
->unix_flags
= unix_flags
;
939 async
->addr_len
= addr_len
;
940 async
->iov_cursor
= 0;
943 status
= try_send( fd
, async
);
945 if (status
!= STATUS_SUCCESS
&& status
!= STATUS_DEVICE_NOT_READY
)
947 release_fileio( &async
->io
);
951 if (status
== STATUS_DEVICE_NOT_READY
&& force_async
)
952 status
= STATUS_PENDING
;
954 SERVER_START_REQ( send_socket
)
956 req
->status
= status
;
957 req
->total
= async
->sent_len
;
958 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, iosb_client_ptr(io
) );
959 status
= wine_server_call( req
);
960 wait_handle
= wine_server_ptr_handle( reply
->wait
);
961 options
= reply
->options
;
962 if ((!NT_ERROR(status
) || wait_handle
) && status
!= STATUS_PENDING
)
965 io
->Information
= async
->sent_len
;
970 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
972 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
976 static ssize_t
do_send( int fd
, const void *buffer
, size_t len
, int flags
)
979 while ((ret
= send( fd
, buffer
, len
, flags
)) < 0 && errno
== EINTR
);
980 if (ret
< 0 && errno
!= EWOULDBLOCK
) WARN( "send: %s\n", strerror( errno
) );
984 static NTSTATUS
try_transmit( int sock_fd
, int file_fd
, struct async_transmit_ioctl
*async
)
988 while (async
->head_cursor
< async
->buffers
.HeadLength
)
990 TRACE( "sending %u bytes of header data\n", async
->buffers
.HeadLength
- async
->head_cursor
);
991 ret
= do_send( sock_fd
, (char *)async
->buffers
.Head
+ async
->head_cursor
,
992 async
->buffers
.HeadLength
- async
->head_cursor
, 0 );
993 if (ret
< 0) return sock_errno_to_status( errno
);
994 TRACE( "send returned %zd\n", ret
);
995 async
->head_cursor
+= ret
;
998 while (async
->buffer_cursor
< async
->read_len
)
1000 TRACE( "sending %u bytes of file data\n", async
->read_len
- async
->buffer_cursor
);
1001 ret
= do_send( sock_fd
, async
->buffer
+ async
->buffer_cursor
,
1002 async
->read_len
- async
->buffer_cursor
, 0 );
1003 if (ret
< 0) return sock_errno_to_status( errno
);
1004 TRACE( "send returned %zd\n", ret
);
1005 async
->buffer_cursor
+= ret
;
1006 async
->file_cursor
+= ret
;
1009 if (async
->file
&& async
->buffer_cursor
== async
->read_len
)
1011 unsigned int read_size
= async
->buffer_size
;
1013 if (async
->file_len
)
1014 read_size
= min( read_size
, async
->file_len
- async
->file_cursor
);
1016 TRACE( "reading %u bytes of file data\n", read_size
);
1019 if (async
->offset
.QuadPart
== FILE_USE_FILE_POINTER_POSITION
)
1020 ret
= read( file_fd
, async
->buffer
, read_size
);
1022 ret
= pread( file_fd
, async
->buffer
, read_size
, async
->offset
.QuadPart
);
1023 } while (ret
< 0 && errno
== EINTR
);
1024 if (ret
< 0) return errno_to_status( errno
);
1025 TRACE( "read returned %zd\n", ret
);
1027 async
->read_len
= ret
;
1028 async
->buffer_cursor
= 0;
1029 if (async
->offset
.QuadPart
!= FILE_USE_FILE_POINTER_POSITION
)
1030 async
->offset
.QuadPart
+= ret
;
1032 if (ret
< read_size
|| (async
->file_len
&& async
->file_cursor
== async
->file_len
))
1034 return STATUS_PENDING
; /* still more data to send */
1037 while (async
->tail_cursor
< async
->buffers
.TailLength
)
1039 TRACE( "sending %u bytes of tail data\n", async
->buffers
.TailLength
- async
->tail_cursor
);
1040 ret
= do_send( sock_fd
, (char *)async
->buffers
.Tail
+ async
->tail_cursor
,
1041 async
->buffers
.TailLength
- async
->tail_cursor
, 0 );
1042 if (ret
< 0) return sock_errno_to_status( errno
);
1043 TRACE( "send returned %zd\n", ret
);
1044 async
->tail_cursor
+= ret
;
1047 return STATUS_SUCCESS
;
1050 static NTSTATUS
async_transmit_proc( void *user
, ULONG_PTR
*info
, NTSTATUS status
)
1052 int sock_fd
, file_fd
= -1, sock_needs_close
= FALSE
, file_needs_close
= FALSE
;
1053 struct async_transmit_ioctl
*async
= user
;
1055 TRACE( "%#x\n", status
);
1057 if (status
== STATUS_ALERTED
)
1059 if ((status
= server_get_unix_fd( async
->io
.handle
, 0, &sock_fd
, &sock_needs_close
, NULL
, NULL
)))
1062 if (async
->file
&& (status
= server_get_unix_fd( async
->file
, 0, &file_fd
, &file_needs_close
, NULL
, NULL
)))
1064 if (sock_needs_close
) close( sock_fd
);
1068 status
= try_transmit( sock_fd
, file_fd
, async
);
1069 TRACE( "got status %#x\n", status
);
1071 if (status
== STATUS_DEVICE_NOT_READY
)
1072 status
= STATUS_PENDING
;
1074 if (sock_needs_close
) close( sock_fd
);
1075 if (file_needs_close
) close( file_fd
);
1077 if (status
!= STATUS_PENDING
)
1079 *info
= async
->head_cursor
+ async
->file_cursor
+ async
->tail_cursor
;
1080 release_fileio( &async
->io
);
1085 static NTSTATUS
sock_transmit( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
1086 IO_STATUS_BLOCK
*io
, int fd
, const struct afd_transmit_params
*params
)
1088 int file_fd
, file_needs_close
= FALSE
;
1089 struct async_transmit_ioctl
*async
;
1090 enum server_fd_type file_type
;
1091 union unix_sockaddr addr
;
1097 addr_len
= sizeof(addr
);
1098 if (getpeername( fd
, &addr
.addr
, &addr_len
) != 0)
1099 return STATUS_INVALID_CONNECTION
;
1103 if ((status
= server_get_unix_fd( params
->file
, 0, &file_fd
, &file_needs_close
, &file_type
, NULL
)))
1105 if (file_needs_close
) close( file_fd
);
1107 if (file_type
!= FD_TYPE_FILE
)
1109 FIXME( "unsupported file type %#x\n", file_type
);
1110 return STATUS_NOT_IMPLEMENTED
;
1114 if (!(async
= (struct async_transmit_ioctl
*)alloc_fileio( sizeof(*async
), async_transmit_proc
, handle
)))
1115 return STATUS_NO_MEMORY
;
1117 async
->file
= params
->file
;
1118 async
->buffer_size
= params
->buffer_size
? params
->buffer_size
: 65536;
1119 if (!(async
->buffer
= malloc( async
->buffer_size
)))
1121 release_fileio( &async
->io
);
1122 return STATUS_NO_MEMORY
;
1124 async
->read_len
= 0;
1125 async
->head_cursor
= 0;
1126 async
->file_cursor
= 0;
1127 async
->buffer_cursor
= 0;
1128 async
->tail_cursor
= 0;
1129 async
->file_len
= params
->file_len
;
1130 async
->flags
= params
->flags
;
1131 async
->buffers
= params
->buffers
;
1132 async
->offset
= params
->offset
;
1134 SERVER_START_REQ( send_socket
)
1136 req
->status
= STATUS_PENDING
;
1138 req
->async
= server_async( handle
, &async
->io
, event
, apc
, apc_user
, iosb_client_ptr(io
) );
1139 status
= wine_server_call( req
);
1140 wait_handle
= wine_server_ptr_handle( reply
->wait
);
1141 options
= reply
->options
;
1142 /* In theory we'd fill the iosb here, as above in sock_send(), but it's
1143 * actually currently impossible to get STATUS_SUCCESS. The server will
1144 * either return STATUS_PENDING or an error code, and in neither case
1145 * should the iosb be filled. */
1149 if (status
!= STATUS_PENDING
) release_fileio( &async
->io
);
1151 if (wait_handle
) status
= wait_async( wait_handle
, options
& FILE_SYNCHRONOUS_IO_ALERT
);
1155 static void complete_async( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
1156 IO_STATUS_BLOCK
*io
, NTSTATUS status
, ULONG_PTR information
)
1158 ULONG_PTR iosb_ptr
= iosb_client_ptr(io
);
1160 io
->Status
= status
;
1161 io
->Information
= information
;
1162 if (event
) NtSetEvent( event
, NULL
);
1163 if (apc
) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC
)apc
, (ULONG_PTR
)apc_user
, iosb_ptr
, 0 );
1164 if (apc_user
) add_completion( handle
, (ULONG_PTR
)apc_user
, status
, information
, FALSE
);
1168 static NTSTATUS
do_getsockopt( HANDLE handle
, IO_STATUS_BLOCK
*io
, int level
,
1169 int option
, void *out_buffer
, ULONG out_size
)
1171 int fd
, needs_close
= FALSE
;
1172 socklen_t len
= out_size
;
1176 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1179 ret
= getsockopt( fd
, level
, option
, out_buffer
, &len
);
1180 if (needs_close
) close( fd
);
1181 if (ret
) return sock_errno_to_status( errno
);
1182 io
->Information
= len
;
1183 return STATUS_SUCCESS
;
1187 static NTSTATUS
do_setsockopt( HANDLE handle
, IO_STATUS_BLOCK
*io
, int level
,
1188 int option
, const void *optval
, socklen_t optlen
)
1190 int fd
, needs_close
= FALSE
;
1194 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1197 ret
= setsockopt( fd
, level
, option
, optval
, optlen
);
1198 if (needs_close
) close( fd
);
1199 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1203 NTSTATUS
sock_ioctl( HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
, IO_STATUS_BLOCK
*io
,
1204 ULONG code
, void *in_buffer
, ULONG in_size
, void *out_buffer
, ULONG out_size
)
1206 int fd
, needs_close
= FALSE
;
1209 TRACE( "handle %p, code %#x, in_buffer %p, in_size %u, out_buffer %p, out_size %u\n",
1210 handle
, code
, in_buffer
, in_size
, out_buffer
, out_size
);
1214 case IOCTL_AFD_BIND
:
1216 const struct afd_bind_params
*params
= in_buffer
;
1218 if (params
->unknown
) FIXME( "bind: got unknown %#x\n", params
->unknown
);
1220 status
= STATUS_BAD_DEVICE_TYPE
;
1224 case IOCTL_AFD_GETSOCKNAME
:
1225 if (in_size
) FIXME( "unexpected input size %u\n", in_size
);
1227 status
= STATUS_BAD_DEVICE_TYPE
;
1230 case IOCTL_AFD_LISTEN
:
1232 const struct afd_listen_params
*params
= in_buffer
;
1234 TRACE( "backlog %u\n", params
->backlog
);
1235 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1236 if (params
->unknown1
) FIXME( "listen: got unknown1 %#x\n", params
->unknown1
);
1237 if (params
->unknown2
) FIXME( "listen: got unknown2 %#x\n", params
->unknown2
);
1239 status
= STATUS_BAD_DEVICE_TYPE
;
1243 case IOCTL_AFD_EVENT_SELECT
:
1245 const struct afd_event_select_params
*params
= in_buffer
;
1247 TRACE( "event %p, mask %#x\n", params
->event
, params
->mask
);
1248 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1250 status
= STATUS_BAD_DEVICE_TYPE
;
1254 case IOCTL_AFD_GET_EVENTS
:
1255 if (in_size
) FIXME( "unexpected input size %u\n", in_size
);
1257 status
= STATUS_BAD_DEVICE_TYPE
;
1260 case IOCTL_AFD_RECV
:
1262 const struct afd_recv_params
*params
= in_buffer
;
1265 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1268 if (out_size
) FIXME( "unexpected output size %u\n", out_size
);
1270 if (in_size
< sizeof(struct afd_recv_params
))
1272 status
= STATUS_INVALID_PARAMETER
;
1276 if ((params
->msg_flags
& (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
)) == 0 ||
1277 (params
->msg_flags
& (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
)) == (AFD_MSG_NOT_OOB
| AFD_MSG_OOB
))
1279 status
= STATUS_INVALID_PARAMETER
;
1283 if (params
->msg_flags
& ~(AFD_MSG_NOT_OOB
| AFD_MSG_OOB
| AFD_MSG_PEEK
| AFD_MSG_WAITALL
))
1284 FIXME( "unknown msg_flags %#x\n", params
->msg_flags
);
1285 if (params
->recv_flags
& ~AFD_RECV_FORCE_ASYNC
)
1286 FIXME( "unknown recv_flags %#x\n", params
->recv_flags
);
1288 if (params
->msg_flags
& AFD_MSG_OOB
)
1289 unix_flags
|= MSG_OOB
;
1290 if (params
->msg_flags
& AFD_MSG_PEEK
)
1291 unix_flags
|= MSG_PEEK
;
1292 if (params
->msg_flags
& AFD_MSG_WAITALL
)
1293 FIXME( "MSG_WAITALL is not supported\n" );
1295 status
= sock_recv( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
, NULL
,
1296 NULL
, NULL
, NULL
, unix_flags
, !!(params
->recv_flags
& AFD_RECV_FORCE_ASYNC
) );
1300 case IOCTL_AFD_WINE_RECVMSG
:
1302 struct afd_recvmsg_params
*params
= in_buffer
;
1305 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1308 if (in_size
< sizeof(*params
))
1310 status
= STATUS_BUFFER_TOO_SMALL
;
1314 if (*params
->ws_flags
& WS_MSG_OOB
)
1315 unix_flags
|= MSG_OOB
;
1316 if (*params
->ws_flags
& WS_MSG_PEEK
)
1317 unix_flags
|= MSG_PEEK
;
1318 if (*params
->ws_flags
& WS_MSG_WAITALL
)
1319 FIXME( "MSG_WAITALL is not supported\n" );
1321 status
= sock_recv( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
, params
->control
,
1322 params
->addr
, params
->addr_len
, params
->ws_flags
, unix_flags
, params
->force_async
);
1326 case IOCTL_AFD_WINE_SENDMSG
:
1328 const struct afd_sendmsg_params
*params
= in_buffer
;
1331 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1334 if (in_size
< sizeof(*params
))
1336 status
= STATUS_BUFFER_TOO_SMALL
;
1340 if (params
->ws_flags
& WS_MSG_OOB
)
1341 unix_flags
|= MSG_OOB
;
1342 if (params
->ws_flags
& WS_MSG_PARTIAL
)
1343 WARN( "ignoring MSG_PARTIAL\n" );
1344 if (params
->ws_flags
& ~(WS_MSG_OOB
| WS_MSG_PARTIAL
))
1345 FIXME( "unknown flags %#x\n", params
->ws_flags
);
1347 status
= sock_send( handle
, event
, apc
, apc_user
, io
, fd
, params
->buffers
, params
->count
,
1348 params
->addr
, params
->addr_len
, unix_flags
, params
->force_async
);
1352 case IOCTL_AFD_WINE_TRANSMIT
:
1354 const struct afd_transmit_params
*params
= in_buffer
;
1356 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1359 if (in_size
< sizeof(*params
))
1361 status
= STATUS_BUFFER_TOO_SMALL
;
1365 status
= sock_transmit( handle
, event
, apc
, apc_user
, io
, fd
, params
);
1369 case IOCTL_AFD_WINE_COMPLETE_ASYNC
:
1371 if (in_size
!= sizeof(NTSTATUS
))
1372 return STATUS_BUFFER_TOO_SMALL
;
1374 status
= *(NTSTATUS
*)in_buffer
;
1375 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1379 case IOCTL_AFD_POLL
:
1380 status
= sock_poll( handle
, event
, apc
, apc_user
, io
, in_buffer
, in_size
, out_buffer
, out_size
);
1383 case IOCTL_AFD_WINE_FIONREAD
:
1387 if (out_size
< sizeof(int))
1389 status
= STATUS_BUFFER_TOO_SMALL
;
1393 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1398 socklen_t len
= sizeof(value
);
1400 /* FIONREAD on a listening socket always fails (see tcp(7)). */
1401 if (!getsockopt( fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &value
, &len
) && value
)
1403 *(int *)out_buffer
= 0;
1404 status
= STATUS_SUCCESS
;
1405 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1411 if ((ret
= ioctl( fd
, FIONREAD
, &value
)) < 0)
1413 status
= sock_errno_to_status( errno
);
1416 *(int *)out_buffer
= value
;
1417 status
= STATUS_SUCCESS
;
1418 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1422 case IOCTL_AFD_WINE_SIOCATMARK
:
1425 socklen_t len
= sizeof(value
);
1427 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1430 if (out_size
< sizeof(int))
1432 status
= STATUS_BUFFER_TOO_SMALL
;
1436 if (getsockopt( fd
, SOL_SOCKET
, SO_OOBINLINE
, &value
, &len
) < 0)
1438 status
= sock_errno_to_status( errno
);
1444 *(int *)out_buffer
= TRUE
;
1448 if ((ret
= ioctl( fd
, SIOCATMARK
, &value
)) < 0)
1450 status
= sock_errno_to_status( errno
);
1453 /* windows is reversed with respect to unix */
1454 *(int *)out_buffer
= !value
;
1456 status
= STATUS_SUCCESS
;
1457 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1461 case IOCTL_AFD_WINE_GET_INTERFACE_LIST
:
1463 #ifdef HAVE_GETIFADDRS
1464 INTERFACE_INFO
*info
= out_buffer
;
1465 struct ifaddrs
*ifaddrs
, *ifaddr
;
1466 unsigned int count
= 0;
1469 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1472 if (getifaddrs( &ifaddrs
) < 0)
1474 status
= sock_errno_to_status( errno
);
1478 for (ifaddr
= ifaddrs
; ifaddr
!= NULL
; ifaddr
= ifaddr
->ifa_next
)
1480 if (ifaddr
->ifa_addr
&& ifaddr
->ifa_addr
->sa_family
== AF_INET
) ++count
;
1483 ret_size
= count
* sizeof(*info
);
1484 if (out_size
< ret_size
)
1486 status
= STATUS_PENDING
;
1487 complete_async( handle
, event
, apc
, apc_user
, io
, STATUS_BUFFER_TOO_SMALL
, 0 );
1488 freeifaddrs( ifaddrs
);
1492 memset( out_buffer
, 0, ret_size
);
1495 for (ifaddr
= ifaddrs
; ifaddr
!= NULL
; ifaddr
= ifaddr
->ifa_next
)
1497 in_addr_t addr
, mask
;
1499 if (!ifaddr
->ifa_addr
|| ifaddr
->ifa_addr
->sa_family
!= AF_INET
)
1502 addr
= ((const struct sockaddr_in
*)ifaddr
->ifa_addr
)->sin_addr
.s_addr
;
1503 mask
= ((const struct sockaddr_in
*)ifaddr
->ifa_netmask
)->sin_addr
.s_addr
;
1505 info
[count
].iiFlags
= 0;
1506 if (ifaddr
->ifa_flags
& IFF_BROADCAST
)
1507 info
[count
].iiFlags
|= WS_IFF_BROADCAST
;
1508 if (ifaddr
->ifa_flags
& IFF_LOOPBACK
)
1509 info
[count
].iiFlags
|= WS_IFF_LOOPBACK
;
1510 if (ifaddr
->ifa_flags
& IFF_MULTICAST
)
1511 info
[count
].iiFlags
|= WS_IFF_MULTICAST
;
1512 #ifdef IFF_POINTTOPOINT
1513 if (ifaddr
->ifa_flags
& IFF_POINTTOPOINT
)
1514 info
[count
].iiFlags
|= WS_IFF_POINTTOPOINT
;
1516 if (ifaddr
->ifa_flags
& IFF_UP
)
1517 info
[count
].iiFlags
|= WS_IFF_UP
;
1519 info
[count
].iiAddress
.AddressIn
.sin_family
= WS_AF_INET
;
1520 info
[count
].iiAddress
.AddressIn
.sin_port
= 0;
1521 info
[count
].iiAddress
.AddressIn
.sin_addr
.WS_s_addr
= addr
;
1523 info
[count
].iiNetmask
.AddressIn
.sin_family
= WS_AF_INET
;
1524 info
[count
].iiNetmask
.AddressIn
.sin_port
= 0;
1525 info
[count
].iiNetmask
.AddressIn
.sin_addr
.WS_s_addr
= mask
;
1527 if (ifaddr
->ifa_flags
& IFF_BROADCAST
)
1529 info
[count
].iiBroadcastAddress
.AddressIn
.sin_family
= WS_AF_INET
;
1530 info
[count
].iiBroadcastAddress
.AddressIn
.sin_port
= 0;
1531 info
[count
].iiBroadcastAddress
.AddressIn
.sin_addr
.WS_s_addr
= addr
| ~mask
;
1537 freeifaddrs( ifaddrs
);
1538 status
= STATUS_PENDING
;
1539 complete_async( handle
, event
, apc
, apc_user
, io
, STATUS_SUCCESS
, ret_size
);
1541 FIXME( "Interface list queries are currently not supported on this platform.\n" );
1542 status
= STATUS_NOT_SUPPORTED
;
1547 case IOCTL_AFD_WINE_KEEPALIVE_VALS
:
1549 struct tcp_keepalive
*k
= in_buffer
;
1552 if (!in_buffer
|| in_size
< sizeof(struct tcp_keepalive
))
1553 return STATUS_BUFFER_TOO_SMALL
;
1554 keepalive
= !!k
->onoff
;
1556 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1559 if (setsockopt( fd
, SOL_SOCKET
, SO_KEEPALIVE
, &keepalive
, sizeof(int) ) < 0)
1561 status
= STATUS_INVALID_PARAMETER
;
1568 int idle
= max( 1, (k
->keepalivetime
+ 500) / 1000 );
1570 if (setsockopt( fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, &idle
, sizeof(int) ) < 0)
1572 status
= STATUS_INVALID_PARAMETER
;
1576 FIXME("ignoring keepalive timeout\n");
1582 #ifdef TCP_KEEPINTVL
1583 int interval
= max( 1, (k
->keepaliveinterval
+ 500) / 1000 );
1585 if (setsockopt( fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, &interval
, sizeof(int) ) < 0)
1586 status
= STATUS_INVALID_PARAMETER
;
1588 FIXME("ignoring keepalive interval\n");
1592 status
= STATUS_SUCCESS
;
1593 complete_async( handle
, event
, apc
, apc_user
, io
, status
, 0 );
1597 case IOCTL_AFD_WINE_GETPEERNAME
:
1599 union unix_sockaddr unix_addr
;
1600 socklen_t unix_len
= sizeof(unix_addr
);
1603 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1606 if (getpeername( fd
, &unix_addr
.addr
, &unix_len
) < 0)
1608 status
= sock_errno_to_status( errno
);
1612 len
= sockaddr_from_unix( &unix_addr
, out_buffer
, out_size
);
1615 status
= STATUS_BUFFER_TOO_SMALL
;
1618 io
->Information
= len
;
1619 status
= STATUS_SUCCESS
;
1623 case IOCTL_AFD_WINE_GET_SO_BROADCAST
:
1624 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_BROADCAST
, out_buffer
, out_size
);
1626 case IOCTL_AFD_WINE_SET_SO_BROADCAST
:
1627 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_BROADCAST
, in_buffer
, in_size
);
1629 case IOCTL_AFD_WINE_GET_SO_KEEPALIVE
:
1630 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_KEEPALIVE
, out_buffer
, out_size
);
1632 case IOCTL_AFD_WINE_SET_SO_KEEPALIVE
:
1633 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_KEEPALIVE
, in_buffer
, in_size
);
1635 case IOCTL_AFD_WINE_GET_SO_LINGER
:
1637 struct WS_linger
*ws_linger
= out_buffer
;
1638 struct linger unix_linger
;
1639 socklen_t len
= sizeof(unix_linger
);
1642 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1645 ret
= getsockopt( fd
, SOL_SOCKET
, SO_LINGER
, &unix_linger
, &len
);
1646 if (needs_close
) close( fd
);
1649 ws_linger
->l_onoff
= unix_linger
.l_onoff
;
1650 ws_linger
->l_linger
= unix_linger
.l_linger
;
1651 io
->Information
= sizeof(*ws_linger
);
1654 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1657 case IOCTL_AFD_WINE_SET_SO_LINGER
:
1659 const struct WS_linger
*ws_linger
= in_buffer
;
1660 struct linger unix_linger
;
1662 unix_linger
.l_onoff
= ws_linger
->l_onoff
;
1663 unix_linger
.l_linger
= ws_linger
->l_linger
;
1665 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_LINGER
, &unix_linger
, sizeof(unix_linger
) );
1668 case IOCTL_AFD_WINE_GET_SO_OOBINLINE
:
1669 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_OOBINLINE
, out_buffer
, out_size
);
1671 case IOCTL_AFD_WINE_SET_SO_OOBINLINE
:
1672 return do_setsockopt( handle
, io
, SOL_SOCKET
, SO_OOBINLINE
, in_buffer
, in_size
);
1674 case IOCTL_AFD_WINE_GET_SO_REUSEADDR
:
1675 return do_getsockopt( handle
, io
, SOL_SOCKET
, SO_REUSEADDR
, out_buffer
, out_size
);
1677 /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics;
1678 * however, using it the BSD way fixes bug 8513 and seems to be what
1679 * most programmers assume, anyway */
1680 case IOCTL_AFD_WINE_SET_SO_REUSEADDR
:
1682 int fd
, needs_close
= FALSE
;
1686 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1689 ret
= setsockopt( fd
, SOL_SOCKET
, SO_REUSEADDR
, in_buffer
, in_size
);
1691 if (!ret
) ret
= setsockopt( fd
, SOL_SOCKET
, SO_REUSEPORT
, in_buffer
, in_size
);
1693 if (needs_close
) close( fd
);
1694 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1697 case IOCTL_AFD_WINE_SET_IP_ADD_MEMBERSHIP
:
1698 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, in_buffer
, in_size
);
1700 case IOCTL_AFD_WINE_SET_IP_ADD_SOURCE_MEMBERSHIP
:
1701 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_ADD_SOURCE_MEMBERSHIP
, in_buffer
, in_size
);
1703 case IOCTL_AFD_WINE_SET_IP_BLOCK_SOURCE
:
1704 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_BLOCK_SOURCE
, in_buffer
, in_size
);
1706 case IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT
:
1708 socklen_t len
= out_size
;
1711 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1715 ret
= getsockopt( fd
, IPPROTO_IP
, IP_DONTFRAG
, out_buffer
, &len
);
1716 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1720 len
= sizeof(value
);
1721 ret
= getsockopt( fd
, IPPROTO_IP
, IP_MTU_DISCOVER
, &value
, &len
);
1722 if (!ret
) *(DWORD
*)out_buffer
= (value
!= IP_PMTUDISC_DONT
);
1729 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
1730 ret
= 0; /* fake success */
1733 if (needs_close
) close( fd
);
1734 if (ret
) return sock_errno_to_status( errno
);
1735 io
->Information
= len
;
1736 return STATUS_SUCCESS
;
1739 case IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT
:
1741 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DONTFRAG
, in_buffer
, in_size
);
1742 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT)
1744 int value
= *(DWORD
*)in_buffer
? IP_PMTUDISC_DO
: IP_PMTUDISC_DONT
;
1746 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MTU_DISCOVER
, &value
, sizeof(value
) );
1753 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
1754 return STATUS_SUCCESS
; /* fake success */
1758 case IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP
:
1759 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, in_buffer
, in_size
);
1761 case IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP
:
1762 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_DROP_SOURCE_MEMBERSHIP
, in_buffer
, in_size
);
1765 case IOCTL_AFD_WINE_SET_IP_HDRINCL
:
1766 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_HDRINCL
, in_buffer
, in_size
);
1769 case IOCTL_AFD_WINE_GET_IP_MULTICAST_IF
:
1770 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_IF
, out_buffer
, out_size
);
1772 case IOCTL_AFD_WINE_SET_IP_MULTICAST_IF
:
1773 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_IF
, in_buffer
, in_size
);
1775 case IOCTL_AFD_WINE_GET_IP_MULTICAST_LOOP
:
1776 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_LOOP
, out_buffer
, out_size
);
1778 case IOCTL_AFD_WINE_SET_IP_MULTICAST_LOOP
:
1779 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_LOOP
, in_buffer
, in_size
);
1781 case IOCTL_AFD_WINE_GET_IP_MULTICAST_TTL
:
1782 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_TTL
, out_buffer
, out_size
);
1784 case IOCTL_AFD_WINE_SET_IP_MULTICAST_TTL
:
1785 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_MULTICAST_TTL
, in_buffer
, in_size
);
1787 case IOCTL_AFD_WINE_GET_IP_OPTIONS
:
1788 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_OPTIONS
, out_buffer
, out_size
);
1790 case IOCTL_AFD_WINE_SET_IP_OPTIONS
:
1791 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_OPTIONS
, in_buffer
, in_size
);
1794 case IOCTL_AFD_WINE_GET_IP_PKTINFO
:
1795 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_PKTINFO
, out_buffer
, out_size
);
1797 case IOCTL_AFD_WINE_SET_IP_PKTINFO
:
1798 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_PKTINFO
, in_buffer
, in_size
);
1799 #elif defined(IP_RECVDSTADDR)
1800 case IOCTL_AFD_WINE_GET_IP_PKTINFO
:
1801 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_RECVDSTADDR
, out_buffer
, out_size
);
1803 case IOCTL_AFD_WINE_SET_IP_PKTINFO
:
1804 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_RECVDSTADDR
, in_buffer
, in_size
);
1807 case IOCTL_AFD_WINE_GET_IP_TOS
:
1808 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_TOS
, out_buffer
, out_size
);
1810 case IOCTL_AFD_WINE_SET_IP_TOS
:
1811 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_TOS
, in_buffer
, in_size
);
1813 case IOCTL_AFD_WINE_GET_IP_TTL
:
1814 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_TTL
, out_buffer
, out_size
);
1816 case IOCTL_AFD_WINE_SET_IP_TTL
:
1817 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_TTL
, in_buffer
, in_size
);
1819 case IOCTL_AFD_WINE_SET_IP_UNBLOCK_SOURCE
:
1820 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_UNBLOCK_SOURCE
, in_buffer
, in_size
);
1822 #ifdef IP_UNICAST_IF
1823 case IOCTL_AFD_WINE_GET_IP_UNICAST_IF
:
1824 return do_getsockopt( handle
, io
, IPPROTO_IP
, IP_UNICAST_IF
, out_buffer
, out_size
);
1826 case IOCTL_AFD_WINE_SET_IP_UNICAST_IF
:
1827 return do_setsockopt( handle
, io
, IPPROTO_IP
, IP_UNICAST_IF
, in_buffer
, in_size
);
1830 #ifdef IPV6_ADD_MEMBERSHIP
1831 case IOCTL_AFD_WINE_SET_IPV6_ADD_MEMBERSHIP
:
1832 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
, in_buffer
, in_size
);
1835 case IOCTL_AFD_WINE_GET_IPV6_DONTFRAG
:
1837 socklen_t len
= out_size
;
1840 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1843 #ifdef IPV6_DONTFRAG
1844 ret
= getsockopt( fd
, IPPROTO_IPV6
, IPV6_DONTFRAG
, out_buffer
, &len
);
1845 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
1849 len
= sizeof(value
);
1850 ret
= getsockopt( fd
, IPPROTO_IPV6
, IPV6_MTU_DISCOVER
, &value
, &len
);
1851 if (!ret
) *(DWORD
*)out_buffer
= (value
!= IPV6_PMTUDISC_DONT
);
1858 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
1859 ret
= 0; /* fake success */
1862 if (needs_close
) close( fd
);
1863 if (ret
) return sock_errno_to_status( errno
);
1864 io
->Information
= len
;
1865 return STATUS_SUCCESS
;
1868 case IOCTL_AFD_WINE_SET_IPV6_DONTFRAG
:
1869 #ifdef IPV6_DONTFRAG
1870 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_DONTFRAG
, in_buffer
, in_size
);
1871 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT)
1873 int value
= *(DWORD
*)in_buffer
? IPV6_PMTUDISC_DO
: IPV6_PMTUDISC_DONT
;
1875 return do_setsockopt( handle
, io
, IPPROTO_IP
, IPV6_MTU_DISCOVER
, &value
, sizeof(value
) );
1882 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
1883 return STATUS_SUCCESS
; /* fake success */
1887 #ifdef IPV6_DROP_MEMBERSHIP
1888 case IOCTL_AFD_WINE_SET_IPV6_DROP_MEMBERSHIP
:
1889 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_DROP_MEMBERSHIP
, in_buffer
, in_size
);
1892 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS
:
1893 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, out_buffer
, out_size
);
1895 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS
:
1896 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, in_buffer
, in_size
);
1898 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_IF
:
1899 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, out_buffer
, out_size
);
1901 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF
:
1902 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, in_buffer
, in_size
);
1904 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP
:
1905 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, out_buffer
, out_size
);
1907 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP
:
1908 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, in_buffer
, in_size
);
1910 #ifdef IPV6_RECVHOPLIMIT
1911 case IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT
:
1912 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
, out_buffer
, out_size
);
1914 case IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT
:
1915 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
, in_buffer
, in_size
);
1918 #ifdef IPV6_RECVPKTINFO
1919 case IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO
:
1920 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, out_buffer
, out_size
);
1922 case IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO
:
1923 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, in_buffer
, in_size
);
1926 #ifdef IPV6_RECVTCLASS
1927 case IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS
:
1928 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVTCLASS
, out_buffer
, out_size
);
1930 case IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS
:
1931 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_RECVTCLASS
, in_buffer
, in_size
);
1934 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS
:
1935 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, out_buffer
, out_size
);
1937 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS
:
1938 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, in_buffer
, in_size
);
1940 #ifdef IPV6_UNICAST_IF
1941 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF
:
1942 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, out_buffer
, out_size
);
1944 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF
:
1945 return do_setsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_UNICAST_IF
, in_buffer
, in_size
);
1948 case IOCTL_AFD_WINE_GET_IPV6_V6ONLY
:
1949 return do_getsockopt( handle
, io
, IPPROTO_IPV6
, IPV6_V6ONLY
, out_buffer
, out_size
);
1951 case IOCTL_AFD_WINE_SET_IPV6_V6ONLY
:
1953 int fd
, needs_close
= FALSE
;
1954 union unix_sockaddr addr
;
1955 socklen_t len
= sizeof(addr
);
1959 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1962 if (!getsockname( fd
, &addr
.addr
, &len
) && addr
.addr
.sa_family
== AF_INET
&& !addr
.in
.sin_port
)
1964 /* changing IPV6_V6ONLY succeeds on an unbound IPv4 socket */
1965 WARN( "ignoring IPV6_V6ONLY on an unbound IPv4 socket\n" );
1966 return STATUS_SUCCESS
;
1969 ret
= setsockopt( fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, in_buffer
, in_size
);
1970 if (needs_close
) close( fd
);
1971 return ret
? sock_errno_to_status( errno
) : STATUS_SUCCESS
;
1975 case IOCTL_AFD_WINE_GET_IPX_PTYPE
:
1976 return do_getsockopt( handle
, io
, SOL_IPX
, IPX_TYPE
, out_buffer
, out_size
);
1978 case IOCTL_AFD_WINE_SET_IPX_PTYPE
:
1979 return do_setsockopt( handle
, io
, SOL_IPX
, IPX_TYPE
, in_buffer
, in_size
);
1980 #elif defined(SO_DEFAULT_HEADERS)
1981 case IOCTL_AFD_WINE_GET_IPX_PTYPE
:
1983 int fd
, needs_close
= FALSE
;
1985 socklen_t len
= sizeof(value
);
1988 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1991 ret
= getsockopt( fd
, 0, SO_DEFAULT_HEADERS
, &value
, &len
);
1992 if (needs_close
) close( fd
);
1993 if (ret
) return sock_errno_to_status( errno
);
1994 *(DWORD
*)out_buffer
= value
.ipx_pt
;
1995 return STATUS_SUCCESS
;
1998 case IOCTL_AFD_WINE_SET_IPX_PTYPE
:
2000 struct ipx value
= {0};
2002 /* FIXME: should we retrieve SO_DEFAULT_HEADERS first and modify it? */
2003 value
.ipx_pt
= *(DWORD
*)in_buffer
;
2004 return do_setsockopt( handle
, io
, 0, SO_DEFAULT_HEADERS
, &value
, sizeof(value
) );
2009 #define MAX_IRDA_DEVICES 10
2010 case IOCTL_AFD_WINE_GET_IRLMP_ENUMDEVICES
:
2012 char buffer
[offsetof( struct irda_device_list
, dev
[MAX_IRDA_DEVICES
] )];
2013 struct irda_device_list
*unix_list
= (struct irda_device_list
*)buffer
;
2014 socklen_t len
= sizeof(buffer
);
2015 DEVICELIST
*ws_list
= out_buffer
;
2016 int fd
, needs_close
= FALSE
;
2021 if ((status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
2024 ret
= getsockopt( fd
, SOL_IRLMP
, IRLMP_ENUMDEVICES
, buffer
, &len
);
2025 if (needs_close
) close( fd
);
2026 if (ret
) return sock_errno_to_status( errno
);
2028 io
->Information
= offsetof( DEVICELIST
, Device
[unix_list
->len
] );
2029 if (out_size
< io
->Information
)
2030 return STATUS_BUFFER_TOO_SMALL
;
2032 TRACE( "IRLMP_ENUMDEVICES: got %u devices:\n", unix_list
->len
);
2033 ws_list
->numDevice
= unix_list
->len
;
2034 for (i
= 0; i
< unix_list
->len
; ++i
)
2036 const struct irda_device_info
*unix_dev
= &unix_list
->dev
[i
];
2037 IRDA_DEVICE_INFO
*ws_dev
= &ws_list
->Device
[i
];
2039 TRACE( "saddr %#08x, daddr %#08x, info %s, hints 0x%02x%02x\n",
2040 unix_dev
->saddr
, unix_dev
->daddr
, unix_dev
->info
, unix_dev
->hints
[0], unix_dev
->hints
[1] );
2041 memcpy( ws_dev
->irdaDeviceID
, &unix_dev
->daddr
, sizeof(unix_dev
->daddr
) );
2042 memcpy( ws_dev
->irdaDeviceName
, unix_dev
->info
, sizeof(unix_dev
->info
) );
2043 ws_dev
->irdaDeviceHints1
= unix_dev
->hints
[0];
2044 ws_dev
->irdaDeviceHints2
= unix_dev
->hints
[1];
2045 ws_dev
->irdaCharSet
= unix_dev
->charset
;
2047 return STATUS_SUCCESS
;
2051 case IOCTL_AFD_WINE_GET_TCP_NODELAY
:
2052 return do_getsockopt( handle
, io
, IPPROTO_TCP
, TCP_NODELAY
, out_buffer
, out_size
);
2054 case IOCTL_AFD_WINE_SET_TCP_NODELAY
:
2055 return do_setsockopt( handle
, io
, IPPROTO_TCP
, TCP_NODELAY
, in_buffer
, in_size
);
2059 if ((code
>> 16) == FILE_DEVICE_NETWORK
)
2061 /* Wine-internal ioctl */
2062 status
= STATUS_BAD_DEVICE_TYPE
;
2066 FIXME( "Unknown ioctl %#x (device %#x, access %#x, function %#x, method %#x)\n",
2067 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3 );
2068 status
= STATUS_INVALID_DEVICE_REQUEST
;
2074 if (needs_close
) close( fd
);