msado15: Semi-stub _Recordset get/put Filter.
[wine.git] / dlls / ntdll / unix / socket.c
blobac351a17a70ad6fba563448b2c120599ab2c7b2f
1 /*
2 * Windows sockets
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
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
26 #include <assert.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #include <unistd.h>
32 #ifdef HAVE_IFADDRS_H
33 # include <ifaddrs.h>
34 #endif
35 #ifdef HAVE_NET_IF_H
36 # include <net/if.h>
37 #endif
38 #ifdef HAVE_NETINET_IN_H
39 # define __APPLE_USE_RFC_3542
40 # include <netinet/in.h>
41 #endif
42 #ifdef HAVE_NETINET_TCP_H
43 # include <netinet/tcp.h>
44 #endif
46 #ifdef HAVE_NETIPX_IPX_H
47 # include <netipx/ipx.h>
48 #elif defined(HAVE_LINUX_IPX_H)
49 # ifdef HAVE_ASM_TYPES_H
50 # include <asm/types.h>
51 # endif
52 # ifdef HAVE_LINUX_TYPES_H
53 # include <linux/types.h>
54 # endif
55 # include <linux/ipx.h>
56 #endif
57 #if defined(SOL_IPX) || defined(SO_DEFAULT_HEADERS)
58 # define HAS_IPX
59 #endif
61 #ifdef HAVE_LINUX_IRDA_H
62 # ifdef HAVE_LINUX_TYPES_H
63 # include <linux/types.h>
64 # endif
65 # include <linux/irda.h>
66 # define HAS_IRDA
67 #endif
69 #include "ntstatus.h"
70 #define WIN32_NO_STATUS
71 #include "windef.h"
72 #include "winioctl.h"
73 #define USE_WS_PREFIX
74 #include "winsock2.h"
75 #include "mswsock.h"
76 #include "mstcpip.h"
77 #include "ws2tcpip.h"
78 #include "wsipx.h"
79 #include "af_irda.h"
80 #include "wine/afd.h"
82 #include "unix_private.h"
84 #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
85 /* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */
86 #define TCP_KEEPIDLE TCP_KEEPALIVE
87 #endif
89 #if defined(linux) && !defined(IP_UNICAST_IF)
90 #define IP_UNICAST_IF 50
91 #endif
93 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
95 #define u64_to_user_ptr(u) ((void *)(uintptr_t)(u))
97 union unix_sockaddr
99 struct sockaddr addr;
100 struct sockaddr_in in;
101 struct sockaddr_in6 in6;
102 #ifdef HAS_IPX
103 struct sockaddr_ipx ipx;
104 #endif
105 #ifdef HAS_IRDA
106 struct sockaddr_irda irda;
107 #endif
110 struct async_recv_ioctl
112 struct async_fileio io;
113 void *control;
114 struct WS_sockaddr *addr;
115 int *addr_len;
116 unsigned int *ret_flags;
117 int unix_flags;
118 unsigned int count;
119 BOOL icmp_over_dgram;
120 struct iovec iov[1];
123 struct async_send_ioctl
125 struct async_fileio io;
126 const struct WS_sockaddr *addr;
127 int addr_len;
128 int unix_flags;
129 unsigned int sent_len;
130 unsigned int count;
131 unsigned int iov_cursor;
132 struct iovec iov[1];
135 struct async_transmit_ioctl
137 struct async_fileio io;
138 HANDLE file;
139 char *buffer;
140 unsigned int buffer_size; /* allocated size of buffer */
141 unsigned int read_len; /* amount of valid data currently in the buffer */
142 unsigned int head_cursor; /* amount of header data already sent */
143 unsigned int file_cursor; /* amount of file data already sent */
144 unsigned int buffer_cursor; /* amount of data currently in the buffer already sent */
145 unsigned int tail_cursor; /* amount of tail data already sent */
146 unsigned int file_len; /* total file length to send */
147 unsigned int flags;
148 const char *head;
149 const char *tail;
150 unsigned int head_len;
151 unsigned int tail_len;
152 LARGE_INTEGER offset;
155 static NTSTATUS sock_errno_to_status( int err )
157 switch (err)
159 case EBADF: return STATUS_INVALID_HANDLE;
160 case EBUSY: return STATUS_DEVICE_BUSY;
161 case EPERM:
162 case EACCES: return STATUS_ACCESS_DENIED;
163 case EFAULT: return STATUS_ACCESS_VIOLATION;
164 case EINVAL: return STATUS_INVALID_PARAMETER;
165 case ENFILE:
166 case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
167 case EINPROGRESS:
168 case EWOULDBLOCK: return STATUS_DEVICE_NOT_READY;
169 case EALREADY: return STATUS_NETWORK_BUSY;
170 case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
171 case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
172 case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
173 case EPROTONOSUPPORT:
174 case ESOCKTNOSUPPORT:
175 case EPFNOSUPPORT:
176 case EAFNOSUPPORT:
177 case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
178 case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
179 case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
180 case EADDRINUSE: return STATUS_SHARING_VIOLATION;
181 case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
182 case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
183 case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
184 case ENOTCONN: return STATUS_INVALID_CONNECTION;
185 case ETIMEDOUT: return STATUS_IO_TIMEOUT;
186 case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
187 case EHOSTUNREACH: return STATUS_HOST_UNREACHABLE;
188 case ENETDOWN: return STATUS_NETWORK_BUSY;
189 case EPIPE:
190 case ECONNRESET: return STATUS_CONNECTION_RESET;
191 case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
192 case EISCONN: return STATUS_CONNECTION_ACTIVE;
194 case 0: return STATUS_SUCCESS;
195 default:
196 FIXME( "unknown errno %d\n", err );
197 return STATUS_UNSUCCESSFUL;
201 static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrlen, union unix_sockaddr *uaddr )
203 memset( uaddr, 0, sizeof(*uaddr) );
205 switch (wsaddr->sa_family)
207 case WS_AF_INET:
209 struct WS_sockaddr_in win = {0};
211 if (wsaddrlen < sizeof(win)) return 0;
212 memcpy( &win, wsaddr, sizeof(win) );
213 uaddr->in.sin_family = AF_INET;
214 uaddr->in.sin_port = win.sin_port;
215 memcpy( &uaddr->in.sin_addr, &win.sin_addr, sizeof(win.sin_addr) );
216 return sizeof(uaddr->in);
219 case WS_AF_INET6:
221 struct WS_sockaddr_in6 win = {0};
223 if (wsaddrlen < sizeof(win)) return 0;
224 memcpy( &win, wsaddr, sizeof(win) );
225 uaddr->in6.sin6_family = AF_INET6;
226 uaddr->in6.sin6_port = win.sin6_port;
227 uaddr->in6.sin6_flowinfo = win.sin6_flowinfo;
228 memcpy( &uaddr->in6.sin6_addr, &win.sin6_addr, sizeof(win.sin6_addr) );
229 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
230 uaddr->in6.sin6_scope_id = win.sin6_scope_id;
231 #endif
232 return sizeof(uaddr->in6);
235 #ifdef HAS_IPX
236 case WS_AF_IPX:
238 struct WS_sockaddr_ipx win = {0};
240 if (wsaddrlen < sizeof(win)) return 0;
241 memcpy( &win, wsaddr, sizeof(win) );
242 uaddr->ipx.sipx_family = AF_IPX;
243 memcpy( &uaddr->ipx.sipx_network, win.sa_netnum, sizeof(win.sa_netnum) );
244 memcpy( &uaddr->ipx.sipx_node, win.sa_nodenum, sizeof(win.sa_nodenum) );
245 uaddr->ipx.sipx_port = win.sa_socket;
246 return sizeof(uaddr->ipx);
248 #endif
250 #ifdef HAS_IRDA
251 case WS_AF_IRDA:
253 SOCKADDR_IRDA win = {0};
254 unsigned int lsap_sel;
256 if (wsaddrlen < sizeof(win)) return 0;
257 memcpy( &win, wsaddr, sizeof(win) );
258 uaddr->irda.sir_family = AF_IRDA;
259 if (sscanf( win.irdaServiceName, "LSAP-SEL%u", &lsap_sel ) == 1)
260 uaddr->irda.sir_lsap_sel = lsap_sel;
261 else
263 uaddr->irda.sir_lsap_sel = LSAP_ANY;
264 memcpy( uaddr->irda.sir_name, win.irdaServiceName, sizeof(win.irdaServiceName) );
266 memcpy( &uaddr->irda.sir_addr, win.irdaDeviceID, sizeof(win.irdaDeviceID) );
267 return sizeof(uaddr->irda);
269 #endif
271 case WS_AF_UNSPEC:
272 switch (wsaddrlen)
274 default: /* likely an ipv4 address */
275 case sizeof(struct WS_sockaddr_in):
276 return sizeof(uaddr->in);
278 #ifdef HAS_IPX
279 case sizeof(struct WS_sockaddr_ipx):
280 return sizeof(uaddr->ipx);
281 #endif
283 #ifdef HAS_IRDA
284 case sizeof(SOCKADDR_IRDA):
285 return sizeof(uaddr->irda);
286 #endif
288 case sizeof(struct WS_sockaddr_in6):
289 return sizeof(uaddr->in6);
292 default:
293 FIXME( "unknown address family %u\n", wsaddr->sa_family );
294 return 0;
298 static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_sockaddr *wsaddr, socklen_t wsaddrlen )
300 memset( wsaddr, 0, wsaddrlen );
302 switch (uaddr->addr.sa_family)
304 case AF_INET:
306 struct WS_sockaddr_in win = {0};
308 if (wsaddrlen < sizeof(win)) return -1;
309 win.sin_family = WS_AF_INET;
310 win.sin_port = uaddr->in.sin_port;
311 memcpy( &win.sin_addr, &uaddr->in.sin_addr, sizeof(win.sin_addr) );
312 memcpy( wsaddr, &win, sizeof(win) );
313 return sizeof(win);
316 case AF_INET6:
318 struct WS_sockaddr_in6 win = {0};
320 if (wsaddrlen < sizeof(win)) return -1;
321 win.sin6_family = WS_AF_INET6;
322 win.sin6_port = uaddr->in6.sin6_port;
323 win.sin6_flowinfo = uaddr->in6.sin6_flowinfo;
324 memcpy( &win.sin6_addr, &uaddr->in6.sin6_addr, sizeof(win.sin6_addr) );
325 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
326 win.sin6_scope_id = uaddr->in6.sin6_scope_id;
327 #endif
328 memcpy( wsaddr, &win, sizeof(win) );
329 return sizeof(win);
332 #ifdef HAS_IPX
333 case AF_IPX:
335 struct WS_sockaddr_ipx win = {0};
337 if (wsaddrlen < sizeof(win)) return -1;
338 win.sa_family = WS_AF_IPX;
339 memcpy( win.sa_netnum, &uaddr->ipx.sipx_network, sizeof(win.sa_netnum) );
340 memcpy( win.sa_nodenum, &uaddr->ipx.sipx_node, sizeof(win.sa_nodenum) );
341 win.sa_socket = uaddr->ipx.sipx_port;
342 memcpy( wsaddr, &win, sizeof(win) );
343 return sizeof(win);
345 #endif
347 #ifdef HAS_IRDA
348 case AF_IRDA:
350 SOCKADDR_IRDA win;
352 if (wsaddrlen < sizeof(win)) return -1;
353 win.irdaAddressFamily = WS_AF_IRDA;
354 memcpy( win.irdaDeviceID, &uaddr->irda.sir_addr, sizeof(win.irdaDeviceID) );
355 if (uaddr->irda.sir_lsap_sel != LSAP_ANY)
356 snprintf( win.irdaServiceName, sizeof(win.irdaServiceName), "LSAP-SEL%u", uaddr->irda.sir_lsap_sel );
357 else
358 memcpy( win.irdaServiceName, uaddr->irda.sir_name, sizeof(win.irdaServiceName) );
359 memcpy( wsaddr, &win, sizeof(win) );
360 return sizeof(win);
362 #endif
364 case AF_UNSPEC:
365 return 0;
367 default:
368 FIXME( "unknown address family %d\n", uaddr->addr.sa_family );
369 return -1;
373 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
374 static WSACMSGHDR *fill_control_message( int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len )
376 ULONG msgsize = sizeof(WSACMSGHDR) + WSA_CMSG_ALIGN(len);
377 char *ptr = (char *) current + sizeof(WSACMSGHDR);
379 if (msgsize > *maxsize)
380 return NULL;
381 *maxsize -= msgsize;
382 current->cmsg_len = sizeof(WSACMSGHDR) + len;
383 current->cmsg_level = level;
384 current->cmsg_type = type;
385 memcpy(ptr, data, len);
386 return (WSACMSGHDR *)(ptr + WSA_CMSG_ALIGN(len));
389 static int convert_control_headers(struct msghdr *hdr, WSABUF *control)
391 WSACMSGHDR *cmsg_win = (WSACMSGHDR *)control->buf, *ptr;
392 ULONG ctlsize = control->len;
393 struct cmsghdr *cmsg_unix;
395 ptr = cmsg_win;
396 for (cmsg_unix = CMSG_FIRSTHDR(hdr); cmsg_unix != NULL; cmsg_unix = CMSG_NXTHDR(hdr, cmsg_unix))
398 switch (cmsg_unix->cmsg_level)
400 case IPPROTO_IP:
401 switch (cmsg_unix->cmsg_type)
403 #if defined(IP_PKTINFO)
404 case IP_PKTINFO:
406 const struct in_pktinfo *data_unix = (struct in_pktinfo *)CMSG_DATA(cmsg_unix);
407 struct WS_in_pktinfo data_win;
409 memcpy( &data_win.ipi_addr, &data_unix->ipi_addr.s_addr, 4 ); /* 4 bytes = 32 address bits */
410 data_win.ipi_ifindex = data_unix->ipi_ifindex;
411 ptr = fill_control_message( WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
412 (void *)&data_win, sizeof(data_win) );
413 if (!ptr) goto error;
414 break;
416 #elif defined(IP_RECVDSTADDR)
417 case IP_RECVDSTADDR:
419 const struct in_addr *addr_unix = (struct in_addr *)CMSG_DATA(cmsg_unix);
420 struct WS_in_pktinfo data_win;
422 memcpy( &data_win.ipi_addr, &addr_unix->s_addr, 4 ); /* 4 bytes = 32 address bits */
423 data_win.ipi_ifindex = 0; /* FIXME */
424 ptr = fill_control_message( WS_IPPROTO_IP, WS_IP_PKTINFO, ptr, &ctlsize,
425 (void *)&data_win, sizeof(data_win) );
426 if (!ptr) goto error;
427 break;
429 #endif /* IP_PKTINFO */
431 #if defined(IP_TOS)
432 case IP_TOS:
434 INT tos = *(unsigned char *)CMSG_DATA(cmsg_unix);
435 ptr = fill_control_message( WS_IPPROTO_IP, WS_IP_TOS, ptr, &ctlsize,
436 &tos, sizeof(INT) );
437 if (!ptr) goto error;
438 break;
440 #endif /* IP_TOS */
442 #if defined(IP_TTL)
443 case IP_TTL:
445 ptr = fill_control_message( WS_IPPROTO_IP, WS_IP_TTL, ptr, &ctlsize,
446 CMSG_DATA(cmsg_unix), sizeof(INT) );
447 if (!ptr) goto error;
448 break;
450 #endif /* IP_TTL */
452 default:
453 FIXME("Unhandled IPPROTO_IP message header type %d\n", cmsg_unix->cmsg_type);
454 break;
456 break;
458 case IPPROTO_IPV6:
459 switch (cmsg_unix->cmsg_type)
461 #if defined(IPV6_HOPLIMIT)
462 case IPV6_HOPLIMIT:
464 ptr = fill_control_message( WS_IPPROTO_IPV6, WS_IPV6_HOPLIMIT, ptr, &ctlsize,
465 CMSG_DATA(cmsg_unix), sizeof(INT) );
466 if (!ptr) goto error;
467 break;
469 #endif /* IPV6_HOPLIMIT */
471 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO_IPI6_ADDR)
472 case IPV6_PKTINFO:
474 struct in6_pktinfo *data_unix = (struct in6_pktinfo *)CMSG_DATA(cmsg_unix);
475 struct WS_in6_pktinfo data_win;
477 memcpy(&data_win.ipi6_addr, &data_unix->ipi6_addr.s6_addr, 16);
478 data_win.ipi6_ifindex = data_unix->ipi6_ifindex;
479 ptr = fill_control_message( WS_IPPROTO_IPV6, WS_IPV6_PKTINFO, ptr, &ctlsize,
480 (void *)&data_win, sizeof(data_win) );
481 if (!ptr) goto error;
482 break;
484 #endif /* IPV6_PKTINFO */
486 #if defined(IPV6_TCLASS)
487 case IPV6_TCLASS:
489 ptr = fill_control_message( WS_IPPROTO_IPV6, WS_IPV6_TCLASS, ptr, &ctlsize,
490 CMSG_DATA(cmsg_unix), sizeof(INT) );
491 if (!ptr) goto error;
492 break;
494 #endif /* IPV6_TCLASS */
496 default:
497 FIXME("Unhandled IPPROTO_IPV6 message header type %d\n", cmsg_unix->cmsg_type);
498 break;
500 break;
502 default:
503 FIXME("Unhandled message header level %d\n", cmsg_unix->cmsg_level);
504 break;
508 control->len = (char *)ptr - (char *)cmsg_win;
509 return 1;
511 error:
512 control->len = 0;
513 return 0;
515 #else
516 static int convert_control_headers(struct msghdr *hdr, WSABUF *control)
518 ERR( "Message control headers cannot be properly supported on this system.\n" );
519 control->len = 0;
520 return 0;
522 #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
524 struct cmsghdr_32
526 ULONG cmsg_len;
527 INT cmsg_level;
528 INT cmsg_type;
529 /* UCHAR cmsg_data[]; */
532 static size_t cmsg_align_32( size_t len )
534 return (len + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
537 /* we assume that cmsg_data does not require translation, which is currently
538 * true for all messages */
539 static int wow64_translate_control( const WSABUF *control64, struct afd_wsabuf_32 *control32 )
541 char *const buf32 = ULongToPtr(control32->buf);
542 const ULONG max_len = control32->len;
543 const char *ptr64 = control64->buf;
544 char *ptr32 = buf32;
546 while (ptr64 < control64->buf + control64->len)
548 struct cmsghdr_32 *cmsg32 = (struct cmsghdr_32 *)ptr32;
549 const WSACMSGHDR *cmsg64 = (const WSACMSGHDR *)ptr64;
551 if (ptr32 + sizeof(*cmsg32) + cmsg_align_32( cmsg64->cmsg_len ) > buf32 + max_len)
553 control32->len = 0;
554 return 0;
557 cmsg32->cmsg_len = cmsg64->cmsg_len - sizeof(*cmsg64) + sizeof(*cmsg32);
558 cmsg32->cmsg_level = cmsg64->cmsg_level;
559 cmsg32->cmsg_type = cmsg64->cmsg_type;
560 memcpy( cmsg32 + 1, cmsg64 + 1, cmsg64->cmsg_len );
562 ptr64 += WSA_CMSG_ALIGN( cmsg64->cmsg_len );
563 ptr32 += cmsg_align_32( cmsg32->cmsg_len );
566 control32->len = ptr32 - buf32;
567 FIXME("-> %d\n", control32->len);
568 return 1;
571 struct ip_hdr
573 BYTE v_hl; /* version << 4 | hdr_len */
574 BYTE tos;
575 UINT16 tot_len;
576 UINT16 id;
577 UINT16 frag_off;
578 BYTE ttl;
579 BYTE protocol;
580 UINT16 checksum;
581 ULONG saddr;
582 ULONG daddr;
585 struct icmp_hdr
587 BYTE type;
588 BYTE code;
589 UINT16 checksum;
590 union
592 struct
594 UINT16 id;
595 UINT16 sequence;
596 } echo;
597 } un;
600 /* rfc 1071 checksum */
601 static unsigned short chksum(BYTE *data, unsigned int count)
603 unsigned int sum = 0, carry = 0;
604 unsigned short check, s;
606 while (count > 1)
608 s = *(unsigned short *)data;
609 data += 2;
610 sum += carry;
611 sum += s;
612 carry = s > sum;
613 count -= 2;
615 sum += carry; /* This won't produce another carry */
616 sum = (sum & 0xffff) + (sum >> 16);
618 if (count) sum += *data; /* LE-only */
620 sum = (sum & 0xffff) + (sum >> 16);
621 /* fold in any carry */
622 sum = (sum & 0xffff) + (sum >> 16);
624 check = ~sum;
625 return check;
628 static ssize_t fixup_icmp_over_dgram( struct msghdr *hdr, union unix_sockaddr *unix_addr,
629 HANDLE handle, ssize_t recv_len, NTSTATUS *status )
631 unsigned int tot_len = sizeof(struct ip_hdr) + recv_len;
632 struct icmp_hdr *icmp_h = NULL;
633 unsigned int fixup_status;
634 struct cmsghdr *cmsg;
635 struct ip_hdr ip_h;
636 size_t buf_len;
637 char *buf;
639 if (hdr->msg_iovlen != 1)
641 FIXME( "Buffer count %zu is not supported for ICMP fixup.\n", (size_t)hdr->msg_iovlen );
642 return recv_len;
645 buf = hdr->msg_iov[0].iov_base;
646 buf_len = hdr->msg_iov[0].iov_len;
648 if (recv_len + sizeof(ip_h) > buf_len)
649 *status = STATUS_BUFFER_OVERFLOW;
651 if (buf_len < sizeof(ip_h))
653 recv_len = buf_len;
655 else
657 recv_len = min( recv_len, buf_len - sizeof(ip_h) );
658 memmove( buf + sizeof(ip_h), buf, recv_len );
659 if (recv_len >= sizeof(struct icmp_hdr))
660 icmp_h = (struct icmp_hdr *)(buf + sizeof(ip_h));
661 recv_len += sizeof(ip_h);
663 memset( &ip_h, 0, sizeof(ip_h) );
664 ip_h.v_hl = (4 << 4) | (sizeof(ip_h) >> 2);
665 ip_h.tot_len = htons( tot_len );
666 ip_h.protocol = 1;
667 ip_h.saddr = unix_addr->in.sin_addr.s_addr;
669 for (cmsg = CMSG_FIRSTHDR( hdr ); cmsg; cmsg = CMSG_NXTHDR( hdr, cmsg ))
671 if (cmsg->cmsg_level != IPPROTO_IP) continue;
672 switch (cmsg->cmsg_type)
674 #if defined(IP_TTL)
675 case IP_TTL:
676 ip_h.ttl = *(BYTE *)CMSG_DATA( cmsg );
677 break;
678 #endif
679 #if defined(IP_TOS)
680 case IP_TOS:
681 ip_h.tos = *(BYTE *)CMSG_DATA( cmsg );
682 break;
683 #endif
684 #if defined(IP_PKTINFO)
685 case IP_PKTINFO:
687 struct in_pktinfo *info;
689 info = (struct in_pktinfo *)CMSG_DATA( cmsg );
690 ip_h.daddr = info->ipi_addr.s_addr;
691 break;
693 #endif
696 if (icmp_h)
698 SERVER_START_REQ( socket_get_icmp_id )
700 req->handle = wine_server_obj_handle( handle );
701 req->icmp_seq = icmp_h->un.echo.sequence;
702 if (!(fixup_status = wine_server_call( req )))
703 icmp_h->un.echo.id = reply->icmp_id;
704 else
705 WARN( "socket_get_fixup_data returned %#x.\n", fixup_status );
707 SERVER_END_REQ;
709 if (!fixup_status)
711 icmp_h->checksum = 0;
712 icmp_h->checksum = chksum( (BYTE *)icmp_h, recv_len - sizeof(ip_h) );
715 ip_h.checksum = chksum( (BYTE *)&ip_h, sizeof(ip_h) );
716 memcpy( buf, &ip_h, min( sizeof(ip_h), buf_len ));
718 return recv_len;
721 static NTSTATUS try_recv( int fd, struct async_recv_ioctl *async, ULONG_PTR *size )
723 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
724 char control_buffer[512];
725 #endif
726 union unix_sockaddr unix_addr;
727 struct msghdr hdr;
728 NTSTATUS status;
729 ssize_t ret;
731 memset( &hdr, 0, sizeof(hdr) );
732 if (async->addr || async->icmp_over_dgram)
734 hdr.msg_name = &unix_addr.addr;
735 hdr.msg_namelen = sizeof(unix_addr);
737 hdr.msg_iov = async->iov;
738 hdr.msg_iovlen = async->count;
739 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
740 hdr.msg_control = control_buffer;
741 hdr.msg_controllen = sizeof(control_buffer);
742 #endif
743 while ((ret = virtual_locked_recvmsg( fd, &hdr, async->unix_flags )) < 0 && errno == EINTR);
745 if (ret < 0)
747 /* Unix-like systems return EINVAL when attempting to read OOB data from
748 * an empty socket buffer; Windows returns WSAEWOULDBLOCK. */
749 if ((async->unix_flags & MSG_OOB) && errno == EINVAL)
750 errno = EWOULDBLOCK;
752 if (errno != EWOULDBLOCK) WARN( "recvmsg: %s\n", strerror( errno ) );
753 return sock_errno_to_status( errno );
756 status = (hdr.msg_flags & MSG_TRUNC) ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
757 if (async->icmp_over_dgram)
758 ret = fixup_icmp_over_dgram( &hdr, &unix_addr, async->io.handle, ret, &status );
760 if (async->control)
762 if (async->icmp_over_dgram)
763 FIXME( "May return extra control headers.\n" );
765 if (in_wow64_call())
767 char control_buffer64[512];
768 WSABUF wsabuf;
770 wsabuf.len = sizeof(control_buffer64);
771 wsabuf.buf = control_buffer64;
772 if (convert_control_headers( &hdr, &wsabuf ))
774 if (!wow64_translate_control( &wsabuf, async->control ))
776 WARN( "Application passed insufficient room for control headers.\n" );
777 *async->ret_flags |= WS_MSG_CTRUNC;
778 status = STATUS_BUFFER_OVERFLOW;
781 else
783 FIXME( "control buffer is too small\n" );
784 *async->ret_flags |= WS_MSG_CTRUNC;
785 status = STATUS_BUFFER_OVERFLOW;
788 else
790 if (!convert_control_headers( &hdr, async->control ))
792 WARN( "Application passed insufficient room for control headers.\n" );
793 *async->ret_flags |= WS_MSG_CTRUNC;
794 status = STATUS_BUFFER_OVERFLOW;
799 /* If this socket is connected, Linux doesn't give us msg_name and
800 * msg_namelen from recvmsg, but it does set msg_namelen to zero.
802 * MSDN says that the address is ignored for connection-oriented sockets, so
803 * don't try to translate it.
805 if (async->addr && hdr.msg_namelen)
806 *async->addr_len = sockaddr_from_unix( &unix_addr, async->addr, *async->addr_len );
808 *size = ret;
809 return status;
812 static BOOL async_recv_proc( void *user, ULONG_PTR *info, unsigned int *status )
814 struct async_recv_ioctl *async = user;
815 int fd, needs_close;
817 TRACE( "%#x\n", *status );
819 if (*status == STATUS_ALERTED)
821 if ((*status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL )))
822 return TRUE;
824 *status = try_recv( fd, async, info );
825 TRACE( "got status %#x, %#lx bytes read\n", *status, *info );
826 if (needs_close) close( fd );
828 if (*status == STATUS_DEVICE_NOT_READY)
829 return FALSE;
831 release_fileio( &async->io );
832 return TRUE;
835 static BOOL is_icmp_over_dgram( int fd )
837 #ifdef linux
838 socklen_t len;
839 int val;
841 len = sizeof(val);
842 if (getsockopt( fd, SOL_SOCKET, SO_PROTOCOL, (char *)&val, &len ) || val != IPPROTO_ICMP)
843 return FALSE;
845 len = sizeof(val);
846 return !getsockopt( fd, SOL_SOCKET, SO_TYPE, (char *)&val, &len ) && val == SOCK_DGRAM;
847 #else
848 return FALSE;
849 #endif
852 static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io,
853 int fd, struct async_recv_ioctl *async, int force_async )
855 HANDLE wait_handle;
856 BOOL nonblocking;
857 unsigned int i, status;
858 ULONG options;
860 for (i = 0; i < async->count; ++i)
862 if (!virtual_check_buffer_for_write( async->iov[i].iov_base, async->iov[i].iov_len ))
864 release_fileio( &async->io );
865 return STATUS_ACCESS_VIOLATION;
869 SERVER_START_REQ( recv_socket )
871 req->force_async = force_async;
872 req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
873 req->oob = !!(async->unix_flags & MSG_OOB);
874 status = wine_server_call( req );
875 wait_handle = wine_server_ptr_handle( reply->wait );
876 options = reply->options;
877 nonblocking = reply->nonblocking;
879 SERVER_END_REQ;
881 /* the server currently will never succeed immediately */
882 assert(status == STATUS_ALERTED || status == STATUS_PENDING || NT_ERROR(status));
884 if (status == STATUS_ALERTED)
886 ULONG_PTR information;
888 status = try_recv( fd, async, &information );
889 if (status == STATUS_DEVICE_NOT_READY && (force_async || !nonblocking))
890 status = STATUS_PENDING;
891 if (!NT_ERROR(status) && status != STATUS_PENDING)
893 io->Status = status;
894 io->Information = information;
896 set_async_direct_result( &wait_handle, status, information, FALSE );
899 if (status != STATUS_PENDING)
900 release_fileio( &async->io );
902 if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT );
903 return status;
907 static NTSTATUS sock_ioctl_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io,
908 int fd, const void *buffers_ptr, unsigned int count, WSABUF *control,
909 struct WS_sockaddr *addr, int *addr_len, unsigned int *ret_flags, int unix_flags, int force_async )
911 struct async_recv_ioctl *async;
912 DWORD async_size;
913 unsigned int i;
915 if (unix_flags & MSG_OOB)
917 int oobinline;
918 socklen_t len = sizeof(oobinline);
919 if (!getsockopt( fd, SOL_SOCKET, SO_OOBINLINE, (char *)&oobinline, &len ) && oobinline)
920 return STATUS_INVALID_PARAMETER;
923 async_size = offsetof( struct async_recv_ioctl, iov[count] );
925 if (!(async = (struct async_recv_ioctl *)alloc_fileio( async_size, async_recv_proc, handle )))
926 return STATUS_NO_MEMORY;
928 async->count = count;
929 if (in_wow64_call())
931 const struct afd_wsabuf_32 *buffers = buffers_ptr;
933 for (i = 0; i < count; ++i)
935 async->iov[i].iov_base = ULongToPtr( buffers[i].buf );
936 async->iov[i].iov_len = buffers[i].len;
939 else
941 const WSABUF *buffers = buffers_ptr;
943 for (i = 0; i < count; ++i)
945 async->iov[i].iov_base = buffers[i].buf;
946 async->iov[i].iov_len = buffers[i].len;
949 async->unix_flags = unix_flags;
950 async->control = control;
951 async->addr = addr;
952 async->addr_len = addr_len;
953 async->ret_flags = ret_flags;
954 async->icmp_over_dgram = is_icmp_over_dgram( fd );
956 return sock_recv( handle, event, apc, apc_user, io, fd, async, force_async );
960 NTSTATUS sock_read( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc,
961 void *apc_user, IO_STATUS_BLOCK *io, void *buffer, ULONG length )
963 static const DWORD async_size = offsetof( struct async_recv_ioctl, iov[1] );
964 struct async_recv_ioctl *async;
966 if (!(async = (struct async_recv_ioctl *)alloc_fileio( async_size, async_recv_proc, handle )))
967 return STATUS_NO_MEMORY;
969 async->count = 1;
970 async->iov[0].iov_base = buffer;
971 async->iov[0].iov_len = length;
972 async->unix_flags = 0;
973 async->control = NULL;
974 async->addr = NULL;
975 async->addr_len = NULL;
976 async->ret_flags = NULL;
977 async->icmp_over_dgram = is_icmp_over_dgram( fd );
979 return sock_recv( handle, event, apc, apc_user, io, fd, async, 1 );
983 static NTSTATUS try_send( int fd, struct async_send_ioctl *async )
985 union unix_sockaddr unix_addr;
986 struct msghdr hdr;
987 ssize_t ret;
989 memset( &hdr, 0, sizeof(hdr) );
990 if (async->addr)
992 hdr.msg_name = &unix_addr;
993 hdr.msg_namelen = sockaddr_to_unix( async->addr, async->addr_len, &unix_addr );
994 if (!hdr.msg_namelen)
996 ERR( "failed to convert address\n" );
997 return STATUS_ACCESS_VIOLATION;
1000 #if defined(HAS_IPX) && defined(SOL_IPX)
1001 if (async->addr->sa_family == WS_AF_IPX)
1003 int type;
1004 socklen_t len = sizeof(type);
1006 /* The packet type is stored at the IPX socket level. At least the
1007 * linux kernel seems to do something with it in case hdr.msg_name
1008 * is NULL. Nonetheless we can use it to store the packet type, and
1009 * then we can retrieve it using getsockopt. After that we can set
1010 * the IPX type in the sockaddr_ipx structure with the stored value.
1012 if (getsockopt(fd, SOL_IPX, IPX_TYPE, &type, &len) >= 0)
1013 unix_addr.ipx.sipx_type = type;
1015 #endif
1018 hdr.msg_iov = async->iov + async->iov_cursor;
1019 hdr.msg_iovlen = async->count - async->iov_cursor;
1021 while ((ret = sendmsg( fd, &hdr, async->unix_flags )) == -1)
1023 if (errno == EISCONN)
1025 hdr.msg_name = NULL;
1026 hdr.msg_namelen = 0;
1028 else if (errno != EINTR)
1030 if (errno != EWOULDBLOCK) WARN( "sendmsg: %s\n", strerror( errno ) );
1031 return sock_errno_to_status( errno );
1035 async->sent_len += ret;
1037 while (async->iov_cursor < async->count && ret >= async->iov[async->iov_cursor].iov_len)
1038 ret -= async->iov[async->iov_cursor++].iov_len;
1039 if (async->iov_cursor < async->count)
1041 async->iov[async->iov_cursor].iov_base = (char *)async->iov[async->iov_cursor].iov_base + ret;
1042 async->iov[async->iov_cursor].iov_len -= ret;
1043 return STATUS_DEVICE_NOT_READY;
1045 return STATUS_SUCCESS;
1048 static BOOL async_send_proc( void *user, ULONG_PTR *info, unsigned int *status )
1050 struct async_send_ioctl *async = user;
1051 int fd, needs_close;
1053 TRACE( "%#x\n", *status );
1055 if (*status == STATUS_ALERTED)
1057 if ((*status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL )))
1058 return TRUE;
1060 *status = try_send( fd, async );
1061 TRACE( "got status %#x\n", *status );
1063 if (needs_close) close( fd );
1065 if (*status == STATUS_DEVICE_NOT_READY)
1066 return FALSE;
1068 *info = async->sent_len;
1069 release_fileio( &async->io );
1070 return TRUE;
1073 static void sock_save_icmp_id( struct async_send_ioctl *async )
1075 unsigned short id, seq;
1076 struct icmp_hdr *h;
1078 if (async->count != 1 || async->iov[0].iov_len < sizeof(*h))
1080 FIXME( "ICMP over DGRAM fixup is not supported for count %u, len %zu.\n", async->count, async->iov[0].iov_len );
1081 return;
1084 h = async->iov[0].iov_base;
1085 id = h->un.echo.id;
1086 seq = h->un.echo.sequence;
1087 SERVER_START_REQ( socket_send_icmp_id )
1089 req->handle = wine_server_obj_handle( async->io.handle );
1090 req->icmp_id = id;
1091 req->icmp_seq = seq;
1092 if (wine_server_call( req ))
1093 WARN( "socket_fixup_send_data failed.\n" );
1095 SERVER_END_REQ;
1098 static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
1099 IO_STATUS_BLOCK *io, int fd, struct async_send_ioctl *async, int force_async )
1101 HANDLE wait_handle;
1102 BOOL nonblocking;
1103 unsigned int status;
1104 ULONG options;
1106 SERVER_START_REQ( send_socket )
1108 req->force_async = force_async;
1109 req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
1110 status = wine_server_call( req );
1111 wait_handle = wine_server_ptr_handle( reply->wait );
1112 options = reply->options;
1113 nonblocking = reply->nonblocking;
1115 SERVER_END_REQ;
1117 /* the server currently will never succeed immediately */
1118 assert(status == STATUS_ALERTED || status == STATUS_PENDING || NT_ERROR(status));
1120 if (!NT_ERROR(status) && is_icmp_over_dgram( fd ))
1121 sock_save_icmp_id( async );
1123 if (status == STATUS_ALERTED)
1125 ULONG_PTR information;
1127 status = try_send( fd, async );
1128 if (status == STATUS_DEVICE_NOT_READY && (force_async || !nonblocking))
1129 status = STATUS_PENDING;
1131 /* If we had a short write and the socket is nonblocking (and we are
1132 * not trying to force the operation to be asynchronous), return
1133 * success. Windows actually refuses to send any data in this case,
1134 * and returns EWOULDBLOCK, but we have no way of doing that. */
1135 if (status == STATUS_DEVICE_NOT_READY && async->sent_len)
1136 status = STATUS_SUCCESS;
1138 information = async->sent_len;
1139 if (!NT_ERROR(status) && status != STATUS_PENDING)
1141 io->Status = status;
1142 io->Information = information;
1145 set_async_direct_result( &wait_handle, status, information, FALSE );
1148 if (status != STATUS_PENDING)
1149 release_fileio( &async->io );
1151 if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT );
1152 return status;
1155 static NTSTATUS sock_ioctl_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
1156 IO_STATUS_BLOCK *io, int fd, const void *buffers_ptr, unsigned int count,
1157 const struct WS_sockaddr *addr, unsigned int addr_len, int unix_flags, int force_async )
1159 struct async_send_ioctl *async;
1160 DWORD async_size;
1161 unsigned int i;
1163 async_size = offsetof( struct async_send_ioctl, iov[count] );
1165 if (!(async = (struct async_send_ioctl *)alloc_fileio( async_size, async_send_proc, handle )))
1166 return STATUS_NO_MEMORY;
1168 async->count = count;
1169 if (in_wow64_call())
1171 const struct afd_wsabuf_32 *buffers = buffers_ptr;
1173 for (i = 0; i < count; ++i)
1175 async->iov[i].iov_base = ULongToPtr( buffers[i].buf );
1176 async->iov[i].iov_len = buffers[i].len;
1179 else
1181 const WSABUF *buffers = buffers_ptr;
1183 for (i = 0; i < count; ++i)
1185 async->iov[i].iov_base = buffers[i].buf;
1186 async->iov[i].iov_len = buffers[i].len;
1189 async->unix_flags = unix_flags;
1190 async->addr = addr;
1191 async->addr_len = addr_len;
1192 async->iov_cursor = 0;
1193 async->sent_len = 0;
1195 return sock_send( handle, event, apc, apc_user, io, fd, async, force_async );
1199 NTSTATUS sock_write( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc,
1200 void *apc_user, IO_STATUS_BLOCK *io, const void *buffer, ULONG length )
1202 static const DWORD async_size = offsetof( struct async_send_ioctl, iov[1] );
1203 struct async_send_ioctl *async;
1205 if (!(async = (struct async_send_ioctl *)alloc_fileio( async_size, async_recv_proc, handle )))
1206 return STATUS_NO_MEMORY;
1208 async->count = 1;
1209 async->iov[0].iov_base = (void *)buffer;
1210 async->iov[0].iov_len = length;
1211 async->unix_flags = 0;
1212 async->addr = NULL;
1213 async->addr_len = 0;
1214 async->iov_cursor = 0;
1215 async->sent_len = 0;
1217 return sock_send( handle, event, apc, apc_user, io, fd, async, 1 );
1221 static ssize_t do_send( int fd, const void *buffer, size_t len, int flags )
1223 ssize_t ret;
1224 while ((ret = send( fd, buffer, len, flags )) < 0 && errno == EINTR);
1225 if (ret < 0 && errno != EWOULDBLOCK) WARN( "send: %s\n", strerror( errno ) );
1226 return ret;
1229 static NTSTATUS try_transmit( int sock_fd, int file_fd, struct async_transmit_ioctl *async )
1231 ssize_t ret;
1233 while (async->head_cursor < async->head_len)
1235 TRACE( "sending %u bytes of header data\n", async->head_len - async->head_cursor );
1236 ret = do_send( sock_fd, async->head + async->head_cursor,
1237 async->head_len - async->head_cursor, 0 );
1238 if (ret < 0) return sock_errno_to_status( errno );
1239 TRACE( "send returned %zd\n", ret );
1240 async->head_cursor += ret;
1243 while (async->buffer_cursor < async->read_len)
1245 TRACE( "sending %u bytes of file data\n", async->read_len - async->buffer_cursor );
1246 ret = do_send( sock_fd, async->buffer + async->buffer_cursor,
1247 async->read_len - async->buffer_cursor, 0 );
1248 if (ret < 0) return sock_errno_to_status( errno );
1249 TRACE( "send returned %zd\n", ret );
1250 async->buffer_cursor += ret;
1251 async->file_cursor += ret;
1254 if (async->file && async->buffer_cursor == async->read_len)
1256 unsigned int read_size = async->buffer_size;
1258 if (async->file_len)
1259 read_size = min( read_size, async->file_len - async->file_cursor );
1261 TRACE( "reading %u bytes of file data\n", read_size );
1264 if (async->offset.QuadPart == FILE_USE_FILE_POINTER_POSITION)
1265 ret = read( file_fd, async->buffer, read_size );
1266 else
1267 ret = pread( file_fd, async->buffer, read_size, async->offset.QuadPart );
1268 } while (ret < 0 && errno == EINTR);
1269 if (ret < 0) return errno_to_status( errno );
1270 TRACE( "read returned %zd\n", ret );
1272 async->read_len = ret;
1273 async->buffer_cursor = 0;
1274 if (async->offset.QuadPart != FILE_USE_FILE_POINTER_POSITION)
1275 async->offset.QuadPart += ret;
1277 if (ret < read_size || (async->file_len && async->file_cursor == async->file_len))
1278 async->file = NULL;
1279 return STATUS_DEVICE_NOT_READY; /* still more data to send */
1282 while (async->tail_cursor < async->tail_len)
1284 TRACE( "sending %u bytes of tail data\n", async->tail_len - async->tail_cursor );
1285 ret = do_send( sock_fd, async->tail + async->tail_cursor,
1286 async->tail_len - async->tail_cursor, 0 );
1287 if (ret < 0) return sock_errno_to_status( errno );
1288 TRACE( "send returned %zd\n", ret );
1289 async->tail_cursor += ret;
1292 return STATUS_SUCCESS;
1295 static BOOL async_transmit_proc( void *user, ULONG_PTR *info, unsigned int *status )
1297 int sock_fd, file_fd = -1, sock_needs_close = FALSE, file_needs_close = FALSE;
1298 struct async_transmit_ioctl *async = user;
1300 TRACE( "%#x\n", *status );
1302 if (*status == STATUS_ALERTED)
1304 if ((*status = server_get_unix_fd( async->io.handle, 0, &sock_fd, &sock_needs_close, NULL, NULL )))
1305 return TRUE;
1307 if (async->file && (*status = server_get_unix_fd( async->file, 0, &file_fd, &file_needs_close, NULL, NULL )))
1309 if (sock_needs_close) close( sock_fd );
1310 return TRUE;
1313 *status = try_transmit( sock_fd, file_fd, async );
1314 TRACE( "got status %#x\n", *status );
1316 if (sock_needs_close) close( sock_fd );
1317 if (file_needs_close) close( file_fd );
1319 if (*status == STATUS_DEVICE_NOT_READY)
1320 return FALSE;
1322 *info = async->head_cursor + async->file_cursor + async->tail_cursor;
1323 release_fileio( &async->io );
1324 return TRUE;
1327 static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
1328 IO_STATUS_BLOCK *io, int fd, const struct afd_transmit_params *params )
1330 int file_fd, file_needs_close = FALSE;
1331 struct async_transmit_ioctl *async;
1332 enum server_fd_type file_type;
1333 union unix_sockaddr addr;
1334 socklen_t addr_len;
1335 HANDLE wait_handle;
1336 unsigned int status;
1337 ULONG options;
1339 addr_len = sizeof(addr);
1340 if (getpeername( fd, &addr.addr, &addr_len ) != 0)
1341 return STATUS_INVALID_CONNECTION;
1343 if (params->file)
1345 if ((status = server_get_unix_fd( ULongToHandle( params->file ), 0, &file_fd, &file_needs_close, &file_type, NULL )))
1346 return status;
1347 if (file_needs_close) close( file_fd );
1349 if (file_type != FD_TYPE_FILE)
1351 FIXME( "unsupported file type %#x\n", file_type );
1352 return STATUS_NOT_IMPLEMENTED;
1356 if (!(async = (struct async_transmit_ioctl *)alloc_fileio( sizeof(*async), async_transmit_proc, handle )))
1357 return STATUS_NO_MEMORY;
1359 async->file = ULongToHandle( params->file );
1360 async->buffer_size = params->buffer_size ? params->buffer_size : 65536;
1361 if (!(async->buffer = malloc( async->buffer_size )))
1363 release_fileio( &async->io );
1364 return STATUS_NO_MEMORY;
1366 async->read_len = 0;
1367 async->head_cursor = 0;
1368 async->file_cursor = 0;
1369 async->buffer_cursor = 0;
1370 async->tail_cursor = 0;
1371 async->file_len = params->file_len;
1372 async->flags = params->flags;
1373 async->head = u64_to_user_ptr(params->head_ptr);
1374 async->head_len = params->head_len;
1375 async->tail = u64_to_user_ptr(params->tail_ptr);
1376 async->tail_len = params->tail_len;
1377 async->offset = params->offset;
1379 SERVER_START_REQ( send_socket )
1381 req->force_async = 1;
1382 req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
1383 status = wine_server_call( req );
1384 wait_handle = wine_server_ptr_handle( reply->wait );
1385 options = reply->options;
1387 SERVER_END_REQ;
1389 /* the server currently will never succeed immediately */
1390 assert(status == STATUS_ALERTED || status == STATUS_PENDING || NT_ERROR(status));
1392 if (status == STATUS_ALERTED)
1394 ULONG_PTR information;
1396 status = try_transmit( fd, file_fd, async );
1397 if (status == STATUS_DEVICE_NOT_READY)
1398 status = STATUS_PENDING;
1400 information = async->head_cursor + async->file_cursor + async->tail_cursor;
1401 if (!NT_ERROR(status) && status != STATUS_PENDING)
1403 io->Status = status;
1404 io->Information = information;
1407 set_async_direct_result( &wait_handle, status, information, TRUE );
1410 if (status != STATUS_PENDING)
1411 release_fileio( &async->io );
1413 if (!status && !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
1415 /* Pretend we always do async I/O. The client can always retrieve
1416 * the actual I/O status via the IO_STATUS_BLOCK.
1418 status = STATUS_PENDING;
1421 if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT );
1422 return status;
1425 static void complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
1426 IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information )
1428 ULONG_PTR iosb_ptr = iosb_client_ptr(io);
1430 io->Status = status;
1431 io->Information = information;
1432 if (event) NtSetEvent( event, NULL );
1433 if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 );
1434 if (apc_user) add_completion( handle, (ULONG_PTR)apc_user, status, information, FALSE );
1438 static NTSTATUS do_getsockopt( HANDLE handle, IO_STATUS_BLOCK *io, int level,
1439 int option, void *out_buffer, ULONG out_size )
1441 int fd, needs_close = FALSE;
1442 socklen_t len = out_size;
1443 NTSTATUS status;
1444 int ret;
1446 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1447 return status;
1449 ret = getsockopt( fd, level, option, out_buffer, &len );
1450 if (needs_close) close( fd );
1451 if (ret) return sock_errno_to_status( errno );
1452 if (io)
1454 io->Status = STATUS_SUCCESS;
1455 io->Information = len;
1457 return STATUS_SUCCESS;
1461 static NTSTATUS do_setsockopt( HANDLE handle, IO_STATUS_BLOCK *io, int level,
1462 int option, const void *optval, socklen_t optlen )
1464 int fd, needs_close = FALSE;
1465 NTSTATUS status;
1466 int ret;
1468 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1469 return status;
1471 ret = setsockopt( fd, level, option, optval, optlen );
1472 if (needs_close) close( fd );
1473 if (ret) return sock_errno_to_status( errno );
1474 if (io) io->Status = STATUS_SUCCESS;
1475 return STATUS_SUCCESS;
1479 static int get_sock_type( HANDLE handle )
1481 int sock_type;
1482 if (do_getsockopt( handle, NULL, SOL_SOCKET, SO_TYPE, &sock_type, sizeof(sock_type) ) != STATUS_SUCCESS)
1483 return -1;
1484 return sock_type;
1488 NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io,
1489 UINT code, void *in_buffer, UINT in_size, void *out_buffer, UINT out_size )
1491 int fd, needs_close = FALSE;
1492 NTSTATUS status;
1494 TRACE( "handle %p, code %#x, in_buffer %p, in_size %u, out_buffer %p, out_size %u\n",
1495 handle, code, in_buffer, in_size, out_buffer, out_size );
1497 switch (code)
1499 case IOCTL_AFD_BIND:
1501 const struct afd_bind_params *params = in_buffer;
1503 if (params->unknown) FIXME( "bind: got unknown %#x\n", params->unknown );
1505 status = STATUS_BAD_DEVICE_TYPE;
1506 break;
1509 case IOCTL_AFD_GETSOCKNAME:
1510 if (in_size) FIXME( "unexpected input size %u\n", in_size );
1512 status = STATUS_BAD_DEVICE_TYPE;
1513 break;
1515 case IOCTL_AFD_LISTEN:
1517 const struct afd_listen_params *params = in_buffer;
1519 TRACE( "backlog %u\n", params->backlog );
1520 if (out_size) FIXME( "unexpected output size %u\n", out_size );
1521 if (params->unknown1) FIXME( "listen: got unknown1 %#x\n", params->unknown1 );
1522 if (params->unknown2) FIXME( "listen: got unknown2 %#x\n", params->unknown2 );
1524 status = STATUS_BAD_DEVICE_TYPE;
1525 break;
1528 case IOCTL_AFD_EVENT_SELECT:
1530 const struct afd_event_select_params *params = in_buffer;
1532 TRACE( "event %p, mask %#x\n", params->event, params->mask );
1533 if (out_size) FIXME( "unexpected output size %u\n", out_size );
1535 status = STATUS_BAD_DEVICE_TYPE;
1536 break;
1539 case IOCTL_AFD_GET_EVENTS:
1540 if (in_size) FIXME( "unexpected input size %u\n", in_size );
1542 status = STATUS_BAD_DEVICE_TYPE;
1543 break;
1545 case IOCTL_AFD_POLL:
1546 status = STATUS_BAD_DEVICE_TYPE;
1547 break;
1549 case IOCTL_AFD_RECV:
1551 struct afd_recv_params params;
1552 int unix_flags = 0;
1554 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1555 return status;
1557 if (out_size) FIXME( "unexpected output size %u\n", out_size );
1559 if (in_wow64_call())
1561 const struct afd_recv_params_32 *params32 = in_buffer;
1563 if (in_size < sizeof(struct afd_recv_params_32))
1565 status = STATUS_INVALID_PARAMETER;
1566 break;
1569 params.recv_flags = params32->recv_flags;
1570 params.msg_flags = params32->msg_flags;
1571 params.buffers = ULongToPtr( params32->buffers );
1572 params.count = params32->count;
1574 else
1576 if (in_size < sizeof(struct afd_recv_params))
1578 status = STATUS_INVALID_PARAMETER;
1579 break;
1582 memcpy( &params, in_buffer, sizeof(params) );
1585 if ((params.msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == 0 ||
1586 (params.msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == (AFD_MSG_NOT_OOB | AFD_MSG_OOB))
1588 status = STATUS_INVALID_PARAMETER;
1589 break;
1592 if (params.msg_flags & ~(AFD_MSG_NOT_OOB | AFD_MSG_OOB | AFD_MSG_PEEK | AFD_MSG_WAITALL))
1593 FIXME( "unknown msg_flags %#x\n", params.msg_flags );
1594 if (params.recv_flags & ~AFD_RECV_FORCE_ASYNC)
1595 FIXME( "unknown recv_flags %#x\n", params.recv_flags );
1597 if (params.msg_flags & AFD_MSG_OOB)
1598 unix_flags |= MSG_OOB;
1599 if (params.msg_flags & AFD_MSG_PEEK)
1600 unix_flags |= MSG_PEEK;
1601 if (params.msg_flags & AFD_MSG_WAITALL)
1602 FIXME( "MSG_WAITALL is not supported\n" );
1603 status = sock_ioctl_recv( handle, event, apc, apc_user, io, fd, params.buffers, params.count, NULL,
1604 NULL, NULL, NULL, unix_flags, !!(params.recv_flags & AFD_RECV_FORCE_ASYNC) );
1605 if (needs_close) close( fd );
1606 return status;
1609 case IOCTL_AFD_WINE_RECVMSG:
1611 struct afd_recvmsg_params *params = in_buffer;
1612 unsigned int *ws_flags = u64_to_user_ptr(params->ws_flags_ptr);
1613 int unix_flags = 0;
1615 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1616 return status;
1618 if (in_size < sizeof(*params))
1620 status = STATUS_BUFFER_TOO_SMALL;
1621 break;
1624 if (*ws_flags & WS_MSG_OOB)
1625 unix_flags |= MSG_OOB;
1626 if (*ws_flags & WS_MSG_PEEK)
1627 unix_flags |= MSG_PEEK;
1628 if (*ws_flags & WS_MSG_WAITALL)
1629 FIXME( "MSG_WAITALL is not supported\n" );
1630 status = sock_ioctl_recv( handle, event, apc, apc_user, io, fd, u64_to_user_ptr(params->buffers_ptr),
1631 params->count, u64_to_user_ptr(params->control_ptr),
1632 u64_to_user_ptr(params->addr_ptr), u64_to_user_ptr(params->addr_len_ptr),
1633 ws_flags, unix_flags, params->force_async );
1634 if (needs_close) close( fd );
1635 return status;
1638 case IOCTL_AFD_WINE_SENDMSG:
1640 const struct afd_sendmsg_params *params = in_buffer;
1641 int unix_flags = 0;
1643 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1644 return status;
1646 if (in_size < sizeof(*params))
1648 status = STATUS_BUFFER_TOO_SMALL;
1649 break;
1652 if (params->ws_flags & WS_MSG_OOB)
1653 unix_flags |= MSG_OOB;
1654 if (params->ws_flags & WS_MSG_PARTIAL)
1655 WARN( "ignoring MSG_PARTIAL\n" );
1656 if (params->ws_flags & ~(WS_MSG_OOB | WS_MSG_PARTIAL))
1657 FIXME( "unknown flags %#x\n", params->ws_flags );
1658 status = sock_ioctl_send( handle, event, apc, apc_user, io, fd, u64_to_user_ptr( params->buffers_ptr ),
1659 params->count, u64_to_user_ptr( params->addr_ptr ), params->addr_len,
1660 unix_flags, params->force_async );
1661 if (needs_close) close( fd );
1662 return status;
1665 case IOCTL_AFD_WINE_TRANSMIT:
1667 const struct afd_transmit_params *params = in_buffer;
1669 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1670 return status;
1672 if (in_size < sizeof(*params))
1674 status = STATUS_BUFFER_TOO_SMALL;
1675 break;
1677 status = sock_transmit( handle, event, apc, apc_user, io, fd, params );
1678 if (needs_close) close( fd );
1679 return status;
1682 case IOCTL_AFD_WINE_COMPLETE_ASYNC:
1684 if (in_size != sizeof(NTSTATUS))
1685 return STATUS_BUFFER_TOO_SMALL;
1687 status = *(NTSTATUS *)in_buffer;
1688 complete_async( handle, event, apc, apc_user, io, status, 0 );
1689 return status;
1692 case IOCTL_AFD_WINE_FIONREAD:
1694 int value, ret;
1696 if (out_size < sizeof(int))
1698 status = STATUS_BUFFER_TOO_SMALL;
1699 break;
1702 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1703 return status;
1705 #ifdef linux
1707 socklen_t len = sizeof(value);
1709 /* FIONREAD on a listening socket always fails (see tcp(7)). */
1710 if (!getsockopt( fd, SOL_SOCKET, SO_ACCEPTCONN, &value, &len ) && value)
1712 *(int *)out_buffer = 0;
1713 if (needs_close) close( fd );
1714 complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
1715 return STATUS_SUCCESS;
1718 #endif
1720 if ((ret = ioctl( fd, FIONREAD, &value )) < 0)
1722 status = sock_errno_to_status( errno );
1723 break;
1725 *(int *)out_buffer = value;
1726 if (needs_close) close( fd );
1727 complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
1728 return STATUS_SUCCESS;
1731 case IOCTL_AFD_WINE_SIOCATMARK:
1733 int value, ret;
1734 socklen_t len = sizeof(value);
1736 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1737 return status;
1739 if (out_size < sizeof(int))
1741 status = STATUS_BUFFER_TOO_SMALL;
1742 break;
1745 if (getsockopt( fd, SOL_SOCKET, SO_OOBINLINE, &value, &len ) < 0)
1747 status = sock_errno_to_status( errno );
1748 break;
1751 if (value)
1753 *(int *)out_buffer = TRUE;
1755 else
1757 if ((ret = ioctl( fd, SIOCATMARK, &value )) < 0)
1759 status = sock_errno_to_status( errno );
1760 break;
1762 /* windows is reversed with respect to unix */
1763 *(int *)out_buffer = !value;
1765 if (needs_close) close( fd );
1766 complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
1767 return STATUS_SUCCESS;
1770 case IOCTL_AFD_WINE_GET_INTERFACE_LIST:
1772 #ifdef HAVE_GETIFADDRS
1773 INTERFACE_INFO *info = out_buffer;
1774 struct ifaddrs *ifaddrs, *ifaddr;
1775 unsigned int count = 0;
1776 ULONG ret_size;
1778 if (getifaddrs( &ifaddrs ) < 0)
1780 status = sock_errno_to_status( errno );
1781 break;
1784 for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next)
1786 if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET) ++count;
1789 ret_size = count * sizeof(*info);
1790 if (out_size < ret_size)
1792 freeifaddrs( ifaddrs );
1793 complete_async( handle, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 );
1794 return STATUS_PENDING;
1797 memset( out_buffer, 0, ret_size );
1799 count = 0;
1800 for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next)
1802 in_addr_t addr, mask;
1804 if (!ifaddr->ifa_addr || ifaddr->ifa_addr->sa_family != AF_INET)
1805 continue;
1807 addr = ((const struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr;
1808 mask = ((const struct sockaddr_in *)ifaddr->ifa_netmask)->sin_addr.s_addr;
1810 info[count].iiFlags = 0;
1811 if (ifaddr->ifa_flags & IFF_BROADCAST)
1812 info[count].iiFlags |= WS_IFF_BROADCAST;
1813 if (ifaddr->ifa_flags & IFF_LOOPBACK)
1814 info[count].iiFlags |= WS_IFF_LOOPBACK;
1815 if (ifaddr->ifa_flags & IFF_MULTICAST)
1816 info[count].iiFlags |= WS_IFF_MULTICAST;
1817 #ifdef IFF_POINTTOPOINT
1818 if (ifaddr->ifa_flags & IFF_POINTTOPOINT)
1819 info[count].iiFlags |= WS_IFF_POINTTOPOINT;
1820 #endif
1821 if (ifaddr->ifa_flags & IFF_UP)
1822 info[count].iiFlags |= WS_IFF_UP;
1824 info[count].iiAddress.AddressIn.sin_family = WS_AF_INET;
1825 info[count].iiAddress.AddressIn.sin_port = 0;
1826 info[count].iiAddress.AddressIn.sin_addr.WS_s_addr = addr;
1828 info[count].iiNetmask.AddressIn.sin_family = WS_AF_INET;
1829 info[count].iiNetmask.AddressIn.sin_port = 0;
1830 info[count].iiNetmask.AddressIn.sin_addr.WS_s_addr = mask;
1832 if (ifaddr->ifa_flags & IFF_BROADCAST)
1834 info[count].iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET;
1835 info[count].iiBroadcastAddress.AddressIn.sin_port = 0;
1836 info[count].iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask;
1839 ++count;
1842 freeifaddrs( ifaddrs );
1843 complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, ret_size );
1844 return STATUS_PENDING;
1845 #else
1846 FIXME( "Interface list queries are currently not supported on this platform.\n" );
1847 status = STATUS_NOT_SUPPORTED;
1848 #endif
1849 break;
1852 case IOCTL_AFD_WINE_KEEPALIVE_VALS:
1854 struct tcp_keepalive *k = in_buffer;
1855 int keepalive;
1857 if (!in_buffer || in_size < sizeof(struct tcp_keepalive))
1858 return STATUS_BUFFER_TOO_SMALL;
1859 keepalive = !!k->onoff;
1861 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1862 return status;
1864 if (setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(int) ) < 0)
1866 status = STATUS_INVALID_PARAMETER;
1867 break;
1870 if (keepalive)
1872 #ifdef TCP_KEEPIDLE
1873 int idle = max( 1, (k->keepalivetime + 500) / 1000 );
1875 if (setsockopt( fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(int) ) < 0)
1877 status = STATUS_INVALID_PARAMETER;
1878 break;
1880 #else
1881 FIXME("ignoring keepalive timeout\n");
1882 #endif
1885 if (keepalive)
1887 #ifdef TCP_KEEPINTVL
1888 int interval = max( 1, (k->keepaliveinterval + 500) / 1000 );
1890 if (setsockopt( fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(int) ) < 0)
1891 status = STATUS_INVALID_PARAMETER;
1892 #else
1893 FIXME("ignoring keepalive interval\n");
1894 #endif
1897 if (needs_close) close( fd );
1898 complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
1899 return STATUS_SUCCESS;
1902 case IOCTL_AFD_WINE_GETPEERNAME:
1904 union unix_sockaddr unix_addr;
1905 socklen_t unix_len = sizeof(unix_addr);
1906 int len;
1908 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1909 return status;
1911 if (getpeername( fd, &unix_addr.addr, &unix_len ) < 0)
1913 status = sock_errno_to_status( errno );
1914 break;
1917 len = sockaddr_from_unix( &unix_addr, out_buffer, out_size );
1918 if (out_size < len)
1920 status = STATUS_BUFFER_TOO_SMALL;
1921 break;
1923 io->Information = len;
1924 status = STATUS_SUCCESS;
1925 break;
1928 case IOCTL_AFD_WINE_GET_SO_BROADCAST:
1929 return do_getsockopt( handle, io, SOL_SOCKET, SO_BROADCAST, out_buffer, out_size );
1931 case IOCTL_AFD_WINE_SET_SO_BROADCAST:
1932 return do_setsockopt( handle, io, SOL_SOCKET, SO_BROADCAST, in_buffer, in_size );
1934 case IOCTL_AFD_WINE_GET_SO_KEEPALIVE:
1935 return do_getsockopt( handle, io, SOL_SOCKET, SO_KEEPALIVE, out_buffer, out_size );
1937 case IOCTL_AFD_WINE_SET_SO_KEEPALIVE:
1938 return do_setsockopt( handle, io, SOL_SOCKET, SO_KEEPALIVE, in_buffer, in_size );
1940 case IOCTL_AFD_WINE_GET_SO_LINGER:
1942 struct WS_linger *ws_linger = out_buffer;
1943 struct linger unix_linger;
1944 socklen_t len = sizeof(unix_linger);
1945 int ret;
1947 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1948 return status;
1950 ret = getsockopt( fd, SOL_SOCKET, SO_LINGER, &unix_linger, &len );
1951 if (!ret)
1953 ws_linger->l_onoff = unix_linger.l_onoff;
1954 ws_linger->l_linger = unix_linger.l_linger;
1955 io->Information = sizeof(*ws_linger);
1958 status = ret ? sock_errno_to_status( errno ) : STATUS_SUCCESS;
1959 break;
1962 case IOCTL_AFD_WINE_SET_SO_LINGER:
1964 const struct WS_linger *ws_linger = in_buffer;
1965 struct linger unix_linger;
1967 unix_linger.l_onoff = ws_linger->l_onoff;
1968 unix_linger.l_linger = ws_linger->l_linger;
1970 return do_setsockopt( handle, io, SOL_SOCKET, SO_LINGER, &unix_linger, sizeof(unix_linger) );
1973 case IOCTL_AFD_WINE_GET_SO_OOBINLINE:
1974 return do_getsockopt( handle, io, SOL_SOCKET, SO_OOBINLINE, out_buffer, out_size );
1976 case IOCTL_AFD_WINE_SET_SO_OOBINLINE:
1977 return do_setsockopt( handle, io, SOL_SOCKET, SO_OOBINLINE, in_buffer, in_size );
1979 case IOCTL_AFD_WINE_SET_IP_ADD_MEMBERSHIP:
1980 return do_setsockopt( handle, io, IPPROTO_IP, IP_ADD_MEMBERSHIP, in_buffer, in_size );
1982 case IOCTL_AFD_WINE_SET_IP_ADD_SOURCE_MEMBERSHIP:
1983 return do_setsockopt( handle, io, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, in_buffer, in_size );
1985 case IOCTL_AFD_WINE_SET_IP_BLOCK_SOURCE:
1986 return do_setsockopt( handle, io, IPPROTO_IP, IP_BLOCK_SOURCE, in_buffer, in_size );
1988 case IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT:
1990 socklen_t len = out_size;
1991 int ret;
1993 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1994 return status;
1996 #ifdef IP_DONTFRAG
1997 ret = getsockopt( fd, IPPROTO_IP, IP_DONTFRAG, out_buffer, &len );
1998 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
2000 int value;
2002 len = sizeof(value);
2003 ret = getsockopt( fd, IPPROTO_IP, IP_MTU_DISCOVER, &value, &len );
2004 if (!ret) *(DWORD *)out_buffer = (value != IP_PMTUDISC_DONT);
2006 #else
2008 static int once;
2010 if (!once++)
2011 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
2012 ret = 0; /* fake success */
2014 #endif
2015 if (ret)
2017 status = sock_errno_to_status( errno );
2019 else
2021 io->Information = len;
2022 status = STATUS_SUCCESS;
2024 break;
2027 case IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT:
2028 #ifdef IP_DONTFRAG
2029 return do_setsockopt( handle, io, IPPROTO_IP, IP_DONTFRAG, in_buffer, in_size );
2030 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && defined(IP_PMTUDISC_DONT)
2032 int value = *(DWORD *)in_buffer ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
2034 return do_setsockopt( handle, io, IPPROTO_IP, IP_MTU_DISCOVER, &value, sizeof(value) );
2036 #else
2038 static int once;
2040 if (!once++)
2041 FIXME( "IP_DONTFRAGMENT is not supported on this platform\n" );
2042 status = STATUS_SUCCESS; /* fake success */
2043 break;
2045 #endif
2047 case IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP:
2048 return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_MEMBERSHIP, in_buffer, in_size );
2050 case IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP:
2051 return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, in_buffer, in_size );
2053 #ifdef IP_HDRINCL
2054 case IOCTL_AFD_WINE_GET_IP_HDRINCL:
2055 if (get_sock_type( handle ) != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2056 return do_getsockopt( handle, io, IPPROTO_IP, IP_HDRINCL, out_buffer, out_size );
2058 case IOCTL_AFD_WINE_SET_IP_HDRINCL:
2059 if (get_sock_type( handle ) != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2060 return do_setsockopt( handle, io, IPPROTO_IP, IP_HDRINCL, in_buffer, in_size );
2061 #endif
2063 case IOCTL_AFD_WINE_GET_IP_MULTICAST_IF:
2065 int sock_type = get_sock_type( handle );
2066 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2067 return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_IF, out_buffer, out_size );
2070 case IOCTL_AFD_WINE_SET_IP_MULTICAST_IF:
2072 int sock_type = get_sock_type( handle );
2073 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2074 return do_setsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_IF, in_buffer, in_size );
2077 case IOCTL_AFD_WINE_GET_IP_MULTICAST_LOOP:
2079 int sock_type = get_sock_type( handle );
2080 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2081 return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_LOOP, out_buffer, out_size );
2084 case IOCTL_AFD_WINE_SET_IP_MULTICAST_LOOP:
2086 int sock_type = get_sock_type( handle );
2087 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2088 return do_setsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_LOOP, in_buffer, in_size );
2091 case IOCTL_AFD_WINE_GET_IP_MULTICAST_TTL:
2093 int sock_type = get_sock_type( handle );
2094 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2095 return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_TTL, out_buffer, out_size );
2098 case IOCTL_AFD_WINE_SET_IP_MULTICAST_TTL:
2100 int sock_type = get_sock_type( handle );
2101 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2102 return do_setsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_TTL, in_buffer, in_size );
2105 case IOCTL_AFD_WINE_GET_IP_OPTIONS:
2106 return do_getsockopt( handle, io, IPPROTO_IP, IP_OPTIONS, out_buffer, out_size );
2108 case IOCTL_AFD_WINE_SET_IP_OPTIONS:
2109 return do_setsockopt( handle, io, IPPROTO_IP, IP_OPTIONS, in_buffer, in_size );
2111 #ifdef IP_PKTINFO
2112 case IOCTL_AFD_WINE_GET_IP_PKTINFO:
2114 int sock_type = get_sock_type( handle );
2115 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2116 return do_getsockopt( handle, io, IPPROTO_IP, IP_PKTINFO, out_buffer, out_size );
2119 case IOCTL_AFD_WINE_SET_IP_PKTINFO:
2121 int sock_type = get_sock_type( handle );
2122 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2123 return do_setsockopt( handle, io, IPPROTO_IP, IP_PKTINFO, in_buffer, in_size );
2125 #elif defined(IP_RECVDSTADDR)
2126 case IOCTL_AFD_WINE_GET_IP_PKTINFO:
2128 int sock_type = get_sock_type( handle );
2129 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2130 return do_getsockopt( handle, io, IPPROTO_IP, IP_RECVDSTADDR, out_buffer, out_size );
2133 case IOCTL_AFD_WINE_SET_IP_PKTINFO:
2135 int sock_type = get_sock_type( handle );
2136 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2137 return do_setsockopt( handle, io, IPPROTO_IP, IP_RECVDSTADDR, in_buffer, in_size );
2139 #endif
2141 #ifdef IP_RECVTOS
2142 case IOCTL_AFD_WINE_GET_IP_RECVTOS:
2144 int sock_type = get_sock_type( handle );
2145 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2146 return do_getsockopt( handle, io, IPPROTO_IP, IP_RECVTOS, out_buffer, out_size );
2149 case IOCTL_AFD_WINE_SET_IP_RECVTOS:
2151 int sock_type = get_sock_type( handle );
2152 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2153 return do_setsockopt( handle, io, IPPROTO_IP, IP_RECVTOS, in_buffer, in_size );
2155 #endif
2157 #ifdef IP_RECVTTL
2158 case IOCTL_AFD_WINE_GET_IP_RECVTTL:
2160 int sock_type = get_sock_type( handle );
2161 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2162 return do_getsockopt( handle, io, IPPROTO_IP, IP_RECVTTL, out_buffer, out_size );
2165 case IOCTL_AFD_WINE_SET_IP_RECVTTL:
2167 int sock_type = get_sock_type( handle );
2168 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2169 return do_setsockopt( handle, io, IPPROTO_IP, IP_RECVTTL, in_buffer, in_size );
2171 #endif
2173 case IOCTL_AFD_WINE_GET_IP_TOS:
2174 return do_getsockopt( handle, io, IPPROTO_IP, IP_TOS, out_buffer, out_size );
2176 case IOCTL_AFD_WINE_SET_IP_TOS:
2177 return do_setsockopt( handle, io, IPPROTO_IP, IP_TOS, in_buffer, in_size );
2179 case IOCTL_AFD_WINE_GET_IP_TTL:
2180 return do_getsockopt( handle, io, IPPROTO_IP, IP_TTL, out_buffer, out_size );
2182 case IOCTL_AFD_WINE_SET_IP_TTL:
2183 return do_setsockopt( handle, io, IPPROTO_IP, IP_TTL, in_buffer, in_size );
2185 case IOCTL_AFD_WINE_SET_IP_UNBLOCK_SOURCE:
2186 return do_setsockopt( handle, io, IPPROTO_IP, IP_UNBLOCK_SOURCE, in_buffer, in_size );
2188 #ifdef IP_UNICAST_IF
2189 case IOCTL_AFD_WINE_GET_IP_UNICAST_IF:
2190 return do_getsockopt( handle, io, IPPROTO_IP, IP_UNICAST_IF, out_buffer, out_size );
2192 case IOCTL_AFD_WINE_SET_IP_UNICAST_IF:
2193 return do_setsockopt( handle, io, IPPROTO_IP, IP_UNICAST_IF, in_buffer, in_size );
2194 #endif
2196 #ifdef IPV6_ADD_MEMBERSHIP
2197 case IOCTL_AFD_WINE_SET_IPV6_ADD_MEMBERSHIP:
2198 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, in_buffer, in_size );
2199 #endif
2201 case IOCTL_AFD_WINE_GET_IPV6_DONTFRAG:
2203 socklen_t len = out_size;
2204 int ret;
2206 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2207 return status;
2209 #ifdef IPV6_DONTFRAG
2210 ret = getsockopt( fd, IPPROTO_IPV6, IPV6_DONTFRAG, out_buffer, &len );
2211 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
2213 int value;
2215 len = sizeof(value);
2216 ret = getsockopt( fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &value, &len );
2217 if (!ret) *(DWORD *)out_buffer = (value != IPV6_PMTUDISC_DONT);
2219 #else
2221 static int once;
2223 if (!once++)
2224 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
2225 ret = 0; /* fake success */
2227 #endif
2228 if (ret)
2230 status = sock_errno_to_status( errno );
2232 else
2234 io->Information = len;
2235 status = STATUS_SUCCESS;
2237 break;
2240 case IOCTL_AFD_WINE_SET_IPV6_DONTFRAG:
2241 #ifdef IPV6_DONTFRAG
2242 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_DONTFRAG, in_buffer, in_size );
2243 #elif defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && defined(IPV6_PMTUDISC_DONT)
2245 int value = *(DWORD *)in_buffer ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_DONT;
2247 return do_setsockopt( handle, io, IPPROTO_IP, IPV6_MTU_DISCOVER, &value, sizeof(value) );
2249 #else
2251 static int once;
2253 if (!once++)
2254 FIXME( "IPV6_DONTFRAGMENT is not supported on this platform\n" );
2255 return STATUS_SUCCESS; /* fake success */
2257 #endif
2259 #ifdef IPV6_DROP_MEMBERSHIP
2260 case IOCTL_AFD_WINE_SET_IPV6_DROP_MEMBERSHIP:
2261 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, in_buffer, in_size );
2262 #endif
2264 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS:
2266 int sock_type = get_sock_type( handle );
2267 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2268 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, out_buffer, out_size );
2271 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS:
2273 int sock_type = get_sock_type( handle );
2274 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2275 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, in_buffer, in_size );
2278 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_IF:
2280 int sock_type = get_sock_type( handle );
2281 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2282 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_IF, out_buffer, out_size );
2285 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF:
2287 int sock_type = get_sock_type( handle );
2288 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2289 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_IF, in_buffer, in_size );
2292 case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP:
2294 int sock_type = get_sock_type( handle );
2295 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2296 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, out_buffer, out_size );
2299 case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP:
2301 int sock_type = get_sock_type( handle );
2302 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2303 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, in_buffer, in_size );
2306 #ifdef IPV6_RECVHOPLIMIT
2307 case IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT:
2309 int sock_type = get_sock_type( handle );
2310 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2311 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, out_buffer, out_size );
2314 case IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT:
2316 int sock_type = get_sock_type( handle );
2317 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2318 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, in_buffer, in_size );
2320 #endif
2322 #ifdef IPV6_RECVPKTINFO
2323 case IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO:
2325 int sock_type = get_sock_type( handle );
2326 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2327 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVPKTINFO, out_buffer, out_size );
2330 case IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO:
2332 int sock_type = get_sock_type( handle );
2333 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2334 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVPKTINFO, in_buffer, in_size );
2336 #endif
2338 #ifdef IPV6_RECVTCLASS
2339 case IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS:
2341 int sock_type = get_sock_type( handle );
2342 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2343 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, out_buffer, out_size );
2346 case IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS:
2348 int sock_type = get_sock_type( handle );
2349 if (sock_type != SOCK_DGRAM && sock_type != SOCK_RAW) return STATUS_INVALID_PARAMETER;
2350 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, in_buffer, in_size );
2352 #endif
2354 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS:
2355 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, out_buffer, out_size );
2357 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS:
2358 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, in_buffer, in_size );
2360 #ifdef IPV6_UNICAST_IF
2361 case IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF:
2362 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, out_buffer, out_size );
2364 case IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF:
2365 return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, in_buffer, in_size );
2366 #endif
2368 case IOCTL_AFD_WINE_GET_IPV6_V6ONLY:
2369 return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_V6ONLY, out_buffer, out_size );
2371 case IOCTL_AFD_WINE_SET_IPV6_V6ONLY:
2373 union unix_sockaddr addr;
2374 socklen_t len = sizeof(addr);
2375 int ret;
2377 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2378 return status;
2380 if (!getsockname( fd, &addr.addr, &len ) && addr.addr.sa_family == AF_INET && !addr.in.sin_port)
2382 /* changing IPV6_V6ONLY succeeds on an unbound IPv4 socket */
2383 WARN( "ignoring IPV6_V6ONLY on an unbound IPv4 socket\n" );
2384 status = STATUS_SUCCESS;
2385 break;
2388 ret = setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, in_buffer, in_size );
2389 status = ret ? sock_errno_to_status( errno ) : STATUS_SUCCESS;
2390 break;
2393 #ifdef SOL_IPX
2394 case IOCTL_AFD_WINE_GET_IPX_PTYPE:
2395 return do_getsockopt( handle, io, SOL_IPX, IPX_TYPE, out_buffer, out_size );
2397 case IOCTL_AFD_WINE_SET_IPX_PTYPE:
2398 return do_setsockopt( handle, io, SOL_IPX, IPX_TYPE, in_buffer, in_size );
2399 #elif defined(SO_DEFAULT_HEADERS)
2400 case IOCTL_AFD_WINE_GET_IPX_PTYPE:
2402 struct ipx value;
2403 socklen_t len = sizeof(value);
2404 int ret;
2406 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2407 return status;
2409 ret = getsockopt( fd, 0, SO_DEFAULT_HEADERS, &value, &len );
2410 if (ret)
2412 status = sock_errno_to_status( errno );
2414 else
2416 *(DWORD *)out_buffer = value.ipx_pt;
2417 status = STATUS_SUCCESS;
2419 break;
2422 case IOCTL_AFD_WINE_SET_IPX_PTYPE:
2424 struct ipx value = {0};
2426 /* FIXME: should we retrieve SO_DEFAULT_HEADERS first and modify it? */
2427 value.ipx_pt = *(DWORD *)in_buffer;
2428 return do_setsockopt( handle, io, 0, SO_DEFAULT_HEADERS, &value, sizeof(value) );
2430 #endif
2432 #ifdef HAS_IRDA
2433 #define MAX_IRDA_DEVICES 10
2434 case IOCTL_AFD_WINE_GET_IRLMP_ENUMDEVICES:
2436 char buffer[offsetof( struct irda_device_list, dev[MAX_IRDA_DEVICES] )];
2437 struct irda_device_list *unix_list = (struct irda_device_list *)buffer;
2438 socklen_t len = sizeof(buffer);
2439 DEVICELIST *ws_list = out_buffer;
2440 int fd, needs_close = FALSE;
2441 unsigned int i;
2442 int ret;
2444 if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2445 return status;
2447 ret = getsockopt( fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buffer, &len );
2448 if (needs_close) close( fd );
2449 if (ret) return sock_errno_to_status( errno );
2451 io->Information = offsetof( DEVICELIST, Device[unix_list->len] );
2452 if (out_size < io->Information)
2453 return STATUS_BUFFER_TOO_SMALL;
2455 TRACE( "IRLMP_ENUMDEVICES: got %u devices:\n", unix_list->len );
2456 ws_list->numDevice = unix_list->len;
2457 for (i = 0; i < unix_list->len; ++i)
2459 const struct irda_device_info *unix_dev = &unix_list->dev[i];
2460 IRDA_DEVICE_INFO *ws_dev = &ws_list->Device[i];
2462 TRACE( "saddr %#08x, daddr %#08x, info %s, hints 0x%02x%02x\n",
2463 unix_dev->saddr, unix_dev->daddr, unix_dev->info, unix_dev->hints[0], unix_dev->hints[1] );
2464 memcpy( ws_dev->irdaDeviceID, &unix_dev->daddr, sizeof(unix_dev->daddr) );
2465 memcpy( ws_dev->irdaDeviceName, unix_dev->info, sizeof(unix_dev->info) );
2466 ws_dev->irdaDeviceHints1 = unix_dev->hints[0];
2467 ws_dev->irdaDeviceHints2 = unix_dev->hints[1];
2468 ws_dev->irdaCharSet = unix_dev->charset;
2470 status = STATUS_SUCCESS;
2471 break;
2473 #endif
2475 case IOCTL_AFD_WINE_GET_TCP_NODELAY:
2476 return do_getsockopt( handle, io, IPPROTO_TCP, TCP_NODELAY, out_buffer, out_size );
2478 case IOCTL_AFD_WINE_SET_TCP_NODELAY:
2479 return do_setsockopt( handle, io, IPPROTO_TCP, TCP_NODELAY, in_buffer, in_size );
2481 default:
2483 if ((code >> 16) == FILE_DEVICE_NETWORK)
2485 /* Wine-internal ioctl */
2486 status = STATUS_BAD_DEVICE_TYPE;
2488 else
2490 FIXME( "Unknown ioctl %#x (device %#x, access %#x, function %#x, method %#x)\n",
2491 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3 );
2492 status = STATUS_INVALID_DEVICE_REQUEST;
2494 break;
2498 if (needs_close) close( fd );
2500 if (status != STATUS_PENDING && !NT_ERROR(status)) io->Status = status;
2502 return status;