[socket] Add EPROTOTYPE error case (#4391)
[mono.git] / mono / metadata / w32socket-unix.c
1 /*
2  * w32socket-unix.c: Unix specific socket code.
3  *
4  * Copyright 2016 Microsoft
5  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
6  */
7
8 #include <config.h>
9 #include <glib.h>
10
11 #include <pthread.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <sys/socket.h>
15 #ifdef HAVE_SYS_IOCTL_H
16 #include <sys/ioctl.h>
17 #endif
18 #include <netinet/in.h>
19 #include <netinet/tcp.h>
20 #ifdef HAVE_NETDB_H
21 #include <netdb.h>
22 #endif
23 #include <arpa/inet.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #ifdef HAVE_SYS_UIO_H
31 #include <sys/uio.h>
32 #endif
33 #ifdef HAVE_SYS_IOCTL_H
34 #include <sys/ioctl.h>
35 #endif
36 #ifdef HAVE_SYS_FILIO_H
37 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
38 #endif
39 #ifdef HAVE_SYS_SOCKIO_H
40 #include <sys/sockio.h>    /* defines SIOCATMARK */
41 #endif
42 #ifndef HAVE_MSG_NOSIGNAL
43 #include <signal.h>
44 #endif
45 #ifdef HAVE_SYS_SENDFILE_H
46 #include <sys/sendfile.h>
47 #endif
48 #include <sys/stat.h>
49
50 #include "w32socket.h"
51 #include "w32socket-internals.h"
52 #include "w32error.h"
53 #include "w32handle.h"
54 #include "utils/mono-logger-internals.h"
55 #include "utils/mono-poll.h"
56
57 typedef struct {
58         int domain;
59         int type;
60         int protocol;
61         int saved_error;
62         int still_readable;
63 } MonoW32HandleSocket;
64
65 static guint32 in_cleanup = 0;
66
67 static void
68 socket_close (gpointer handle, gpointer data)
69 {
70         int ret;
71         MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data;
72         MonoThreadInfo *info = mono_thread_info_current ();
73
74         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle);
75
76         /* Shutdown the socket for reading, to interrupt any potential
77          * receives that may be blocking for data.  See bug 75705. */
78         shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
79
80         do {
81                 ret = close (GPOINTER_TO_UINT(handle));
82         } while (ret == -1 && errno == EINTR &&
83                  !mono_thread_info_is_interrupt_state (info));
84
85         if (ret == -1) {
86                 gint errnum = errno;
87                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno));
88                 if (!in_cleanup)
89                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
90         }
91
92         if (!in_cleanup)
93                 socket_handle->saved_error = 0;
94 }
95
96 static void
97 socket_details (gpointer data)
98 {
99         /* FIXME: do something */
100 }
101
102 static const gchar*
103 socket_typename (void)
104 {
105         return "Socket";
106 }
107
108 static gsize
109 socket_typesize (void)
110 {
111         return sizeof (MonoW32HandleSocket);
112 }
113
114 static MonoW32HandleOps ops = {
115         socket_close,    /* close */
116         NULL,            /* signal */
117         NULL,            /* own */
118         NULL,            /* is_owned */
119         NULL,            /* special_wait */
120         NULL,            /* prewait */
121         socket_details,  /* details */
122         socket_typename, /* typename */
123         socket_typesize, /* typesize */
124 };
125
126 void
127 mono_w32socket_initialize (void)
128 {
129         mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &ops);
130 }
131
132 static gboolean
133 cleanup_close (gpointer handle, gpointer data, gpointer user_data)
134 {
135         if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET)
136                 mono_w32handle_force_close (handle, data);
137
138         return FALSE;
139 }
140
141 void
142 mono_w32socket_cleanup (void)
143 {
144         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
145
146         in_cleanup = 1;
147         mono_w32handle_foreach (cleanup_close, NULL);
148         in_cleanup = 0;
149 }
150
151 SOCKET
152 mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
153 {
154         gpointer handle;
155         gpointer new_handle;
156         MonoW32HandleSocket *socket_handle;
157         MonoW32HandleSocket new_socket_handle;
158         SOCKET new_fd;
159         MonoThreadInfo *info;
160
161         if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
162                 mono_w32socket_set_last_error (WSAEFAULT);
163                 return INVALID_SOCKET;
164         }
165
166         handle = GUINT_TO_POINTER (sock);
167         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
168                 mono_w32socket_set_last_error (WSAENOTSOCK);
169                 return INVALID_SOCKET;
170         }
171
172         info = mono_thread_info_current ();
173
174         do {
175                 new_fd = accept (sock, addr, addrlen);
176         } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
177
178         if (new_fd == -1) {
179                 gint errnum = errno;
180                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno));
181                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
182                 return INVALID_SOCKET;
183         }
184
185         if (new_fd >= mono_w32handle_fd_reserve) {
186                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
187
188                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
189
190                 close (new_fd);
191
192                 return INVALID_SOCKET;
193         }
194
195         new_socket_handle.domain = socket_handle->domain;
196         new_socket_handle.type = socket_handle->type;
197         new_socket_handle.protocol = socket_handle->protocol;
198         new_socket_handle.still_readable = 1;
199
200         new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd,
201                                           &new_socket_handle);
202         if(new_handle == INVALID_HANDLE_VALUE) {
203                 g_warning ("%s: error creating socket handle", __func__);
204                 mono_w32socket_set_last_error (ERROR_GEN_FAILURE);
205                 return INVALID_SOCKET;
206         }
207
208         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
209                    __func__, new_handle);
210
211         return new_fd;
212 }
213
214 int
215 mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
216 {
217         gpointer handle;
218         MonoW32HandleSocket *socket_handle;
219
220         handle = GUINT_TO_POINTER (sock);
221         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
222                 mono_w32socket_set_last_error (WSAENOTSOCK);
223                 return SOCKET_ERROR;
224         }
225
226         if (connect (sock, addr, addrlen) == -1) {
227                 MonoThreadInfo *info;
228                 mono_pollfd fds;
229                 gint errnum, so_error;
230                 socklen_t len;
231
232                 errnum = errno;
233
234                 if (errno != EINTR) {
235                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
236                                    g_strerror (errnum));
237
238                         errnum = mono_w32socket_convert_error (errnum);
239                         if (errnum == WSAEINPROGRESS)
240                                 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
241
242                         mono_w32socket_set_last_error (errnum);
243
244                         /*
245                          * On solaris x86 getsockopt (SO_ERROR) is not set after
246                          * connect () fails so we need to save this error.
247                          *
248                          * But don't do this for EWOULDBLOCK (bug 317315)
249                          */
250                         if (errnum != WSAEWOULDBLOCK) {
251                                 /* ECONNRESET means the socket was closed by another thread */
252                                 /* Async close on mac raises ECONNABORTED. */
253                                 socket_handle->saved_error = errnum;
254                         }
255                         return SOCKET_ERROR;
256                 }
257
258                 info = mono_thread_info_current ();
259
260                 fds.fd = sock;
261                 fds.events = MONO_POLLOUT;
262                 while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) {
263                         if (errno != EINTR) {
264                                 gint errnum = errno;
265                                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno));
266                                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
267                                 return SOCKET_ERROR;
268                         }
269                 }
270
271                 len = sizeof(so_error);
272                 if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
273                         gint errnum = errno;
274                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
275                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
276                         return SOCKET_ERROR;
277                 }
278
279                 if (so_error != 0) {
280                         gint errnum = mono_w32socket_convert_error (so_error);
281
282                         /* Need to save this socket error */
283                         socket_handle->saved_error = errnum;
284
285                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
286                                    __func__, g_strerror (so_error));
287
288                         mono_w32socket_set_last_error (errnum);
289                         return SOCKET_ERROR;
290                 }
291         }
292
293         return 0;
294 }
295
296 int
297 mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
298 {
299         return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking);
300 }
301
302 int
303 mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
304 {
305         gpointer handle;
306         MonoW32HandleSocket *socket_handle;
307         int ret;
308         MonoThreadInfo *info;
309
310         handle = GUINT_TO_POINTER (sock);
311         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
312                 mono_w32socket_set_last_error (WSAENOTSOCK);
313                 return SOCKET_ERROR;
314         }
315
316         info = mono_thread_info_current ();
317
318         do {
319                 ret = recvfrom (sock, buf, len, flags, from, fromlen);
320         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
321
322         if (ret == 0 && len > 0) {
323                 /* According to the Linux man page, recvfrom only
324                  * returns 0 when the socket has been shut down
325                  * cleanly.  Turn this into an EINTR to simulate win32
326                  * behaviour of returning EINTR when a socket is
327                  * closed while the recvfrom is blocking (we use a
328                  * shutdown() in socket_close() to trigger this.) See
329                  * bug 75705.
330                  */
331                 /* Distinguish between the socket being shut down at
332                  * the local or remote ends, and reads that request 0
333                  * bytes to be read
334                  */
335
336                 /* If this returns FALSE, it means the socket has been
337                  * closed locally.  If it returns TRUE, but
338                  * still_readable != 1 then shutdown
339                  * (SHUT_RD|SHUT_RDWR) has been called locally.
340                  */
341                 if (socket_handle->still_readable != 1) {
342                         ret = -1;
343                         errno = EINTR;
344                 }
345         }
346
347         if (ret == -1) {
348                 gint errnum = errno;
349                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno));
350                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
351                 return SOCKET_ERROR;
352         }
353         return ret;
354 }
355
356 static void
357 wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr)
358 {
359         guint32 i;
360
361         memset (hdr, 0, sizeof (struct msghdr));
362         hdr->msg_iovlen = count;
363         hdr->msg_iov = g_new0 (struct iovec, count);
364         for (i = 0; i < count; i++) {
365                 hdr->msg_iov [i].iov_base = buffers [i].buf;
366                 hdr->msg_iov [i].iov_len  = buffers [i].len;
367         }
368 }
369
370 static void
371 msghdr_iov_free (struct msghdr *hdr)
372 {
373         g_free (hdr->msg_iov);
374 }
375
376 int
377 mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
378 {
379         MonoW32HandleSocket *socket_handle;
380         MonoThreadInfo *info;
381         gpointer handle;
382         gint ret;
383         struct msghdr hdr;
384
385         g_assert (overlapped == NULL);
386         g_assert (complete == NULL);
387
388         handle = GUINT_TO_POINTER (sock);
389         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
390                 mono_w32socket_set_last_error (WSAENOTSOCK);
391                 return SOCKET_ERROR;
392         }
393
394         info = mono_thread_info_current ();
395
396         wsabuf_to_msghdr (buffers, count, &hdr);
397
398         do {
399                 ret = recvmsg (sock, &hdr, *flags);
400         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
401
402         msghdr_iov_free (&hdr);
403
404         if (ret == 0) {
405                 /* see mono_w32socket_recvfrom */
406                 if (socket_handle->still_readable != 1) {
407                         ret = -1;
408                         errno = EINTR;
409                 }
410         }
411
412         if (ret == -1) {
413                 gint errnum = errno;
414                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno));
415                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
416                 return SOCKET_ERROR;
417         }
418
419         *received = ret;
420         *flags = hdr.msg_flags;
421
422         return 0;
423 }
424
425 int
426 mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
427 {
428         gpointer handle;
429         int ret;
430         MonoThreadInfo *info;
431
432         handle = GUINT_TO_POINTER (sock);
433         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
434                 mono_w32socket_set_last_error (WSAENOTSOCK);
435                 return SOCKET_ERROR;
436         }
437
438         info = mono_thread_info_current ();
439
440         do {
441                 ret = send (sock, buf, len, flags);
442         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
443
444         if (ret == -1) {
445                 gint errnum = errno;
446                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
447
448 #ifdef O_NONBLOCK
449                 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
450                  * a blocking socket. See bug #599488 */
451                 if (errnum == EAGAIN) {
452                         ret = fcntl (sock, F_GETFL, 0);
453                         if (ret != -1 && (ret & O_NONBLOCK) == 0)
454                                 errnum = ETIMEDOUT;
455                 }
456 #endif /* O_NONBLOCK */
457                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
458                 return SOCKET_ERROR;
459         }
460         return ret;
461 }
462
463 int
464 mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
465 {
466         gpointer handle;
467         int ret;
468         MonoThreadInfo *info;
469
470         handle = GUINT_TO_POINTER (sock);
471         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
472                 mono_w32socket_set_last_error (WSAENOTSOCK);
473                 return SOCKET_ERROR;
474         }
475
476         info = mono_thread_info_current ();
477
478         do {
479                 ret = sendto (sock, buf, len, flags, to, tolen);
480         } while (ret == -1 && errno == EINTR &&  !mono_thread_info_is_interrupt_state (info));
481
482         if (ret == -1) {
483                 gint errnum = errno;
484                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
485                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
486                 return SOCKET_ERROR;
487         }
488         return ret;
489 }
490
491 int
492 mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
493 {
494         struct msghdr hdr;
495         MonoThreadInfo *info;
496         gpointer handle;
497         gint ret;
498
499         g_assert (overlapped == NULL);
500         g_assert (complete == NULL);
501
502         handle = GUINT_TO_POINTER (sock);
503         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
504                 mono_w32socket_set_last_error (WSAENOTSOCK);
505                 return SOCKET_ERROR;
506         }
507
508         info = mono_thread_info_current ();
509
510         wsabuf_to_msghdr (buffers, count, &hdr);
511
512         do {
513                 ret = sendmsg (sock, &hdr, flags);
514         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
515
516         msghdr_iov_free (&hdr);
517
518         if (ret == -1) {
519                 gint errnum = errno;
520                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
521                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
522                 return SOCKET_ERROR;
523         }
524
525         *sent = ret;
526         return 0;
527 }
528
529 #define SF_BUFFER_SIZE  16384
530
531 BOOL
532 mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
533 {
534         MonoThreadInfo *info;
535         gpointer handle;
536         gint file;
537         gssize ret;
538 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
539         struct stat statbuf;
540 #else
541         gchar *buffer;
542 #endif
543
544         handle = GUINT_TO_POINTER (sock);
545         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
546                 mono_w32socket_set_last_error (WSAENOTSOCK);
547                 return FALSE;
548         }
549
550         /* Write the header */
551         if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
552                 ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE);
553                 if (ret == SOCKET_ERROR)
554                         return FALSE;
555         }
556
557         info = mono_thread_info_current ();
558
559         file = GPOINTER_TO_INT (file_handle);
560
561 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
562         ret = fstat (file, &statbuf);
563         if (ret == -1) {
564                 gint errnum = errno;
565                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
566                 return SOCKET_ERROR;
567         }
568
569         do {
570 #ifdef __linux__
571                 ret = sendfile (sock, file, NULL, statbuf.st_size);
572 #elif defined(DARWIN)
573                 /* TODO: header/tail could be sent in the 5th argument */
574                 /* TODO: Might not send the entire file for non-blocking sockets */
575                 ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0);
576 #endif
577         } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
578 #else
579         buffer = g_malloc (SF_BUFFER_SIZE);
580
581         do {
582                 do {
583                         ret = read (file, buffer, SF_BUFFER_SIZE);
584                 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
585
586                 if (ret == -1 || ret == 0)
587                         break;
588
589                 do {
590                         ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */
591                 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
592         } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
593
594         g_free (buffer);
595 #endif
596
597         if (ret == -1) {
598                 gint errnum = errno;
599                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
600                 return FALSE;
601         }
602
603         /* Write the tail */
604         if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
605                 ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE);
606                 if (ret == SOCKET_ERROR)
607                         return FALSE;
608         }
609
610         if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
611                 mono_w32handle_close (handle);
612
613         return TRUE;
614 }
615
616 SOCKET
617 mono_w32socket_socket (int domain, int type, int protocol)
618 {
619         MonoW32HandleSocket socket_handle = {0};
620         gpointer handle;
621         SOCKET sock;
622
623         socket_handle.domain = domain;
624         socket_handle.type = type;
625         socket_handle.protocol = protocol;
626         socket_handle.still_readable = 1;
627
628         sock = socket (domain, type, protocol);
629         if (sock == -1 && domain == AF_INET && type == SOCK_RAW &&
630             protocol == 0) {
631                 /* Retry with protocol == 4 (see bug #54565) */
632                 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
633                 socket_handle.protocol = 4;
634                 sock = socket (AF_INET, SOCK_RAW, 4);
635         }
636
637         if (sock == -1) {
638                 gint errnum = errno;
639                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno));
640                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
641                 return INVALID_SOCKET;
642         }
643
644         if (sock >= mono_w32handle_fd_reserve) {
645                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
646                            __func__, sock, mono_w32handle_fd_reserve);
647
648                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
649                 close (sock);
650
651                 return INVALID_SOCKET;
652         }
653
654         /* .net seems to set this by default for SOCK_STREAM, not for
655          * SOCK_DGRAM (see bug #36322)
656          * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
657          *
658          * It seems winsock has a rather different idea of what
659          * SO_REUSEADDR means.  If it's set, then a new socket can be
660          * bound over an existing listening socket.  There's a new
661          * windows-specific option called SO_EXCLUSIVEADDRUSE but
662          * using that means the socket MUST be closed properly, or a
663          * denial of service can occur.  Luckily for us, winsock
664          * behaves as though any other system would when SO_REUSEADDR
665          * is true, so we don't need to do anything else here.  See
666          * bug 53992.
667          * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
668          */
669         {
670                 int ret, true_ = 1;
671
672                 ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
673                 if (ret == -1) {
674                         close (sock);
675                         gint errnum = errno;
676                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
677                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
678                         return INVALID_SOCKET;
679                 }
680         }
681
682
683         handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, sock, &socket_handle);
684         if (handle == INVALID_HANDLE_VALUE) {
685                 g_warning ("%s: error creating socket handle", __func__);
686                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
687                 close (sock);
688                 return INVALID_SOCKET;
689         }
690
691         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle);
692
693         return sock;
694 }
695
696 gint
697 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
698 {
699         gpointer handle;
700         int ret;
701
702         handle = GUINT_TO_POINTER (sock);
703         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
704                 mono_w32socket_set_last_error (WSAENOTSOCK);
705                 return SOCKET_ERROR;
706         }
707
708         ret = bind (sock, addr, addrlen);
709         if (ret == -1) {
710                 gint errnum = errno;
711                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno));
712                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
713                 return SOCKET_ERROR;
714         }
715
716         return 0;
717 }
718
719 gint
720 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
721 {
722         gpointer handle;
723         gint ret;
724
725         handle = GUINT_TO_POINTER (sock);
726         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
727                 mono_w32socket_set_last_error (WSAENOTSOCK);
728                 return SOCKET_ERROR;
729         }
730
731         ret = getpeername (sock, name, namelen);
732         if (ret == -1) {
733                 gint errnum = errno;
734                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno));
735                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
736                 return SOCKET_ERROR;
737         }
738
739         return 0;
740 }
741
742 gint
743 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
744 {
745         gpointer handle;
746         gint ret;
747
748         handle = GUINT_TO_POINTER (sock);
749         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
750                 mono_w32socket_set_last_error (WSAENOTSOCK);
751                 return SOCKET_ERROR;
752         }
753
754         ret = getsockname (sock, name, namelen);
755         if (ret == -1) {
756                 gint errnum = errno;
757                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
758                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
759                 return SOCKET_ERROR;
760         }
761
762         return 0;
763 }
764
765 gint
766 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
767 {
768         gpointer handle;
769         gint ret;
770         struct timeval tv;
771         gpointer tmp_val;
772         MonoW32HandleSocket *socket_handle;
773
774         handle = GUINT_TO_POINTER (sock);
775         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
776                 mono_w32socket_set_last_error (WSAENOTSOCK);
777                 return SOCKET_ERROR;
778         }
779
780         tmp_val = optval;
781         if (level == SOL_SOCKET &&
782             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
783                 tmp_val = &tv;
784                 *optlen = sizeof (tv);
785         }
786
787         ret = getsockopt (sock, level, optname, tmp_val, optlen);
788         if (ret == -1) {
789                 gint errnum = errno;
790                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
791                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
792                 return SOCKET_ERROR;
793         }
794
795         if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
796                 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000);     // milli from micro
797                 *optlen = sizeof (int);
798         }
799
800         if (optname == SO_ERROR) {
801                 if (*((int *)optval) != 0) {
802                         *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
803                         socket_handle->saved_error = *((int *)optval);
804                 } else {
805                         *((int *)optval) = socket_handle->saved_error;
806                 }
807         }
808
809         return 0;
810 }
811
812 gint
813 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
814 {
815         gpointer handle;
816         gint ret;
817         gpointer tmp_val;
818 #if defined (__linux__)
819         /* This has its address taken so it cannot be moved to the if block which uses it */
820         gint bufsize = 0;
821 #endif
822         struct timeval tv;
823
824         handle = GUINT_TO_POINTER (sock);
825         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
826                 mono_w32socket_set_last_error (WSAENOTSOCK);
827                 return SOCKET_ERROR;
828         }
829
830         tmp_val = optval;
831         if (level == SOL_SOCKET &&
832             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
833                 int ms = *((int *) optval);
834                 tv.tv_sec = ms / 1000;
835                 tv.tv_usec = (ms % 1000) * 1000;        // micro from milli
836                 tmp_val = &tv;
837                 optlen = sizeof (tv);
838         }
839 #if defined (__linux__)
840         else if (level == SOL_SOCKET &&
841                    (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
842                 /* According to socket(7) the Linux kernel doubles the
843                  * buffer sizes "to allow space for bookkeeping
844                  * overhead."
845                  */
846                 bufsize = *((int *) optval);
847
848                 bufsize /= 2;
849                 tmp_val = &bufsize;
850         }
851 #endif
852
853         ret = setsockopt (sock, level, optname, tmp_val, optlen);
854         if (ret == -1) {
855                 gint errnum = errno;
856                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
857                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
858                 return SOCKET_ERROR;
859         }
860
861 #if defined (SO_REUSEPORT)
862         /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
863         if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
864                 int type;
865                 socklen_t type_len = sizeof (type);
866
867                 if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) {
868                         if (type == SOCK_DGRAM || type == SOCK_STREAM)
869                                 setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen);
870                 }
871         }
872 #endif
873
874         return ret;
875 }
876
877 gint
878 mono_w32socket_listen (SOCKET sock, gint backlog)
879 {
880         gpointer handle;
881         gint ret;
882
883         handle = GUINT_TO_POINTER (sock);
884         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
885                 mono_w32socket_set_last_error (WSAENOTSOCK);
886                 return SOCKET_ERROR;
887         }
888
889         ret = listen (sock, backlog);
890         if (ret == -1) {
891                 gint errnum = errno;
892                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
893                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
894                 return SOCKET_ERROR;
895         }
896
897         return 0;
898 }
899
900 gint
901 mono_w32socket_shutdown (SOCKET sock, gint how)
902 {
903         MonoW32HandleSocket *socket_handle;
904         gpointer handle;
905         gint ret;
906
907         handle = GUINT_TO_POINTER (sock);
908         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
909                 mono_w32socket_set_last_error (WSAENOTSOCK);
910                 return SOCKET_ERROR;
911         }
912
913         if (how == SHUT_RD || how == SHUT_RDWR)
914                 socket_handle->still_readable = 0;
915
916         ret = shutdown (sock, how);
917         if (ret == -1) {
918                 gint errnum = errno;
919                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno));
920                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
921                 return SOCKET_ERROR;
922         }
923
924         return ret;
925 }
926
927 gint
928 mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
929 {
930         MonoW32HandleSocket *socket_handle;
931         gpointer handle;
932         SOCKET newsock;
933         gint ret;
934
935         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock);
936
937         /* We could check the socket type here and fail unless its
938          * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
939          * if we really wanted to */
940
941         handle = GUINT_TO_POINTER (sock);
942         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
943                 mono_w32socket_set_last_error (WSAENOTSOCK);
944                 return SOCKET_ERROR;
945         }
946
947         newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol);
948         if (newsock == -1) {
949                 gint errnum = errno;
950                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum));
951                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
952                 return SOCKET_ERROR;
953         }
954
955         /* According to Stevens "Advanced Programming in the UNIX
956          * Environment: UNIX File I/O" dup2() is atomic so there
957          * should not be a race condition between the old fd being
958          * closed and the new socket fd being copied over */
959         do {
960                 ret = dup2 (newsock, sock);
961         } while (ret == -1 && errno == EAGAIN);
962
963         if (ret == -1) {
964                 gint errnum = errno;
965                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum));
966                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
967                 return SOCKET_ERROR;
968         }
969
970         close (newsock);
971
972         return 0;
973 }
974
975 static gboolean
976 extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
977 {
978         return mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
979 }
980
981 static gboolean
982 extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
983         OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
984 {
985         return mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
986 }
987
988 static struct {
989         GUID guid;
990         gpointer func;
991 } extension_functions[] = {
992         { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, extension_disconect },
993         { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, extension_transmit_file },
994         { {0} , NULL },
995 };
996
997 gint
998 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
999 {
1000         gpointer handle;
1001         gint ret;
1002         gchar *buffer;
1003
1004         handle = GUINT_TO_POINTER (sock);
1005         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1006                 mono_w32socket_set_last_error (WSAENOTSOCK);
1007                 return SOCKET_ERROR;
1008         }
1009
1010         if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1011                 gint i;
1012                 GUID *guid;
1013
1014                 if (inputlen < sizeof(GUID)) {
1015                         /* As far as I can tell, windows doesn't
1016                          * actually set an error here...
1017                          */
1018                         mono_w32socket_set_last_error (WSAEINVAL);
1019                         return SOCKET_ERROR;
1020                 }
1021
1022                 if (outputlen < sizeof(gpointer)) {
1023                         /* Or here... */
1024                         mono_w32socket_set_last_error (WSAEINVAL);
1025                         return SOCKET_ERROR;
1026                 }
1027
1028                 if (output == NULL) {
1029                         /* Or here */
1030                         mono_w32socket_set_last_error (WSAEINVAL);
1031                         return SOCKET_ERROR;
1032                 }
1033
1034                 guid = (GUID*) input;
1035                 for (i = 0; extension_functions[i].func; i++) {
1036                         if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
1037                                 memcpy (output, &extension_functions[i].func, sizeof(gpointer));
1038                                 *written = sizeof(gpointer);
1039                                 return 0;
1040                         }
1041                 }
1042
1043                 mono_w32socket_set_last_error (WSAEINVAL);
1044                 return SOCKET_ERROR;
1045         }
1046
1047         if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1048                 guint32 onoff;
1049
1050                 if (inputlen < 3 * sizeof (guint32)) {
1051                         mono_w32socket_set_last_error (WSAEINVAL);
1052                         return SOCKET_ERROR;
1053                 }
1054
1055                 onoff = *((guint32*) input);
1056
1057                 ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
1058                 if (ret < 0) {
1059                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1060                         return SOCKET_ERROR;
1061                 }
1062
1063 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1064                 if (onoff != 0) {
1065                         /* Values are in ms, but we need s */
1066                         guint32 keepalivetime, keepaliveinterval, rem;
1067
1068                         keepalivetime = *(((guint32*) input) + 1);
1069                         keepaliveinterval = *(((guint32*) input) + 2);
1070
1071                         /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1072                         rem = keepalivetime % 1000;
1073                         keepalivetime /= 1000;
1074                         if (keepalivetime == 0 || rem >= 500)
1075                                 keepalivetime++;
1076                         ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
1077                         if (ret == 0) {
1078                                 rem = keepaliveinterval % 1000;
1079                                 keepaliveinterval /= 1000;
1080                                 if (keepaliveinterval == 0 || rem >= 500)
1081                                         keepaliveinterval++;
1082                                 ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
1083                         }
1084                         if (ret != 0) {
1085                                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1086                                 return SOCKET_ERROR;
1087                         }
1088
1089                         return 0;
1090                 }
1091 #endif
1092
1093                 return 0;
1094         }
1095
1096         buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
1097
1098         ret = ioctl (sock, command, buffer);
1099         if (ret == -1) {
1100                 g_free (buffer);
1101
1102                 gint errnum = errno;
1103                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
1104                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1105                 return SOCKET_ERROR;
1106         }
1107
1108         if (!buffer) {
1109                 *written = 0;
1110                 return 0;
1111         }
1112
1113         /* We just copy the buffer to the output. Some ioctls
1114          * don't even output any data, but, well...
1115          *
1116          * NB windows returns WSAEFAULT if outputlen is too small */
1117         inputlen = (inputlen > outputlen) ? outputlen : inputlen;
1118
1119         if (inputlen > 0 && output != NULL)
1120                 memcpy (output, buffer, inputlen);
1121
1122         g_free (buffer);
1123         *written = inputlen;
1124
1125         return 0;
1126 }
1127
1128 gboolean
1129 mono_w32socket_close (SOCKET sock)
1130 {
1131         return mono_w32handle_close (GINT_TO_POINTER (sock));
1132 }
1133
1134 gint
1135 mono_w32socket_set_blocking (SOCKET socket, gboolean blocking)
1136 {
1137         gint ret;
1138         gpointer handle;
1139
1140         handle = GINT_TO_POINTER (socket);
1141         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1142                 mono_w32socket_set_last_error (WSAENOTSOCK);
1143                 return SOCKET_ERROR;
1144         }
1145
1146 #ifdef O_NONBLOCK
1147         /* This works better than ioctl(...FIONBIO...)
1148          * on Linux (it causes connect to return
1149          * EINPROGRESS, but the ioctl doesn't seem to) */
1150         ret = fcntl (socket, F_GETFL, 0);
1151         if (ret != -1)
1152                 ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
1153 #endif /* O_NONBLOCK */
1154
1155         if (ret == -1) {
1156                 gint errnum = errno;
1157                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1158                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1159                 return SOCKET_ERROR;
1160         }
1161
1162         return 0;
1163 }
1164
1165 gint
1166 mono_w32socket_get_available (SOCKET socket, guint64 *amount)
1167 {
1168         gint ret;
1169         gpointer handle;
1170
1171         handle = GINT_TO_POINTER (socket);
1172         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1173                 mono_w32socket_set_last_error (WSAENOTSOCK);
1174                 return SOCKET_ERROR;
1175         }
1176
1177 #if defined (PLATFORM_MACOSX)
1178         // ioctl (socket, FIONREAD, XXX) returns the size of
1179         // the UDP header as well on Darwin.
1180         //
1181         // Use getsockopt SO_NREAD instead to get the
1182         // right values for TCP and UDP.
1183         //
1184         // ai_canonname can be null in some cases on darwin,
1185         // where the runtime assumes it will be the value of
1186         // the ip buffer.
1187
1188         socklen_t optlen = sizeof (int);
1189         ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
1190 #else
1191         ret = ioctl (socket, FIONREAD, (gulong*) amount);
1192 #endif
1193
1194         if (ret == -1) {
1195                 gint errnum = errno;
1196                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1197                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1198                 return SOCKET_ERROR;
1199         }
1200
1201         return 0;
1202 }
1203
1204 void
1205 mono_w32socket_set_last_error (gint32 error)
1206 {
1207         mono_w32error_set_last (error);
1208 }
1209
1210 gint32
1211 mono_w32socket_get_last_error (void)
1212 {
1213         return mono_w32error_get_last ();
1214 }
1215
1216 gint32
1217 mono_w32socket_convert_error (gint error)
1218 {
1219         switch (error) {
1220         case 0: return ERROR_SUCCESS;
1221         case EACCES: return WSAEACCES;
1222 #ifdef EADDRINUSE
1223         case EADDRINUSE: return WSAEADDRINUSE;
1224 #endif
1225 #ifdef EAFNOSUPPORT
1226         case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1227 #endif
1228 #if EAGAIN != EWOULDBLOCK
1229         case EAGAIN: return WSAEWOULDBLOCK;
1230 #endif
1231 #ifdef EALREADY
1232         case EALREADY: return WSAEALREADY;
1233 #endif
1234         case EBADF: return WSAENOTSOCK;
1235 #ifdef ECONNABORTED
1236         case ECONNABORTED: return WSAENETDOWN;
1237 #endif
1238 #ifdef ECONNREFUSED
1239         case ECONNREFUSED: return WSAECONNREFUSED;
1240 #endif
1241 #ifdef ECONNRESET
1242         case ECONNRESET: return WSAECONNRESET;
1243 #endif
1244         case EFAULT: return WSAEFAULT;
1245 #ifdef EHOSTUNREACH
1246         case EHOSTUNREACH: return WSAEHOSTUNREACH;
1247 #endif
1248 #ifdef EINPROGRESS
1249         case EINPROGRESS: return WSAEINPROGRESS;
1250 #endif
1251         case EINTR: return WSAEINTR;
1252         case EINVAL: return WSAEINVAL;
1253         /*FIXME: case EIO: return WSAE????; */
1254 #ifdef EISCONN
1255         case EISCONN: return WSAEISCONN;
1256 #endif
1257         /* FIXME: case ELOOP: return WSA????; */
1258         case EMFILE: return WSAEMFILE;
1259 #ifdef EMSGSIZE
1260         case EMSGSIZE: return WSAEMSGSIZE;
1261 #endif
1262         /* FIXME: case ENAMETOOLONG: return WSAEACCES; */
1263 #ifdef ENETUNREACH
1264         case ENETUNREACH: return WSAENETUNREACH;
1265 #endif
1266 #ifdef ENOBUFS
1267         case ENOBUFS: return WSAENOBUFS; /* not documented */
1268 #endif
1269         /* case ENOENT: return WSAE????; */
1270         case ENOMEM: return WSAENOBUFS;
1271 #ifdef ENOPROTOOPT
1272         case ENOPROTOOPT: return WSAENOPROTOOPT;
1273 #endif
1274 #ifdef ENOSR
1275         case ENOSR: return WSAENETDOWN;
1276 #endif
1277 #ifdef ENOTCONN
1278         case ENOTCONN: return WSAENOTCONN;
1279 #endif
1280         /*FIXME: case ENOTDIR: return WSAE????; */
1281 #ifdef ENOTSOCK
1282         case ENOTSOCK: return WSAENOTSOCK;
1283 #endif
1284         case ENOTTY: return WSAENOTSOCK;
1285 #ifdef EOPNOTSUPP
1286         case EOPNOTSUPP: return WSAEOPNOTSUPP;
1287 #endif
1288         case EPERM: return WSAEACCES;
1289         case EPIPE: return WSAESHUTDOWN;
1290 #ifdef EPROTONOSUPPORT
1291         case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1292 #endif
1293 #if ERESTARTSYS
1294         case ERESTARTSYS: return WSAENETDOWN;
1295 #endif
1296         /*FIXME: case EROFS: return WSAE????; */
1297 #ifdef ESOCKTNOSUPPORT
1298         case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1299 #endif
1300 #ifdef ETIMEDOUT
1301         case ETIMEDOUT: return WSAETIMEDOUT;
1302 #endif
1303 #ifdef EWOULDBLOCK
1304         case EWOULDBLOCK: return WSAEWOULDBLOCK;
1305 #endif
1306 #ifdef EADDRNOTAVAIL
1307         case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1308 #endif
1309         /* This might happen with unix sockets */
1310         case ENOENT: return WSAECONNREFUSED;
1311 #ifdef EDESTADDRREQ
1312         case EDESTADDRREQ: return WSAEDESTADDRREQ;
1313 #endif
1314 #ifdef EHOSTDOWN
1315         case EHOSTDOWN: return WSAEHOSTDOWN;
1316 #endif
1317 #ifdef ENETDOWN
1318         case ENETDOWN: return WSAENETDOWN;
1319 #endif
1320         case ENODEV: return WSAENETDOWN;
1321 #ifdef EPROTOTYPE
1322         case EPROTOTYPE: return WSAEPROTOTYPE;
1323 #endif
1324         default:
1325                 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
1326         }
1327 }
1328
1329 gboolean
1330 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto)
1331 {
1332 #if defined (SO_REUSEPORT)
1333         return TRUE;
1334 #else
1335 #ifdef __linux__
1336         /* Linux always supports double binding for UDP, even on older kernels. */
1337         if (proto == ProtocolType_Udp)
1338                 return TRUE;
1339 #endif
1340         return FALSE;
1341 #endif
1342 }