[HttpConnection] Bug fix: HttpListener's "IgnoreWriteExceptions" property value is...
[mono.git] / mono / metadata / socket-io.c
1 /*
2  * socket-io.c: Socket IO internal calls
3  *
4  * Authors:
5  *      Dick Porter (dick@ximian.com)
6  *      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  *
11  * This file has been re-licensed under the MIT License:
12  * http://opensource.org/licenses/MIT
13  */
14
15 #include <config.h>
16
17 #ifndef DISABLE_SOCKETS
18
19 #if defined(__APPLE__) || defined(__FreeBSD__)
20 #define __APPLE_USE_RFC_3542
21 #endif
22
23 #include <glib.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #ifdef HOST_WIN32
27 #include <ws2tcpip.h>
28 #else
29 #include <sys/socket.h>
30 #ifdef HAVE_SYS_IOCTL_H
31 #include <sys/ioctl.h>
32 #endif
33 #include <netinet/in.h>
34 #include <netinet/tcp.h>
35 #ifdef HAVE_NETDB_H
36 #include <netdb.h>
37 #endif
38 #include <arpa/inet.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #include <errno.h>
44
45 #include <sys/types.h>
46
47 #include <mono/metadata/object.h>
48 #include <mono/io-layer/io-layer.h>
49 #include <mono/metadata/socket-io.h>
50 #include <mono/metadata/exception.h>
51 #include <mono/metadata/assembly.h>
52 #include <mono/metadata/appdomain.h>
53 #include <mono/metadata/file-io.h>
54 #include <mono/metadata/threads.h>
55 #include <mono/metadata/threads-types.h>
56 #include <mono/metadata/threadpool-ms-io.h>
57 #include <mono/utils/mono-poll.h>
58 /* FIXME change this code to not mess so much with the internals */
59 #include <mono/metadata/class-internals.h>
60 #include <mono/metadata/domain-internals.h>
61 #include <mono/utils/mono-threads.h>
62 #include <mono/utils/mono-memory-model.h>
63 #include <mono/utils/networking.h>
64
65 #include <time.h>
66 #ifdef HAVE_SYS_TIME_H
67 #include <sys/time.h>
68 #endif
69 #ifdef HAVE_SYS_IOCTL_H
70 #include <sys/ioctl.h>
71 #endif
72 #ifdef HAVE_NET_IF_H
73 #include <net/if.h>
74 #endif
75
76 #ifdef HAVE_NETDB_H
77 #include <netdb.h>
78 #endif
79 #ifdef HAVE_SYS_FILIO_H
80 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
81 #endif
82 #ifdef HAVE_SYS_SOCKIO_H
83 #include <sys/sockio.h>    /* defines SIOCATMARK */
84 #endif
85 #ifdef HAVE_SYS_UN_H
86 #include <sys/un.h>
87 #endif
88
89 #ifdef HAVE_GETIFADDRS
90 // <net/if.h> must be included before <ifaddrs.h>
91 #include <ifaddrs.h>
92 #endif
93
94 #include "mono/io-layer/socket-wrappers.h"
95
96 #define LOGDEBUG(...)  
97 /* define LOGDEBUG(...) g_message(__VA_ARGS__)  */
98
99 static void
100 abort_syscall (gpointer data)
101 {
102         mono_thread_info_abort_socket_syscall_for_close ((MonoNativeThreadId) (gsize) data);
103 }
104
105 static gint32
106 convert_family (MonoAddressFamily mono_family)
107 {
108         switch (mono_family) {
109         case AddressFamily_Unknown:
110         case AddressFamily_ImpLink:
111         case AddressFamily_Pup:
112         case AddressFamily_Chaos:
113         case AddressFamily_Iso:
114         case AddressFamily_Ecma:
115         case AddressFamily_DataKit:
116         case AddressFamily_Ccitt:
117         case AddressFamily_DataLink:
118         case AddressFamily_Lat:
119         case AddressFamily_HyperChannel:
120         case AddressFamily_NetBios:
121         case AddressFamily_VoiceView:
122         case AddressFamily_FireFox:
123         case AddressFamily_Banyan:
124         case AddressFamily_Atm:
125         case AddressFamily_Cluster:
126         case AddressFamily_Ieee12844:
127         case AddressFamily_NetworkDesigners:
128                 g_warning("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
129                 return -1;
130         case AddressFamily_Unspecified:
131                 return AF_UNSPEC;
132         case AddressFamily_Unix:
133                 return AF_UNIX;
134         case AddressFamily_InterNetwork:
135                 return AF_INET;
136         case AddressFamily_AppleTalk:
137                 return AF_APPLETALK;
138         case AddressFamily_InterNetworkV6:
139                 return AF_INET6;
140         case AddressFamily_DecNet:
141 #ifdef AF_DECnet
142                 return AF_DECnet;
143 #else
144                 return -1;
145 #endif
146         case AddressFamily_Ipx:
147 #ifdef AF_IPX
148                 return AF_IPX;
149 #else
150                 return -1;
151 #endif
152         case AddressFamily_Sna:
153 #ifdef AF_SNA
154                 return AF_SNA;
155 #else
156                 return -1;
157 #endif
158         case AddressFamily_Irda:
159 #ifdef AF_IRDA
160                 return AF_IRDA;
161 #else
162                 return -1;
163 #endif
164         default:
165                 g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
166                 return -1;
167         }
168 }
169
170 static MonoAddressFamily
171 convert_to_mono_family (guint16 af_family)
172 {
173         switch (af_family) {
174         case AF_UNSPEC:
175                 return AddressFamily_Unspecified;
176         case AF_UNIX:
177                 return AddressFamily_Unix;
178         case AF_INET:
179                 return AddressFamily_InterNetwork;
180 #ifdef AF_IPX
181         case AF_IPX:
182                 return AddressFamily_Ipx;
183 #endif
184 #ifdef AF_SNA
185         case AF_SNA:
186                 return AddressFamily_Sna;
187 #endif
188 #ifdef AF_DECnet
189         case AF_DECnet:
190                 return AddressFamily_DecNet;
191 #endif
192         case AF_APPLETALK:
193                 return AddressFamily_AppleTalk;
194         case AF_INET6:
195                 return AddressFamily_InterNetworkV6;
196 #ifdef AF_IRDA
197         case AF_IRDA:
198                 return AddressFamily_Irda;
199 #endif
200         default:
201                 g_warning("unknown address family 0x%x", af_family);
202                 return AddressFamily_Unknown;
203         }
204 }
205
206 static gint32
207 convert_type (MonoSocketType mono_type)
208 {
209         switch (mono_type) {
210         case SocketType_Stream:
211                 return SOCK_STREAM;
212         case SocketType_Dgram:
213                 return SOCK_DGRAM;
214         case SocketType_Raw:
215                 return SOCK_RAW;
216         case SocketType_Rdm:
217 #ifdef SOCK_RDM
218                 return SOCK_RDM;
219 #else
220                 return -1;
221 #endif
222         case SocketType_Seqpacket:
223                 return SOCK_SEQPACKET;
224         case SocketType_Unknown:
225                 g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
226                 return -1;
227         default:
228                 g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
229                 return -1;
230         }
231 }
232
233 static gint32
234 convert_proto (MonoProtocolType mono_proto)
235 {
236         switch (mono_proto) {
237         case ProtocolType_IP:
238         case ProtocolType_IPv6:
239         case ProtocolType_Icmp:
240         case ProtocolType_Igmp:
241         case ProtocolType_Ggp:
242         case ProtocolType_Tcp:
243         case ProtocolType_Pup:
244         case ProtocolType_Udp:
245         case ProtocolType_Idp:
246                 /* These protocols are known (on my system at least) */
247                 return mono_proto;
248         case ProtocolType_ND:
249         case ProtocolType_Raw:
250         case ProtocolType_Ipx:
251         case ProtocolType_Spx:
252         case ProtocolType_SpxII:
253         case ProtocolType_Unknown:
254                 /* These protocols arent */
255                 g_warning("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
256                 return -1;
257         default:
258                 return -1;
259         }
260 }
261
262 /* Convert MonoSocketFlags */
263 static gint32
264 convert_socketflags (gint32 sflags)
265 {
266         gint32 flags = 0;
267
268         if (!sflags)
269                 /* SocketFlags.None */
270                 return 0;
271
272         if (sflags & ~(SocketFlags_OutOfBand | SocketFlags_MaxIOVectorLength | SocketFlags_Peek | 
273                         SocketFlags_DontRoute | SocketFlags_Partial))
274                 /* Contains invalid flag values */
275                 return -1;
276
277         if (sflags & SocketFlags_OutOfBand)
278                 flags |= MSG_OOB;
279         if (sflags & SocketFlags_Peek)
280                 flags |= MSG_PEEK;
281         if (sflags & SocketFlags_DontRoute)
282                 flags |= MSG_DONTROUTE;
283
284         /* Ignore Partial - see bug 349688.  Don't return -1, because
285          * according to the comment in that bug ms runtime doesn't for
286          * UDP sockets (this means we will silently ignore it for TCP
287          * too)
288          */
289 #ifdef MSG_MORE
290         if (sflags & SocketFlags_Partial)
291                 flags |= MSG_MORE;
292 #endif
293 #if 0
294         /* Don't do anything for MaxIOVectorLength */
295         if (sflags & SocketFlags_MaxIOVectorLength)
296                 return -1;      
297 #endif
298         return flags;
299 }
300
301 /*
302  * Returns:
303  *    0 on success (mapped mono_level and mono_name to system_level and system_name
304  *   -1 on error
305  *   -2 on non-fatal error (ie, must ignore)
306  */
307 static gint32
308 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level, MonoSocketOptionName mono_name, int *system_level, int *system_name)
309 {
310         switch (mono_level) {
311         case SocketOptionLevel_Socket:
312                 *system_level = SOL_SOCKET;
313                 
314                 switch(mono_name) {
315                 case SocketOptionName_DontLinger:
316                         /* This is SO_LINGER, because the setsockopt
317                          * internal call maps DontLinger to SO_LINGER
318                          * with l_onoff=0
319                          */
320                         *system_name = SO_LINGER;
321                         break;
322                 case SocketOptionName_Debug:
323                         *system_name = SO_DEBUG;
324                         break;
325 #ifdef SO_ACCEPTCONN
326                 case SocketOptionName_AcceptConnection:
327                         *system_name = SO_ACCEPTCONN;
328                         break;
329 #endif
330                 case SocketOptionName_ReuseAddress:
331                         *system_name = SO_REUSEADDR;
332                         break;
333                 case SocketOptionName_KeepAlive:
334                         *system_name = SO_KEEPALIVE;
335                         break;
336                 case SocketOptionName_DontRoute:
337                         *system_name = SO_DONTROUTE;
338                         break;
339                 case SocketOptionName_Broadcast:
340                         *system_name = SO_BROADCAST;
341                         break;
342                 case SocketOptionName_Linger:
343                         *system_name = SO_LINGER;
344                         break;
345                 case SocketOptionName_OutOfBandInline:
346                         *system_name = SO_OOBINLINE;
347                         break;
348                 case SocketOptionName_SendBuffer:
349                         *system_name = SO_SNDBUF;
350                         break;
351                 case SocketOptionName_ReceiveBuffer:
352                         *system_name = SO_RCVBUF;
353                         break;
354                 case SocketOptionName_SendLowWater:
355                         *system_name = SO_SNDLOWAT;
356                         break;
357                 case SocketOptionName_ReceiveLowWater:
358                         *system_name = SO_RCVLOWAT;
359                         break;
360                 case SocketOptionName_SendTimeout:
361                         *system_name = SO_SNDTIMEO;
362                         break;
363                 case SocketOptionName_ReceiveTimeout:
364                         *system_name = SO_RCVTIMEO;
365                         break;
366                 case SocketOptionName_Error:
367                         *system_name = SO_ERROR;
368                         break;
369                 case SocketOptionName_Type:
370                         *system_name = SO_TYPE;
371                         break;
372 #ifdef SO_PEERCRED
373                 case SocketOptionName_PeerCred:
374                         *system_name = SO_PEERCRED;
375                         break;
376 #endif
377                 case SocketOptionName_ExclusiveAddressUse:
378 #ifdef SO_EXCLUSIVEADDRUSE
379                         *system_name = SO_EXCLUSIVEADDRUSE;
380                         break;
381 #endif
382                 case SocketOptionName_UseLoopback:
383 #ifdef SO_USELOOPBACK
384                         *system_name = SO_USELOOPBACK;
385                         break;
386 #endif
387                 case SocketOptionName_MaxConnections:
388 #ifdef SO_MAXCONN
389                         *system_name = SO_MAXCONN;
390                         break;
391 #elif defined(SOMAXCONN)
392                         *system_name = SOMAXCONN;
393                         break;
394 #endif
395                 default:
396                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
397                         return(-1);
398                 }
399                 break;
400                 
401         case SocketOptionLevel_IP:
402                 *system_level = mono_networking_get_ip_protocol ();
403                 
404                 switch(mono_name) {
405                 case SocketOptionName_IPOptions:
406                         *system_name = IP_OPTIONS;
407                         break;
408 #ifdef IP_HDRINCL
409                 case SocketOptionName_HeaderIncluded:
410                         *system_name = IP_HDRINCL;
411                         break;
412 #endif
413 #ifdef IP_TOS
414                 case SocketOptionName_TypeOfService:
415                         *system_name = IP_TOS;
416                         break;
417 #endif
418 #ifdef IP_TTL
419                 case SocketOptionName_IpTimeToLive:
420                         *system_name = IP_TTL;
421                         break;
422 #endif
423                 case SocketOptionName_MulticastInterface:
424                         *system_name = IP_MULTICAST_IF;
425                         break;
426                 case SocketOptionName_MulticastTimeToLive:
427                         *system_name = IP_MULTICAST_TTL;
428                         break;
429                 case SocketOptionName_MulticastLoopback:
430                         *system_name = IP_MULTICAST_LOOP;
431                         break;
432                 case SocketOptionName_AddMembership:
433                         *system_name = IP_ADD_MEMBERSHIP;
434                         break;
435                 case SocketOptionName_DropMembership:
436                         *system_name = IP_DROP_MEMBERSHIP;
437                         break;
438 #ifdef HAVE_IP_PKTINFO
439                 case SocketOptionName_PacketInformation:
440                         *system_name = IP_PKTINFO;
441                         break;
442 #endif /* HAVE_IP_PKTINFO */
443
444                 case SocketOptionName_DontFragment:
445 #ifdef HAVE_IP_DONTFRAGMENT
446                         *system_name = IP_DONTFRAGMENT;
447                         break;
448 #elif defined HAVE_IP_MTU_DISCOVER
449                         /* Not quite the same */
450                         *system_name = IP_MTU_DISCOVER;
451                         break;
452 #else
453                         /* If the flag is not available on this system, we can ignore this error */
454                         return (-2);
455 #endif /* HAVE_IP_DONTFRAGMENT */
456                 case SocketOptionName_AddSourceMembership:
457                 case SocketOptionName_DropSourceMembership:
458                 case SocketOptionName_BlockSource:
459                 case SocketOptionName_UnblockSource:
460                         /* Can't figure out how to map these, so fall
461                          * through
462                          */
463                 default:
464                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
465                         return(-1);
466                 }
467                 break;
468
469         case SocketOptionLevel_IPv6:
470                 *system_level = mono_networking_get_ipv6_protocol ();
471
472                 switch(mono_name) {
473                 case SocketOptionName_IpTimeToLive:
474                 case SocketOptionName_HopLimit:
475                         *system_name = IPV6_UNICAST_HOPS;
476                         break;
477                 case SocketOptionName_MulticastInterface:
478                         *system_name = IPV6_MULTICAST_IF;
479                         break;
480                 case SocketOptionName_MulticastTimeToLive:
481                         *system_name = IPV6_MULTICAST_HOPS;
482                         break;
483                 case SocketOptionName_MulticastLoopback:
484                         *system_name = IPV6_MULTICAST_LOOP;
485                         break;
486                 case SocketOptionName_AddMembership:
487                         *system_name = IPV6_JOIN_GROUP;
488                         break;
489                 case SocketOptionName_DropMembership:
490                         *system_name = IPV6_LEAVE_GROUP;
491                         break;
492                 case SocketOptionName_IPv6Only:
493 #ifdef IPV6_V6ONLY
494                         *system_name = IPV6_V6ONLY;
495 #else
496                         return -1;
497 #endif
498                         break;
499                 case SocketOptionName_PacketInformation:
500 #ifdef HAVE_IPV6_PKTINFO
501                         *system_name = IPV6_PKTINFO;
502 #endif
503                         break;
504                 case SocketOptionName_HeaderIncluded:
505                 case SocketOptionName_IPOptions:
506                 case SocketOptionName_TypeOfService:
507                 case SocketOptionName_DontFragment:
508                 case SocketOptionName_AddSourceMembership:
509                 case SocketOptionName_DropSourceMembership:
510                 case SocketOptionName_BlockSource:
511                 case SocketOptionName_UnblockSource:
512                         /* Can't figure out how to map these, so fall
513                          * through
514                          */
515                 default:
516                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name);
517                         return(-1);
518                 }
519
520                 break;  /* SocketOptionLevel_IPv6 */
521                 
522         case SocketOptionLevel_Tcp:
523                 *system_level = mono_networking_get_tcp_protocol ();
524                 
525                 switch(mono_name) {
526                 case SocketOptionName_NoDelay:
527                         *system_name = TCP_NODELAY;
528                         break;
529 #if 0
530                         /* The documentation is talking complete
531                          * bollocks here: rfc-1222 is titled
532                          * 'Advancing the NSFNET Routing Architecture'
533                          * and doesn't mention either of the words
534                          * "expedite" or "urgent".
535                          */
536                 case SocketOptionName_BsdUrgent:
537                 case SocketOptionName_Expedited:
538 #endif
539                 default:
540                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
541                         return(-1);
542                 }
543                 break;
544                 
545         case SocketOptionLevel_Udp:
546                 g_warning("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
547
548                 switch(mono_name) {
549                 case SocketOptionName_NoChecksum:
550                 case SocketOptionName_ChecksumCoverage:
551                 default:
552                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
553                         return(-1);
554                 }
555                 return(-1);
556                 break;
557
558         default:
559                 g_warning("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
560                 return(-1);
561         }
562
563         return(0);
564 }
565
566 static MonoImage*
567 get_socket_assembly (void)
568 {
569         MonoDomain *domain = mono_domain_get ();
570         
571         if (domain->socket_assembly == NULL) {
572                 MonoImage *socket_assembly;
573
574                 socket_assembly = mono_image_loaded ("System");
575                 if (!socket_assembly) {
576                         MonoAssembly *sa = mono_assembly_open ("System.dll", NULL);
577                 
578                         if (!sa) {
579                                 g_assert_not_reached ();
580                         } else {
581                                 socket_assembly = mono_assembly_get_image (sa);
582                         }
583                 }
584                 mono_atomic_store_release (&domain->socket_assembly, socket_assembly);
585         }
586         
587         return domain->socket_assembly;
588 }
589
590 static gint32
591 get_family_hint (void)
592 {
593         MonoDomain *domain = mono_domain_get ();
594
595         if (!domain->inet_family_hint) {
596                 MonoImage *socket_assembly;
597                 MonoClass *socket_class;
598                 MonoClassField *ipv6_field, *ipv4_field;
599                 gint32 ipv6_enabled = -1, ipv4_enabled = -1;
600                 MonoVTable *vtable;
601
602                 socket_assembly = get_socket_assembly ();
603                 g_assert (socket_assembly);
604
605                 socket_class = mono_class_from_name (socket_assembly, "System.Net.Sockets", "Socket");
606                 g_assert (socket_class);
607
608                 ipv4_field = mono_class_get_field_from_name (socket_class, "ipv4_supported");
609                 g_assert (ipv4_field);
610
611                 ipv6_field = mono_class_get_field_from_name (socket_class, "ipv6_supported");
612                 g_assert (ipv6_field);
613
614                 vtable = mono_class_vtable (mono_domain_get (), socket_class);
615                 g_assert (vtable);
616
617                 mono_runtime_class_init (vtable);
618
619                 mono_field_static_get_value (vtable, ipv4_field, &ipv4_enabled);
620                 mono_field_static_get_value (vtable, ipv6_field, &ipv6_enabled);
621
622                 mono_domain_lock (domain);
623                 if (ipv4_enabled == 1 && ipv6_enabled == 1) {
624                         domain->inet_family_hint = 1;
625                 } else if (ipv4_enabled == 1) {
626                         domain->inet_family_hint = 2;
627                 } else {
628                         domain->inet_family_hint = 3;
629                 }
630                 mono_domain_unlock (domain);
631         }
632         switch (domain->inet_family_hint) {
633         case 1: return PF_UNSPEC;
634         case 2: return PF_INET;
635         case 3: return PF_INET6;
636         default:
637                 return PF_UNSPEC;
638         }
639 }
640
641 gpointer
642 ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject *this_obj, gint32 family, gint32 type, gint32 proto, gint32 *error)
643 {
644         SOCKET sock;
645         gint32 sock_family;
646         gint32 sock_proto;
647         gint32 sock_type;
648         
649         *error = 0;
650         
651         sock_family=convert_family(family);
652         if(sock_family==-1) {
653                 *error = WSAEAFNOSUPPORT;
654                 return(NULL);
655         }
656
657         sock_proto=convert_proto(proto);
658         if(sock_proto==-1) {
659                 *error = WSAEPROTONOSUPPORT;
660                 return(NULL);
661         }
662         
663         sock_type=convert_type(type);
664         if(sock_type==-1) {
665                 *error = WSAESOCKTNOSUPPORT;
666                 return(NULL);
667         }
668         
669         sock = _wapi_socket (sock_family, sock_type, sock_proto,
670                              NULL, 0, WSA_FLAG_OVERLAPPED);
671
672         if(sock==INVALID_SOCKET) {
673                 *error = WSAGetLastError ();
674                 return(NULL);
675         }
676
677         return(GUINT_TO_POINTER (sock));
678 }
679
680 /* FIXME: the SOCKET parameter (here and in other functions in this
681  * file) is really an IntPtr which needs to be converted to a guint32.
682  */
683 void
684 ves_icall_System_Net_Sockets_Socket_Close_internal (SOCKET sock, gint32 *error)
685 {
686         LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock));
687
688         *error = 0;
689
690         /* Clear any pending work item from this socket if the underlying
691          * polling system does not notify when the socket is closed */
692         mono_threadpool_ms_io_remove_socket (GPOINTER_TO_INT (sock));
693         closesocket(sock);
694 }
695
696 gint32
697 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void)
698 {
699         LOGDEBUG (g_message("%s: returning %d", __func__, WSAGetLastError()));
700
701         return(WSAGetLastError());
702 }
703
704 gint32
705 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock, gint32 *error)
706 {
707         int ret;
708         int amount;
709         
710         *error = 0;
711
712         /* FIXME: this might require amount to be unsigned long. */
713         ret=ioctlsocket(sock, FIONREAD, &amount);
714         if(ret==SOCKET_ERROR) {
715                 *error = WSAGetLastError ();
716                 return(0);
717         }
718         
719         return(amount);
720 }
721
722 void
723 ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock, gboolean block, gint32 *error)
724 {
725         int ret;
726         
727         *error = 0;
728
729         /*
730          * block == TRUE/FALSE means we will block/not block.
731          * But the ioctlsocket call takes TRUE/FALSE for non-block/block
732          */
733         block = !block;
734         
735         ret = ioctlsocket (sock, FIONBIO, (gulong *) &block);
736         if(ret==SOCKET_ERROR) {
737                 *error = WSAGetLastError ();
738         }
739 }
740
741 gpointer
742 ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *error, gboolean blocking)
743 {
744         gboolean interrupted;
745         SOCKET newsock;
746
747         *error = 0;
748
749         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
750         if (interrupted) {
751                 *error = WSAEINTR;
752                 return NULL;
753         }
754
755         MONO_PREPARE_BLOCKING;
756
757 #ifdef HOST_WIN32
758         {
759                 MonoInternalThread *curthread = mono_thread_internal_current ();
760                 curthread->interrupt_on_stop = (gpointer)TRUE;
761                 newsock = _wapi_accept (sock, NULL, 0);
762                 curthread->interrupt_on_stop = (gpointer)FALSE;
763         }
764 #else
765         newsock = _wapi_accept (sock, NULL, 0);
766 #endif
767
768         MONO_FINISH_BLOCKING;
769
770         mono_thread_info_uninstall_interrupt (&interrupted);
771         if (interrupted) {
772                 *error = WSAEINTR;
773                 return NULL;
774         }
775
776         if(newsock==INVALID_SOCKET) {
777                 *error = WSAGetLastError ();
778                 return(NULL);
779         }
780         
781         return(GUINT_TO_POINTER (newsock));
782 }
783
784 void
785 ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog, gint32 *error)
786 {
787         int ret;
788         
789         *error = 0;
790
791         MONO_PREPARE_BLOCKING;
792
793         ret = _wapi_listen (sock, backlog);
794
795         MONO_FINISH_BLOCKING;
796
797         if(ret==SOCKET_ERROR) {
798                 *error = WSAGetLastError ();
799         }
800 }
801
802 // Check whether it's ::ffff::0:0.
803 static gboolean
804 is_ipv4_mapped_any (const struct in6_addr *addr)
805 {
806         int i;
807         
808         for (i = 0; i < 10; i++) {
809                 if (addr->s6_addr [i])
810                         return FALSE;
811         }
812         if ((addr->s6_addr [10] != 0xff) || (addr->s6_addr [11] != 0xff))
813                 return FALSE;
814         for (i = 12; i < 16; i++) {
815                 if (addr->s6_addr [i])
816                         return FALSE;
817         }
818         return TRUE;
819 }
820
821 static MonoObject*
822 create_object_from_sockaddr(struct sockaddr *saddr, int sa_size, gint32 *error)
823 {
824         MonoDomain *domain = mono_domain_get ();
825         MonoObject *sockaddr_obj;
826         MonoArray *data;
827         MonoAddressFamily family;
828
829         /* Build a System.Net.SocketAddress object instance */
830         if (!domain->sockaddr_class) {
831                 domain->sockaddr_class=mono_class_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
832                 g_assert (domain->sockaddr_class);
833         }
834         sockaddr_obj=mono_object_new(domain, domain->sockaddr_class);
835         
836         /* Locate the SocketAddress data buffer in the object */
837         if (!domain->sockaddr_data_field) {
838                 domain->sockaddr_data_field=mono_class_get_field_from_name (domain->sockaddr_class, "data");
839                 g_assert (domain->sockaddr_data_field);
840         }
841
842         /* May be the +2 here is too conservative, as sa_len returns
843          * the length of the entire sockaddr_in/in6, including
844          * sizeof (unsigned short) of the family */
845         /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
846         data=mono_array_new_cached(domain, mono_get_byte_class (), sa_size+2);
847
848         /* The data buffer is laid out as follows:
849          * bytes 0 and 1 are the address family
850          * bytes 2 and 3 are the port info
851          * the rest is the address info
852          */
853                 
854         family=convert_to_mono_family(saddr->sa_family);
855         if(family==AddressFamily_Unknown) {
856                 *error = WSAEAFNOSUPPORT;
857                 return(NULL);
858         }
859
860         mono_array_set(data, guint8, 0, family & 0x0FF);
861         mono_array_set(data, guint8, 1, (family >> 8) & 0x0FF);
862         
863         if(saddr->sa_family==AF_INET) {
864                 struct sockaddr_in *sa_in=(struct sockaddr_in *)saddr;
865                 guint16 port=ntohs(sa_in->sin_port);
866                 guint32 address=ntohl(sa_in->sin_addr.s_addr);
867                 
868                 if(sa_size<8) {
869                         mono_raise_exception((MonoException *)mono_exception_from_name(mono_get_corlib (), "System", "SystemException"));
870                 }
871                 
872                 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
873                 mono_array_set(data, guint8, 3, (port) & 0xff);
874                 mono_array_set(data, guint8, 4, (address>>24) & 0xff);
875                 mono_array_set(data, guint8, 5, (address>>16) & 0xff);
876                 mono_array_set(data, guint8, 6, (address>>8) & 0xff);
877                 mono_array_set(data, guint8, 7, (address) & 0xff);
878         
879                 mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
880
881                 return(sockaddr_obj);
882         } else if (saddr->sa_family == AF_INET6) {
883                 struct sockaddr_in6 *sa_in=(struct sockaddr_in6 *)saddr;
884                 int i;
885
886                 guint16 port=ntohs(sa_in->sin6_port);
887
888                 if(sa_size<28) {
889                         mono_raise_exception((MonoException *)mono_exception_from_name(mono_get_corlib (), "System", "SystemException"));
890                 }
891
892                 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
893                 mono_array_set(data, guint8, 3, (port) & 0xff);
894                 
895                 if (is_ipv4_mapped_any (&sa_in->sin6_addr)) {
896                         // Map ::ffff:0:0 to :: (bug #5502)
897                         for(i=0; i<16; i++) {
898                                 mono_array_set(data, guint8, 8+i, 0);
899                         }
900                 } else {
901                         for(i=0; i<16; i++) {
902                                 mono_array_set(data, guint8, 8+i,
903                                                sa_in->sin6_addr.s6_addr[i]);
904                         }
905                 }
906
907                 mono_array_set(data, guint8, 24, sa_in->sin6_scope_id & 0xff);
908                 mono_array_set(data, guint8, 25,
909                                (sa_in->sin6_scope_id >> 8) & 0xff);
910                 mono_array_set(data, guint8, 26,
911                                (sa_in->sin6_scope_id >> 16) & 0xff);
912                 mono_array_set(data, guint8, 27,
913                                (sa_in->sin6_scope_id >> 24) & 0xff);
914
915                 mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
916
917                 return(sockaddr_obj);
918         }
919 #ifdef HAVE_SYS_UN_H
920         else if (saddr->sa_family == AF_UNIX) {
921                 int i;
922
923                 for (i = 0; i < sa_size; i++) {
924                         mono_array_set (data, guint8, i+2, saddr->sa_data[i]);
925                 }
926                 
927                 mono_field_set_value (sockaddr_obj, domain->sockaddr_data_field, data);
928
929                 return sockaddr_obj;
930         }
931 #endif
932         else {
933                 *error = WSAEAFNOSUPPORT;
934                 return(NULL);
935         }
936 }
937
938 static int
939 get_sockaddr_size (int family)
940 {
941         int size;
942
943         size = 0;
944         if (family == AF_INET) {
945                 size = sizeof (struct sockaddr_in);
946         } else if (family == AF_INET6) {
947                 size = sizeof (struct sockaddr_in6);
948         }
949 #ifdef HAVE_SYS_UN_H
950         else if (family == AF_UNIX) {
951                 size = sizeof (struct sockaddr_un);
952         }
953 #endif
954         return size;
955 }
956
957 MonoObject*
958 ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock, gint32 af, gint32 *error)
959 {
960         gchar *sa;
961         socklen_t salen;
962         int ret;
963         MonoObject *result;
964         
965         *error = 0;
966         
967         salen = get_sockaddr_size (convert_family (af));
968         if (salen == 0) {
969                 *error = WSAEAFNOSUPPORT;
970                 return NULL;
971         }
972         sa = (salen <= 128) ? alloca (salen) : g_malloc0 (salen);
973
974         MONO_PREPARE_BLOCKING;
975
976         ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen);
977
978         MONO_FINISH_BLOCKING;
979         
980         if(ret==SOCKET_ERROR) {
981                 *error = WSAGetLastError ();
982                 if (salen > 128)
983                         g_free (sa);
984                 return(NULL);
985         }
986         
987         LOGDEBUG (g_message("%s: bound to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port)));
988
989         result = create_object_from_sockaddr((struct sockaddr *)sa, salen, error);
990         if (salen > 128)
991                 g_free (sa);
992         return result;
993 }
994
995 MonoObject*
996 ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (SOCKET sock, gint32 af, gint32 *error)
997 {
998         gchar *sa;
999         socklen_t salen;
1000         int ret;
1001         MonoObject *result;
1002         
1003         *error = 0;
1004         
1005         salen = get_sockaddr_size (convert_family (af));
1006         if (salen == 0) {
1007                 *error = WSAEAFNOSUPPORT;
1008                 return NULL;
1009         }
1010         sa = (salen <= 128) ? alloca (salen) : g_malloc0 (salen);
1011         /* Note: linux returns just 2 for AF_UNIX. Always. */
1012
1013         MONO_PREPARE_BLOCKING;
1014
1015         ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen);
1016
1017         MONO_FINISH_BLOCKING;
1018
1019         if(ret==SOCKET_ERROR) {
1020                 *error = WSAGetLastError ();
1021                 if (salen > 128)
1022                         g_free (sa);
1023                 return(NULL);
1024         }
1025         
1026         LOGDEBUG (g_message("%s: connected to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port)));
1027
1028         result = create_object_from_sockaddr((struct sockaddr *)sa, salen, error);
1029         if (salen > 128)
1030                 g_free (sa);
1031         return result;
1032 }
1033
1034 static struct sockaddr*
1035 create_sockaddr_from_object(MonoObject *saddr_obj, socklen_t *sa_size, gint32 *error)
1036 {
1037         MonoClassField *field;
1038         MonoArray *data;
1039         gint32 family;
1040         int len;
1041
1042         /* Dig the SocketAddress data buffer out of the object */
1043         field=mono_class_get_field_from_name(saddr_obj->vtable->klass, "data");
1044         data=*(MonoArray **)(((char *)saddr_obj) + field->offset);
1045
1046         /* The data buffer is laid out as follows:
1047          * byte 0 is the address family low byte
1048          * byte 1 is the address family high byte
1049          * INET:
1050          *      bytes 2 and 3 are the port info
1051          *      the rest is the address info
1052          * UNIX:
1053          *      the rest is the file name
1054          */
1055         len = mono_array_length (data);
1056         if (len < 2) {
1057                 mono_raise_exception (mono_exception_from_name(mono_get_corlib (), "System", "SystemException"));
1058         }
1059         
1060         family = convert_family (mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8));
1061         if (family == AF_INET) {
1062                 struct sockaddr_in *sa;
1063                 guint16 port;
1064                 guint32 address;
1065                 
1066                 if (len < 8) {
1067                         mono_raise_exception (mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
1068                 }
1069
1070                 sa = g_new0 (struct sockaddr_in, 1);
1071                 port = (mono_array_get (data, guint8, 2) << 8) +
1072                         mono_array_get (data, guint8, 3);
1073                 address = (mono_array_get (data, guint8, 4) << 24) +
1074                         (mono_array_get (data, guint8, 5) << 16 ) +
1075                         (mono_array_get (data, guint8, 6) << 8) +
1076                         mono_array_get (data, guint8, 7);
1077
1078                 sa->sin_family = family;
1079                 sa->sin_addr.s_addr = htonl (address);
1080                 sa->sin_port = htons (port);
1081
1082                 *sa_size = sizeof(struct sockaddr_in);
1083                 return((struct sockaddr *)sa);
1084         } else if (family == AF_INET6) {
1085                 struct sockaddr_in6 *sa;
1086                 int i;
1087                 guint16 port;
1088                 guint32 scopeid;
1089                 
1090                 if (len < 28) {
1091                         mono_raise_exception (mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
1092                 }
1093
1094                 sa = g_new0 (struct sockaddr_in6, 1);
1095                 port = mono_array_get (data, guint8, 3) +
1096                         (mono_array_get (data, guint8, 2) << 8);
1097                 scopeid = mono_array_get (data, guint8, 24) + 
1098                         (mono_array_get (data, guint8, 25) << 8) + 
1099                         (mono_array_get (data, guint8, 26) << 16) + 
1100                         (mono_array_get (data, guint8, 27) << 24);
1101
1102                 sa->sin6_family = family;
1103                 sa->sin6_port = htons (port);
1104                 sa->sin6_scope_id = scopeid;
1105
1106                 for(i=0; i<16; i++) {
1107                         sa->sin6_addr.s6_addr[i] = mono_array_get (data, guint8, 8+i);
1108                 }
1109
1110                 *sa_size = sizeof(struct sockaddr_in6);
1111                 return((struct sockaddr *)sa);
1112         }
1113 #ifdef HAVE_SYS_UN_H
1114         else if (family == AF_UNIX) {
1115                 struct sockaddr_un *sock_un;
1116                 int i;
1117
1118                 /* Need a byte for the '\0' terminator/prefix, and the first
1119                  * two bytes hold the SocketAddress family
1120                  */
1121                 if (len - 2 >= sizeof(sock_un->sun_path)) {
1122                         mono_raise_exception (mono_get_exception_index_out_of_range ());
1123                 }
1124                 
1125                 sock_un = g_new0 (struct sockaddr_un, 1);
1126
1127                 sock_un->sun_family = family;
1128                 for (i = 0; i < len - 2; i++) {
1129                         sock_un->sun_path [i] = mono_array_get (data, guint8,
1130                                                                 i + 2);
1131                 }
1132                 
1133                 *sa_size = len;
1134
1135                 return (struct sockaddr *)sock_un;
1136         }
1137 #endif
1138         else {
1139                 *error = WSAEAFNOSUPPORT;
1140                 return(0);
1141         }
1142 }
1143
1144 void
1145 ves_icall_System_Net_Sockets_Socket_Bind_internal (SOCKET sock, MonoObject *sockaddr, gint32 *error)
1146 {
1147         struct sockaddr *sa;
1148         socklen_t sa_size;
1149         int ret;
1150         
1151         *error = 0;
1152         
1153         sa=create_sockaddr_from_object(sockaddr, &sa_size, error);
1154         if (*error != 0) {
1155                 return;
1156         }
1157
1158         LOGDEBUG (g_message("%s: binding to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
1159
1160         ret = _wapi_bind (sock, sa, sa_size);
1161
1162         if(ret==SOCKET_ERROR) {
1163                 *error = WSAGetLastError ();
1164         }
1165
1166         g_free(sa);
1167 }
1168
1169 enum {
1170         SelectModeRead,
1171         SelectModeWrite,
1172         SelectModeError
1173 };
1174
1175 MonoBoolean
1176 ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode,
1177                                                    gint timeout, gint32 *error)
1178 {
1179         MonoInternalThread *thread = mono_thread_internal_current ();
1180         mono_pollfd *pfds;
1181         int ret;
1182         gboolean interrupted;
1183         time_t start;
1184
1185         *error = 0;
1186
1187         pfds = g_new0 (mono_pollfd, 1);
1188         pfds->fd = GPOINTER_TO_INT (sock);
1189
1190         switch (mode) {
1191         case SelectModeRead:  pfds->events = MONO_POLLIN; break;
1192         case SelectModeWrite: pfds->events = MONO_POLLOUT; break;
1193         default:              pfds->events = MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL; break;
1194         }
1195
1196         timeout = (timeout >= 0) ? (timeout / 1000) : -1;
1197         start = time (NULL);
1198
1199         do {
1200                 mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1201                 if (interrupted) {
1202                         g_free (pfds);
1203                         *error = WSAEINTR;
1204                         return FALSE;
1205                 }
1206
1207                 MONO_PREPARE_BLOCKING;
1208
1209                 ret = mono_poll (pfds, 1, timeout);
1210
1211                 MONO_FINISH_BLOCKING;
1212
1213                 mono_thread_info_uninstall_interrupt (&interrupted);
1214                 if (interrupted) {
1215                         g_free (pfds);
1216                         *error = WSAEINTR;
1217                         return FALSE;
1218                 }
1219
1220                 if (timeout > 0 && ret < 0) {
1221                         int err = errno;
1222                         int sec = time (NULL) - start;
1223                         
1224                         timeout -= sec * 1000;
1225                         if (timeout < 0) {
1226                                 timeout = 0;
1227                         }
1228                         
1229                         errno = err;
1230                 }
1231
1232                 if (ret == -1 && errno == EINTR) {
1233                         if (mono_thread_test_state (thread, ThreadState_AbortRequested | ThreadState_StopRequested)) {
1234                                 g_free (pfds);
1235                                 return FALSE;
1236                         }
1237
1238                         /* Suspend requested? */
1239                         mono_thread_interruption_checkpoint ();
1240
1241                         errno = EINTR;
1242                 }
1243         } while (ret == -1 && errno == EINTR);
1244
1245         if (ret == -1) {
1246 #ifdef HOST_WIN32
1247                 *error = WSAGetLastError ();
1248 #else
1249                 *error = errno_to_WSA (errno, __func__);
1250 #endif
1251                 g_free (pfds);
1252                 return FALSE;
1253         }
1254
1255         g_free (pfds);
1256         return ret != 0;
1257 }
1258
1259 void
1260 ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *sockaddr, gint32 *error)
1261 {
1262         struct sockaddr *sa;
1263         socklen_t sa_size;
1264         int ret;
1265         gboolean interrupted;
1266
1267         *error = 0;
1268
1269         sa = create_sockaddr_from_object(sockaddr, &sa_size, error);
1270         if (*error != 0)
1271                 return;
1272
1273         LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port)));
1274
1275         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1276         if (interrupted) {
1277                 *error = WSAEINTR;
1278                 return;
1279         }
1280
1281         MONO_PREPARE_BLOCKING;
1282
1283         ret = _wapi_connect (sock, sa, sa_size);
1284
1285         MONO_FINISH_BLOCKING;
1286
1287         mono_thread_info_uninstall_interrupt (&interrupted);
1288         if (interrupted) {
1289                 *error = WSAEINTR;
1290                 return;
1291         }
1292
1293         if (ret == SOCKET_ERROR)
1294                 *error = WSAGetLastError ();
1295
1296         g_free(sa);
1297 }
1298
1299 /* These #defines from mswsock.h from wine.  Defining them here allows
1300  * us to build this file on a mingw box that doesn't know the magic
1301  * numbers, but still run on a newer windows box that does.
1302  */
1303 #ifndef WSAID_DISCONNECTEX
1304 #define WSAID_DISCONNECTEX {0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}
1305 typedef BOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET, LPOVERLAPPED, DWORD, DWORD);
1306 #endif
1307
1308 #ifndef WSAID_TRANSMITFILE
1309 #define WSAID_TRANSMITFILE {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
1310 typedef BOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET, HANDLE, DWORD, DWORD, LPOVERLAPPED, LPTRANSMIT_FILE_BUFFERS, DWORD);
1311 #endif
1312
1313 void
1314 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolean reuse, gint32 *error)
1315 {
1316         int ret;
1317         glong output_bytes = 0;
1318         GUID disco_guid = WSAID_DISCONNECTEX;
1319         GUID trans_guid = WSAID_TRANSMITFILE;
1320         LPFN_DISCONNECTEX _wapi_disconnectex = NULL;
1321         LPFN_TRANSMITFILE _wapi_transmitfile = NULL;
1322         gboolean interrupted;
1323
1324         *error = 0;
1325
1326         LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__, sock, reuse));
1327
1328         MONO_PREPARE_BLOCKING;
1329
1330         /* I _think_ the extension function pointers need to be looked
1331          * up for each socket.  FIXME: check the best way to store
1332          * pointers to functions in managed objects that still works
1333          * on 64bit platforms.
1334          */
1335         ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (void *)&disco_guid, sizeof(GUID),
1336                         (void *)&_wapi_disconnectex, sizeof(void *), &output_bytes, NULL, NULL);
1337
1338         MONO_FINISH_BLOCKING;
1339
1340         if (ret != 0) {
1341                 /* make sure that WSAIoctl didn't put crap in the
1342                  * output pointer
1343                  */
1344                 _wapi_disconnectex = NULL;
1345
1346                 MONO_PREPARE_BLOCKING;
1347
1348                 /*
1349                  * Use the SIO_GET_EXTENSION_FUNCTION_POINTER to
1350                  * determine the address of the disconnect method without
1351                  * taking a hard dependency on a single provider
1352                  * 
1353                  * For an explanation of why this is done, you can read
1354                  * the article at http://www.codeproject.com/internet/jbsocketserver3.asp
1355                  */
1356                 ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, (void *)&trans_guid, sizeof(GUID),
1357                                 (void *)&_wapi_transmitfile, sizeof(void *), &output_bytes, NULL, NULL);
1358
1359                 MONO_FINISH_BLOCKING;
1360
1361                 if (ret != 0)
1362                         _wapi_transmitfile = NULL;
1363         }
1364
1365         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1366         if (interrupted) {
1367                 *error = WSAEINTR;
1368                 return;
1369         }
1370
1371         MONO_PREPARE_BLOCKING;
1372
1373         if (_wapi_disconnectex != NULL) {
1374                 if (!_wapi_disconnectex (sock, NULL, TF_REUSE_SOCKET, 0))
1375                         *error = WSAGetLastError ();
1376         } else if (_wapi_transmitfile != NULL) {
1377                 if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | TF_REUSE_SOCKET))
1378                         *error = WSAGetLastError ();
1379         } else {
1380                 *error = ERROR_NOT_SUPPORTED;
1381         }
1382
1383         MONO_FINISH_BLOCKING;
1384
1385         mono_thread_info_uninstall_interrupt (&interrupted);
1386         if (interrupted)
1387                 *error = WSAEINTR;
1388 }
1389
1390 gint32
1391 ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error)
1392 {
1393         int ret;
1394         guchar *buf;
1395         gint32 alen;
1396         int recvflags=0;
1397         gboolean interrupted;
1398         MonoInternalThread* curthread G_GNUC_UNUSED = mono_thread_internal_current ();
1399         
1400         *error = 0;
1401         
1402         alen = mono_array_length (buffer);
1403         if (offset > alen - count) {
1404                 return(0);
1405         }
1406         
1407         buf=mono_array_addr(buffer, guchar, offset);
1408         
1409         recvflags = convert_socketflags (flags);
1410         if (recvflags == -1) {
1411                 *error = WSAEOPNOTSUPP;
1412                 return (0);
1413         }
1414
1415         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1416         if (interrupted)
1417                 return 0;
1418
1419         MONO_PREPARE_BLOCKING;
1420
1421 #ifdef HOST_WIN32
1422         {
1423                 curthread->interrupt_on_stop = (gpointer)TRUE;
1424                 ret = _wapi_recv (sock, buf, count, recvflags);
1425                 curthread->interrupt_on_stop = (gpointer)FALSE;
1426         }
1427 #else
1428         ret = _wapi_recv (sock, buf, count, recvflags);
1429 #endif
1430
1431         MONO_FINISH_BLOCKING;
1432
1433         mono_thread_info_uninstall_interrupt (&interrupted);
1434         if (interrupted) {
1435                 *error = WSAEINTR;
1436                 return 0;
1437         }
1438
1439         if(ret==SOCKET_ERROR) {
1440                 *error = WSAGetLastError ();
1441                 return(0);
1442         }
1443
1444         return(ret);
1445 }
1446
1447 gint32
1448 ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error)
1449 {
1450         int ret, count;
1451         gboolean interrupted;
1452         DWORD recv;
1453         WSABUF *wsabufs;
1454         DWORD recvflags = 0;
1455         
1456         *error = 0;
1457         
1458         wsabufs = mono_array_addr (buffers, WSABUF, 0);
1459         count = mono_array_length (buffers);
1460         
1461         recvflags = convert_socketflags (flags);
1462         if (recvflags == -1) {
1463                 *error = WSAEOPNOTSUPP;
1464                 return(0);
1465         }
1466
1467         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1468         if (interrupted) {
1469                 *error = WSAEINTR;
1470                 return 0;
1471         }
1472
1473         MONO_PREPARE_BLOCKING;
1474
1475         ret = WSARecv (sock, wsabufs, count, &recv, &recvflags, NULL, NULL);
1476
1477         MONO_FINISH_BLOCKING;
1478
1479         mono_thread_info_uninstall_interrupt (&interrupted);
1480         if (interrupted) {
1481                 *error = WSAEINTR;
1482                 return 0;
1483         }
1484
1485         if (ret == SOCKET_ERROR) {
1486                 *error = WSAGetLastError ();
1487                 return 0;
1488         }
1489
1490         return recv;
1491 }
1492
1493 gint32
1494 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr, gint32 *error)
1495 {
1496         int ret;
1497         guchar *buf;
1498         gint32 alen;
1499         int recvflags=0;
1500         struct sockaddr *sa;
1501         socklen_t sa_size;
1502         gboolean interrupted;
1503         
1504         *error = 0;
1505         
1506         alen = mono_array_length (buffer);
1507         if (offset > alen - count) {
1508                 return(0);
1509         }
1510
1511         sa=create_sockaddr_from_object(*sockaddr, &sa_size, error);
1512         if (*error != 0) {
1513                 return(0);
1514         }
1515         
1516         buf=mono_array_addr(buffer, guchar, offset);
1517         
1518         recvflags = convert_socketflags (flags);
1519         if (recvflags == -1) {
1520                 *error = WSAEOPNOTSUPP;
1521                 return (0);
1522         }
1523
1524         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1525         if (interrupted) {
1526                 g_free(sa);
1527                 *error = WSAEINTR;
1528                 return 0;
1529         }
1530
1531         MONO_PREPARE_BLOCKING;
1532
1533         ret = _wapi_recvfrom (sock, buf, count, recvflags, sa, &sa_size);
1534
1535         MONO_FINISH_BLOCKING;
1536
1537         mono_thread_info_uninstall_interrupt (&interrupted);
1538         if (interrupted) {
1539                 g_free(sa);
1540                 *error = WSAEINTR;
1541                 return 0;
1542         }
1543
1544         if(ret==SOCKET_ERROR) {
1545                 g_free(sa);
1546                 *error = WSAGetLastError ();
1547                 return(0);
1548         }
1549
1550         /* If we didn't get a socket size, then we're probably a
1551          * connected connection-oriented socket and the stack hasn't
1552          * returned the remote address. All we can do is return null.
1553          */
1554         if ( sa_size != 0 )
1555                 *sockaddr=create_object_from_sockaddr(sa, sa_size, error);
1556         else
1557                 *sockaddr=NULL;
1558
1559         g_free(sa);
1560         
1561         return(ret);
1562 }
1563
1564 gint32
1565 ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error)
1566 {
1567         int ret;
1568         guchar *buf;
1569         gint32 alen;
1570         int sendflags=0;
1571         gboolean interrupted;
1572         
1573         *error = 0;
1574         
1575         alen = mono_array_length (buffer);
1576         if (offset > alen - count) {
1577                 return(0);
1578         }
1579
1580         LOGDEBUG (g_message("%s: alen: %d", __func__, alen));
1581         
1582         buf=mono_array_addr(buffer, guchar, offset);
1583
1584         LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
1585
1586         sendflags = convert_socketflags (flags);
1587         if (sendflags == -1) {
1588                 *error = WSAEOPNOTSUPP;
1589                 return (0);
1590         }
1591
1592         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1593         if (interrupted) {
1594                 *error = WSAEINTR;
1595                 return 0;
1596         }
1597
1598         MONO_PREPARE_BLOCKING;
1599
1600         ret = _wapi_send (sock, buf, count, sendflags);
1601
1602         MONO_FINISH_BLOCKING;
1603
1604         mono_thread_info_uninstall_interrupt (&interrupted);
1605         if (interrupted) {
1606                 *error = WSAEINTR;
1607                 return 0;
1608         }
1609
1610         if(ret==SOCKET_ERROR) {
1611                 *error = WSAGetLastError ();
1612                 return(0);
1613         }
1614
1615         return(ret);
1616 }
1617
1618 gint32
1619 ves_icall_System_Net_Sockets_Socket_Send_array_internal(SOCKET sock, MonoArray *buffers, gint32 flags, gint32 *error)
1620 {
1621         int ret, count;
1622         DWORD sent;
1623         WSABUF *wsabufs;
1624         DWORD sendflags = 0;
1625         gboolean interrupted;
1626         
1627         *error = 0;
1628         
1629         wsabufs = mono_array_addr (buffers, WSABUF, 0);
1630         count = mono_array_length (buffers);
1631         
1632         sendflags = convert_socketflags (flags);
1633         if (sendflags == -1) {
1634                 *error = WSAEOPNOTSUPP;
1635                 return(0);
1636         }
1637
1638         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1639         if (interrupted) {
1640                 *error = WSAEINTR;
1641                 return 0;
1642         }
1643
1644         MONO_PREPARE_BLOCKING;
1645
1646         ret = WSASend (sock, wsabufs, count, &sent, sendflags, NULL, NULL);
1647
1648         MONO_FINISH_BLOCKING;
1649
1650         mono_thread_info_uninstall_interrupt (&interrupted);
1651         if (interrupted) {
1652                 *error = WSAEINTR;
1653                 return 0;
1654         }
1655
1656         if (ret == SOCKET_ERROR) {
1657                 *error = WSAGetLastError ();
1658                 return(0);
1659         }
1660         
1661         return(sent);
1662 }
1663
1664 gint32
1665 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr, gint32 *error)
1666 {
1667         int ret;
1668         guchar *buf;
1669         gint32 alen;
1670         int sendflags=0;
1671         struct sockaddr *sa;
1672         socklen_t sa_size;
1673         gboolean interrupted;
1674         
1675         *error = 0;
1676         
1677         alen = mono_array_length (buffer);
1678         if (offset > alen - count) {
1679                 return(0);
1680         }
1681
1682         sa=create_sockaddr_from_object(sockaddr, &sa_size, error);
1683         if(*error != 0) {
1684                 return(0);
1685         }
1686         
1687         LOGDEBUG (g_message("%s: alen: %d", __func__, alen));
1688         
1689         buf=mono_array_addr(buffer, guchar, offset);
1690
1691         LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count));
1692
1693         sendflags = convert_socketflags (flags);
1694         if (sendflags == -1) {
1695                 g_free (sa);
1696                 *error = WSAEOPNOTSUPP;
1697                 return (0);
1698         }
1699
1700         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1701         if (interrupted) {
1702                 g_free (sa);
1703                 *error = WSAEINTR;
1704                 return 0;
1705         }
1706
1707         MONO_PREPARE_BLOCKING;
1708
1709         ret = _wapi_sendto (sock, buf, count, sendflags, sa, sa_size);
1710
1711         MONO_FINISH_BLOCKING;
1712
1713         mono_thread_info_uninstall_interrupt (&interrupted);
1714         if (interrupted) {
1715                 g_free (sa);
1716                 *error = WSAEINTR;
1717                 return 0;
1718         }
1719
1720         if(ret==SOCKET_ERROR) {
1721                 *error = WSAGetLastError ();
1722         }
1723
1724         g_free(sa);
1725         
1726         return(ret);
1727 }
1728
1729 static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
1730 {
1731         MonoSafeHandle *safe_handle;
1732         MonoClassField *field;
1733         
1734         field = mono_class_get_field_from_name (sockobj->vtable->klass, "safe_handle");
1735         safe_handle = ((MonoSafeHandle*) (*(gpointer *)(((char *)sockobj)+field->offset)));
1736
1737         if (safe_handle == NULL)
1738                 return -1;
1739
1740         return (SOCKET) safe_handle->handle;
1741 }
1742
1743 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
1744 void
1745 ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray **sockets, gint32 timeout, gint32 *error)
1746 {
1747         MonoInternalThread *thread = mono_thread_internal_current ();
1748         MonoObject *obj;
1749         mono_pollfd *pfds;
1750         int nfds, idx;
1751         int ret;
1752         int i, count;
1753         int mode;
1754         MonoClass *sock_arr_class;
1755         MonoArray *socks;
1756         time_t start;
1757         uintptr_t socks_size;
1758         gboolean interrupted;
1759
1760         *error = 0;
1761         
1762         /* *sockets -> READ, null, WRITE, null, ERROR, null */
1763         count = mono_array_length (*sockets);
1764         nfds = count - 3; /* NULL separators */
1765         pfds = g_new0 (mono_pollfd, nfds);
1766         mode = idx = 0;
1767         for (i = 0; i < count; i++) {
1768                 obj = mono_array_get (*sockets, MonoObject *, i);
1769                 if (obj == NULL) {
1770                         mode++;
1771                         continue;
1772                 }
1773
1774                 if (idx >= nfds) {
1775                         /* The socket array was bogus */
1776                         g_free (pfds);
1777                         *error = WSAEFAULT;
1778                         return;
1779                 }
1780
1781                 pfds [idx].fd = Socket_to_SOCKET (obj);
1782                 pfds [idx].events = (mode == 0) ? MONO_POLLIN : (mode == 1) ? MONO_POLLOUT : POLL_ERRORS;
1783                 idx++;
1784         }
1785
1786         timeout = (timeout >= 0) ? (timeout / 1000) : -1;
1787         start = time (NULL);
1788         do {
1789                 mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
1790                 if (interrupted) {
1791                         g_free (pfds);
1792                         *error = WSAEINTR;
1793                         return;
1794                 }
1795
1796                 MONO_PREPARE_BLOCKING;
1797
1798                 ret = mono_poll (pfds, nfds, timeout);
1799
1800                 MONO_FINISH_BLOCKING;
1801
1802                 mono_thread_info_uninstall_interrupt (&interrupted);
1803                 if (interrupted) {
1804                         g_free (pfds);
1805                         *error = WSAEINTR;
1806                         return;
1807                 }
1808
1809                 if (timeout > 0 && ret < 0) {
1810                         int err = errno;
1811                         int sec = time (NULL) - start;
1812
1813                         timeout -= sec * 1000;
1814                         if (timeout < 0)
1815                                 timeout = 0;
1816                         errno = err;
1817                 }
1818
1819                 if (ret == -1 && errno == EINTR) {
1820                         if (mono_thread_test_state (thread, ThreadState_AbortRequested | ThreadState_StopRequested)) {
1821                                 g_free (pfds);
1822                                 *sockets = NULL;
1823                                 return;
1824                         }
1825
1826                         /* Suspend requested? */
1827                         mono_thread_interruption_checkpoint ();
1828
1829                         errno = EINTR;
1830                 }
1831         } while (ret == -1 && errno == EINTR);
1832         
1833         if (ret == -1) {
1834 #ifdef HOST_WIN32
1835                 *error = WSAGetLastError ();
1836 #else
1837                 *error = errno_to_WSA (errno, __func__);
1838 #endif
1839                 g_free (pfds);
1840                 return;
1841         }
1842
1843         if (ret == 0) {
1844                 g_free (pfds);
1845                 *sockets = NULL;
1846                 return;
1847         }
1848
1849         sock_arr_class= ((MonoObject *)*sockets)->vtable->klass;
1850         socks_size = ((uintptr_t)ret) + 3; /* space for the NULL delimiters */
1851         socks = mono_array_new_full (mono_domain_get (), sock_arr_class, &socks_size, NULL);
1852
1853         mode = idx = 0;
1854         for (i = 0; i < count && ret > 0; i++) {
1855                 mono_pollfd *pfd;
1856
1857                 obj = mono_array_get (*sockets, MonoObject *, i);
1858                 if (obj == NULL) {
1859                         mode++;
1860                         idx++;
1861                         continue;
1862                 }
1863
1864                 pfd = &pfds [i - mode];
1865                 if (pfd->revents == 0)
1866                         continue;
1867
1868                 ret--;
1869                 if (mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
1870                         mono_array_setref (socks, idx++, obj);
1871                 } else if (mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
1872                         mono_array_setref (socks, idx++, obj);
1873                 } else if ((pfd->revents & POLL_ERRORS) != 0) {
1874                         mono_array_setref (socks, idx++, obj);
1875                 }
1876         }
1877
1878         *sockets = socks;
1879         g_free (pfds);
1880 }
1881
1882 static MonoObject* int_to_object (MonoDomain *domain, int val)
1883 {
1884         return mono_value_box (domain, mono_get_int32_class (), &val);
1885 }
1886
1887
1888 void
1889 ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val, gint32 *error)
1890 {
1891         int system_level = 0;
1892         int system_name = 0;
1893         int ret;
1894         int val;
1895         socklen_t valsize=sizeof(val);
1896         struct linger linger;
1897         socklen_t lingersize=sizeof(linger);
1898         int time_ms = 0;
1899         socklen_t time_ms_size = sizeof (time_ms);
1900 #ifdef SO_PEERCRED
1901 #  if defined(__OpenBSD__)
1902         struct sockpeercred cred;
1903 #  else
1904         struct ucred cred;
1905 #  endif
1906         socklen_t credsize = sizeof(cred);
1907 #endif
1908         MonoDomain *domain=mono_domain_get();
1909         MonoObject *obj;
1910         MonoClass *obj_class;
1911         MonoClassField *field;
1912         
1913         *error = 0;
1914         
1915 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1916         if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
1917                 system_level = SOL_SOCKET;
1918                 system_name = SO_REUSEADDR;
1919                 ret = 0;
1920         } else
1921 #endif
1922         {
1923
1924                 ret = convert_sockopt_level_and_name (level, name, &system_level, &system_name);
1925         }
1926
1927         if(ret==-1) {
1928                 *error = WSAENOPROTOOPT;
1929                 return;
1930         }
1931         if (ret == -2) {
1932                 *obj_val = int_to_object (domain, 0);
1933                 return;
1934         }
1935
1936         MONO_PREPARE_BLOCKING;
1937
1938         /* No need to deal with MulticastOption names here, because
1939          * you cant getsockopt AddMembership or DropMembership (the
1940          * int getsockopt will error, causing an exception)
1941          */
1942         switch(name) {
1943         case SocketOptionName_Linger:
1944         case SocketOptionName_DontLinger:
1945                 ret = _wapi_getsockopt(sock, system_level, system_name, &linger, &lingersize);
1946                 break;
1947                 
1948         case SocketOptionName_SendTimeout:
1949         case SocketOptionName_ReceiveTimeout:
1950                 ret = _wapi_getsockopt (sock, system_level, system_name, (char *) &time_ms, &time_ms_size);
1951                 break;
1952
1953 #ifdef SO_PEERCRED
1954         case SocketOptionName_PeerCred: 
1955                 ret = _wapi_getsockopt (sock, system_level, system_name, &cred, &credsize);
1956                 break;
1957 #endif
1958
1959         default:
1960                 ret = _wapi_getsockopt (sock, system_level, system_name, &val, &valsize);
1961         }
1962
1963         MONO_FINISH_BLOCKING;
1964
1965         if(ret==SOCKET_ERROR) {
1966                 *error = WSAGetLastError ();
1967                 return;
1968         }
1969         
1970         switch(name) {
1971         case SocketOptionName_Linger:
1972                 /* build a System.Net.Sockets.LingerOption */
1973                 obj_class=mono_class_from_name(get_socket_assembly (),
1974                                                "System.Net.Sockets",
1975                                                "LingerOption");
1976                 obj=mono_object_new(domain, obj_class);
1977                 
1978                 /* Locate and set the fields "bool enabled" and "int
1979                  * seconds"
1980                  */
1981                 field=mono_class_get_field_from_name(obj_class, "enabled");
1982                 *(guint8 *)(((char *)obj)+field->offset)=linger.l_onoff;
1983
1984                 field=mono_class_get_field_from_name(obj_class, "seconds");
1985                 *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
1986                 
1987                 break;
1988                 
1989         case SocketOptionName_DontLinger:
1990                 /* construct a bool int in val - true if linger is off */
1991                 obj = int_to_object (domain, !linger.l_onoff);
1992                 break;
1993                 
1994         case SocketOptionName_SendTimeout:
1995         case SocketOptionName_ReceiveTimeout:
1996                 obj = int_to_object (domain, time_ms);
1997                 break;
1998
1999 #ifdef SO_PEERCRED
2000         case SocketOptionName_PeerCred: 
2001         {
2002                 /* build a Mono.Posix.PeerCred+PeerCredData if
2003                  * possible
2004                  */
2005                 static MonoImage *mono_posix_image = NULL;
2006                 MonoPeerCredData *cred_data;
2007                 
2008                 if (mono_posix_image == NULL) {
2009                         mono_posix_image=mono_image_loaded ("Mono.Posix");
2010                         if (!mono_posix_image) {
2011                                 MonoAssembly *sa = mono_assembly_open ("Mono.Posix.dll", NULL);
2012                                 if (!sa) {
2013                                         *error = WSAENOPROTOOPT;
2014                                         return;
2015                                 } else {
2016                                         mono_posix_image = mono_assembly_get_image (sa);
2017                                 }
2018                         }
2019                 }
2020                 
2021                 obj_class = mono_class_from_name(mono_posix_image,
2022                                                  "Mono.Posix",
2023                                                  "PeerCredData");
2024                 obj = mono_object_new(domain, obj_class);
2025                 cred_data = (MonoPeerCredData *)obj;
2026                 cred_data->pid = cred.pid;
2027                 cred_data->uid = cred.uid;
2028                 cred_data->gid = cred.gid;
2029                 break;
2030         }
2031 #endif
2032
2033         default:
2034 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2035                 if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse)
2036                         val = val ? 0 : 1;
2037 #endif
2038                 obj = int_to_object (domain, val);
2039         }
2040         *obj_val=obj;
2041 }
2042
2043 void
2044 ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val, gint32 *error)
2045 {
2046         int system_level = 0;
2047         int system_name = 0;
2048         int ret;
2049         guchar *buf;
2050         socklen_t valsize;
2051         
2052         *error = 0;
2053         
2054         ret=convert_sockopt_level_and_name(level, name, &system_level,
2055                                            &system_name);
2056         if(ret==-1) {
2057                 *error = WSAENOPROTOOPT;
2058                 return;
2059         }
2060         if(ret==-2)
2061                 return;
2062
2063         valsize=mono_array_length(*byte_val);
2064         buf=mono_array_addr(*byte_val, guchar, 0);
2065
2066         MONO_PREPARE_BLOCKING;
2067
2068         ret = _wapi_getsockopt (sock, system_level, system_name, buf, &valsize);
2069
2070         MONO_FINISH_BLOCKING;
2071
2072         if(ret==SOCKET_ERROR) {
2073                 *error = WSAGetLastError ();
2074         }
2075 }
2076
2077 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2078 static struct in_addr ipaddress_to_struct_in_addr(MonoObject *ipaddr)
2079 {
2080         struct in_addr inaddr;
2081         MonoClassField *field;
2082         
2083         field=mono_class_get_field_from_name(ipaddr->vtable->klass, "m_Address");
2084
2085         /* No idea why .net uses a 64bit type to hold a 32bit value...
2086          *
2087          * Internal value of IPAddess is in little-endian order
2088          */
2089         inaddr.s_addr=GUINT_FROM_LE ((guint32)*(guint64 *)(((char *)ipaddr)+field->offset));
2090         
2091         return(inaddr);
2092 }
2093
2094 static struct in6_addr ipaddress_to_struct_in6_addr(MonoObject *ipaddr)
2095 {
2096         struct in6_addr in6addr;
2097         MonoClassField *field;
2098         MonoArray *data;
2099         int i;
2100
2101         field=mono_class_get_field_from_name(ipaddr->vtable->klass, "m_Numbers");
2102         data=*(MonoArray **)(((char *)ipaddr) + field->offset);
2103
2104 /* Solaris has only the 8 bit version. */
2105 #ifndef s6_addr16
2106         for(i=0; i<8; i++) {
2107                 guint16 s = mono_array_get (data, guint16, i);
2108                 in6addr.s6_addr[2 * i + 1] = (s >> 8) & 0xff;
2109                 in6addr.s6_addr[2 * i] = s & 0xff;
2110         }
2111 #else
2112         for(i=0; i<8; i++)
2113                 in6addr.s6_addr16[i] = mono_array_get (data, guint16, i);
2114 #endif
2115         return(in6addr);
2116 }
2117 #endif
2118
2119 #if defined(__APPLE__) || defined(__FreeBSD__)
2120
2121 static int
2122 get_local_interface_id (int family)
2123 {
2124 #if !defined(HAVE_GETIFADDRS) || !defined(HAVE_IF_NAMETOINDEX)
2125         return 0;
2126 #else
2127         struct ifaddrs *ifap = NULL, *ptr;
2128         int idx = 0;
2129         
2130         if (getifaddrs (&ifap)) {
2131                 return 0;
2132         }
2133         
2134         for (ptr = ifap; ptr; ptr = ptr->ifa_next) {
2135                 if (!ptr->ifa_addr || !ptr->ifa_name)
2136                         continue;
2137                 if (ptr->ifa_addr->sa_family != family)
2138                         continue;
2139                 if ((ptr->ifa_flags & IFF_LOOPBACK) != 0)
2140                         continue;
2141                 if ((ptr->ifa_flags & IFF_MULTICAST) == 0)
2142                         continue;
2143                         
2144                 idx = if_nametoindex (ptr->ifa_name);
2145                 break;
2146         }
2147         
2148         freeifaddrs (ifap);
2149         return idx;
2150 #endif
2151 }
2152
2153 #endif /* defined(__APPLE__) || defined(__FreeBSD__) */
2154
2155 void
2156 ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val, gint32 *error)
2157 {
2158         struct linger linger;
2159         int system_level = 0;
2160         int system_name = 0;
2161         int ret;
2162         int sol_ip;
2163         int sol_ipv6;
2164
2165         *error = 0;
2166
2167         sol_ipv6 = mono_networking_get_ipv6_protocol ();
2168         sol_ip = mono_networking_get_ip_protocol ();
2169
2170         ret=convert_sockopt_level_and_name(level, name, &system_level,
2171                                            &system_name);
2172
2173 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2174         if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) {
2175                 system_name = SO_REUSEADDR;
2176                 int_val = int_val ? 0 : 1;
2177                 ret = 0;
2178         }
2179 #endif
2180
2181         if(ret==-1) {
2182                 *error = WSAENOPROTOOPT;
2183                 return;
2184         }
2185         if(ret==-2){
2186                 return;
2187         }
2188
2189         /* Only one of obj_val, byte_val or int_val has data */
2190         if(obj_val!=NULL) {
2191                 MonoClassField *field;
2192                 int valsize;
2193                 
2194                 switch(name) {
2195                 case SocketOptionName_Linger:
2196                         /* Dig out "bool enabled" and "int seconds"
2197                          * fields
2198                          */
2199                         field=mono_class_get_field_from_name(obj_val->vtable->klass, "enabled");
2200                         linger.l_onoff=*(guint8 *)(((char *)obj_val)+field->offset);
2201                         field=mono_class_get_field_from_name(obj_val->vtable->klass, "seconds");
2202                         linger.l_linger=*(guint32 *)(((char *)obj_val)+field->offset);
2203                         
2204                         valsize=sizeof(linger);
2205                         ret = _wapi_setsockopt (sock, system_level,
2206                                                 system_name, &linger, valsize);
2207                         break;
2208                 case SocketOptionName_AddMembership:
2209                 case SocketOptionName_DropMembership:
2210 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2211                 {
2212                         MonoObject *address = NULL;
2213
2214                         if(system_level == sol_ipv6) {
2215                                 struct ipv6_mreq mreq6;
2216
2217                                 /*
2218                                  *      Get group address
2219                                  */
2220                                 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
2221                                 address = *(gpointer *)(((char *)obj_val) + field->offset);
2222                                 
2223                                 if(address) {
2224                                         mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
2225                                 }
2226
2227                                 field=mono_class_get_field_from_name(obj_val->vtable->klass, "ifIndex");
2228                                 mreq6.ipv6mr_interface =*(guint64 *)(((char *)obj_val)+field->offset);
2229                                 
2230 #if defined(__APPLE__) || defined(__FreeBSD__)
2231                                 /*
2232                                 * Bug #5504:
2233                                 *
2234                                 * Mac OS Lion doesn't allow ipv6mr_interface = 0.
2235                                 *
2236                                 * Tests on Windows and Linux show that the multicast group is only
2237                                 * joined on one NIC when interface = 0, so we simply use the interface
2238                                 * id from the first non-loopback interface (this is also what
2239                                 * Dns.GetHostName (string.Empty) would return).
2240                                 */
2241                                 if (!mreq6.ipv6mr_interface)
2242                                         mreq6.ipv6mr_interface = get_local_interface_id (AF_INET6);
2243 #endif
2244                                         
2245                                 ret = _wapi_setsockopt (sock, system_level,
2246                                                         system_name, &mreq6,
2247                                                         sizeof (mreq6));
2248                         } else if(system_level == sol_ip) {
2249 #ifdef HAVE_STRUCT_IP_MREQN
2250                                 struct ip_mreqn mreq = {{0}};
2251 #else
2252                                 struct ip_mreq mreq = {{0}};
2253 #endif /* HAVE_STRUCT_IP_MREQN */
2254                         
2255                                 /* pain! MulticastOption holds two IPAddress
2256                                  * members, so I have to dig the value out of
2257                                  * those :-(
2258                                  */
2259                                 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
2260                                 address = *(gpointer *)(((char *)obj_val) + field->offset);
2261
2262                                 /* address might not be defined and if so, set the address to ADDR_ANY.
2263                                  */
2264                                 if(address) {
2265                                         mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
2266                                 }
2267
2268                                 field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
2269                                 address = *(gpointer *)(((char *)obj_val) + field->offset);
2270
2271 #ifdef HAVE_STRUCT_IP_MREQN
2272                                 if(address) {
2273                                         mreq.imr_address = ipaddress_to_struct_in_addr (address);
2274                                 }
2275
2276                                 field = mono_class_get_field_from_name(obj_val->vtable->klass, "iface_index");
2277                                 mreq.imr_ifindex = *(gint32 *)(((char *)obj_val)+field->offset);
2278 #else
2279                                 if(address) {
2280                                         mreq.imr_interface = ipaddress_to_struct_in_addr (address);
2281                                 }
2282 #endif /* HAVE_STRUCT_IP_MREQN */
2283
2284                                 ret = _wapi_setsockopt (sock, system_level,
2285                                                         system_name, &mreq,
2286                                                         sizeof (mreq));
2287                         }
2288                         break;
2289                 }
2290 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
2291                 default:
2292                         /* Cause an exception to be thrown */
2293                         *error = WSAEINVAL;
2294                         return;
2295                 }
2296         } else if (byte_val!=NULL) {
2297                 int valsize = mono_array_length (byte_val);
2298                 guchar *buf = mono_array_addr (byte_val, guchar, 0);
2299                 
2300                 switch(name) {
2301                 case SocketOptionName_DontLinger:
2302                         if (valsize == 1) {
2303                                 linger.l_onoff = (*buf) ? 0 : 1;
2304                                 linger.l_linger = 0;
2305                                 ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
2306                         } else {
2307                                 *error = WSAEINVAL;
2308                         }
2309                         break;
2310                 default:
2311                         ret = _wapi_setsockopt (sock, system_level, system_name, buf, valsize);
2312                         break;
2313                 }
2314         } else {
2315                 /* ReceiveTimeout/SendTimeout get here */
2316                 switch(name) {
2317                 case SocketOptionName_DontLinger:
2318                         linger.l_onoff = !int_val;
2319                         linger.l_linger = 0;
2320                         ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
2321                         break;
2322                 case SocketOptionName_MulticastInterface:
2323 #ifndef HOST_WIN32
2324 #ifdef HAVE_STRUCT_IP_MREQN
2325                         int_val = GUINT32_FROM_BE (int_val);
2326                         if ((int_val & 0xff000000) == 0) {
2327                                 /* int_val is interface index */
2328                                 struct ip_mreqn mreq = {{0}};
2329                                 mreq.imr_ifindex = int_val;
2330                                 ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &mreq, sizeof (mreq));
2331                                 break;
2332                         }
2333                         int_val = GUINT32_TO_BE (int_val);
2334 #endif /* HAVE_STRUCT_IP_MREQN */
2335 #endif /* HOST_WIN32 */
2336                         /* int_val is in_addr */
2337                         ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
2338                         break;
2339                 case SocketOptionName_DontFragment:
2340 #ifdef HAVE_IP_MTU_DISCOVER
2341                         /* Fiddle with the value slightly if we're
2342                          * turning DF on
2343                          */
2344                         if (int_val == 1) {
2345                                 int_val = IP_PMTUDISC_DO;
2346                         }
2347                         /* Fall through */
2348 #endif
2349                         
2350                 default:
2351                         ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
2352                 }
2353         }
2354
2355         if(ret==SOCKET_ERROR) {
2356                 *error = WSAGetLastError ();
2357         }
2358 }
2359
2360 void
2361 ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock, gint32 how, gint32 *error)
2362 {
2363         int ret;
2364         gboolean interrupted;
2365
2366         *error = 0;
2367
2368         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
2369         if (interrupted) {
2370                 *error = WSAEINTR;
2371                 return;
2372         }
2373
2374         MONO_PREPARE_BLOCKING;
2375
2376         /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
2377         ret = _wapi_shutdown (sock, how);
2378
2379         MONO_FINISH_BLOCKING;
2380
2381         mono_thread_info_uninstall_interrupt (&interrupted);
2382         if (interrupted) {
2383                 *error = WSAEINTR;
2384                 return;
2385         }
2386
2387         if (ret == SOCKET_ERROR)
2388                 *error = WSAGetLastError ();
2389 }
2390
2391 gint
2392 ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock, gint32 code, MonoArray *input, MonoArray *output, gint32 *error)
2393 {
2394         glong output_bytes = 0;
2395         gchar *i_buffer, *o_buffer;
2396         gint i_len, o_len;
2397         gint ret;
2398
2399         *error = 0;
2400         
2401         if ((guint32)code == FIONBIO) {
2402                 /* Invalid command. Must use Socket.Blocking */
2403                 return -1;
2404         }
2405
2406         if (input == NULL) {
2407                 i_buffer = NULL;
2408                 i_len = 0;
2409         } else {
2410                 i_buffer = mono_array_addr (input, gchar, 0);
2411                 i_len = mono_array_length (input);
2412         }
2413
2414         if (output == NULL) {
2415                 o_buffer = NULL;
2416                 o_len = 0;
2417         } else {
2418                 o_buffer = mono_array_addr (output, gchar, 0);
2419                 o_len = mono_array_length (output);
2420         }
2421
2422         MONO_PREPARE_BLOCKING;
2423
2424         ret = WSAIoctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes, NULL, NULL);
2425
2426         MONO_FINISH_BLOCKING;
2427
2428         if (ret == SOCKET_ERROR) {
2429                 *error = WSAGetLastError ();
2430                 return(-1);
2431         }
2432
2433         return (gint) output_bytes;
2434 }
2435
2436 static gboolean 
2437 addrinfo_to_IPHostEntry(MonoAddressInfo *info, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list, gboolean add_local_ips)
2438 {
2439         gint32 count, i;
2440         MonoAddressEntry *ai = NULL;
2441         struct in_addr *local_in = NULL;
2442         int nlocal_in = 0;
2443         struct in6_addr *local_in6 = NULL;
2444         int nlocal_in6 = 0;
2445         int addr_index;
2446
2447         MonoDomain *domain = mono_domain_get ();
2448
2449         addr_index = 0;
2450         *h_aliases=mono_array_new(domain, mono_get_string_class (), 0);
2451         if (add_local_ips) {
2452                 local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in);
2453                 local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6);
2454                 if (nlocal_in || nlocal_in6) {
2455                         char addr [INET6_ADDRSTRLEN];
2456                         *h_addr_list=mono_array_new(domain, mono_get_string_class (), nlocal_in + nlocal_in6);
2457                         if (nlocal_in) {
2458                                 MonoString *addr_string;
2459                                 int i;
2460
2461                                 for (i = 0; i < nlocal_in; i++) {
2462                                         MonoAddress maddr;
2463                                         mono_address_init (&maddr, AF_INET, &local_in [i]);
2464                                         if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
2465                                                 addr_string = mono_string_new (domain, addr);
2466                                                 mono_array_setref (*h_addr_list, addr_index, addr_string);
2467                                                 addr_index++;
2468                                         }
2469                                 }
2470                         }
2471
2472                         if (nlocal_in6) {
2473                                 MonoString *addr_string;
2474                                 int i;
2475
2476                                 for (i = 0; i < nlocal_in6; i++) {
2477                                         MonoAddress maddr;
2478                                         mono_address_init (&maddr, AF_INET6, &local_in6 [i]);
2479                                         if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) {
2480                                                 addr_string = mono_string_new (domain, addr);
2481                                                 mono_array_setref (*h_addr_list, addr_index, addr_string);
2482                                                 addr_index++;
2483                                         }
2484                                 }
2485                         }
2486
2487                         g_free (local_in);
2488                         g_free (local_in6);
2489                         if (info) {
2490                                 mono_free_address_info (info);
2491                         }
2492                         return TRUE;
2493                 }
2494
2495                 g_free (local_in);
2496                 g_free (local_in6);
2497         }
2498
2499         for (count = 0, ai = info->entries; ai != NULL; ai = ai->next) {
2500                 if (ai->family != AF_INET && ai->family != AF_INET6)
2501                         continue;
2502
2503                 count++;
2504         }
2505
2506         *h_addr_list=mono_array_new(domain, mono_get_string_class (), count);
2507
2508         for (ai = info->entries, i = 0; ai != NULL; ai = ai->next) {
2509                 MonoAddress maddr;
2510                 MonoString *addr_string;
2511                 char buffer [INET6_ADDRSTRLEN]; /* Max. size for IPv6 */
2512
2513                 if((ai->family != PF_INET) && (ai->family != PF_INET6)) {
2514                         continue;
2515                 }
2516
2517                 mono_address_init (&maddr, ai->family, &ai->address);
2518                 if(mono_networking_addr_to_str (&maddr, buffer, sizeof (buffer))) {
2519                         addr_string=mono_string_new(domain, buffer);
2520                 } else {
2521                         addr_string=mono_string_new(domain, "");
2522                 }
2523
2524                 mono_array_setref (*h_addr_list, addr_index, addr_string);
2525
2526                 if(!i) {
2527                         i++;
2528                         if (ai->canonical_name != NULL) {
2529                                 *h_name=mono_string_new(domain, ai->canonical_name);
2530                         } else {
2531                                 *h_name=mono_string_new(domain, buffer);
2532                         }
2533                 }
2534
2535                 addr_index++;
2536         }
2537
2538         if(info) {
2539                 mono_free_address_info (info);
2540         }
2541
2542         return(TRUE);
2543 }
2544
2545 static int
2546 get_addrinfo_family_hint (void)
2547 {
2548         switch (get_family_hint ()) {
2549         case PF_UNSPEC: return MONO_HINT_UNSPECIFIED;
2550         case PF_INET: return MONO_HINT_IPV4;
2551 #ifdef PF_INET6
2552         case PF_INET6: return MONO_HINT_IPV6;
2553 #endif
2554         default:
2555                 g_error ("invalid hint");
2556                 return 0;
2557         }
2558 }
2559
2560 MonoBoolean
2561 ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
2562 {
2563         gboolean add_local_ips = FALSE, add_info_ok = TRUE;
2564         gchar this_hostname [256];
2565         MonoAddressInfo *info = NULL;
2566         char *hostname = mono_string_to_utf8 (host);
2567         int hint = get_addrinfo_family_hint ();
2568
2569         if (*hostname == '\0') {
2570                 add_local_ips = TRUE;
2571                 *h_name = host;
2572         }
2573
2574         if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) {
2575                 if (!strcmp (hostname, this_hostname)) {
2576                         add_local_ips = TRUE;
2577                         *h_name = host;
2578                 }
2579         }
2580
2581         if (*hostname && mono_get_address_info (hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info))
2582                 add_info_ok = FALSE;
2583
2584         g_free(hostname);
2585
2586         if (add_info_ok)
2587                 return addrinfo_to_IPHostEntry(info, h_name, h_aliases, h_addr_list, add_local_ips);
2588         return FALSE;
2589 }
2590
2591 MonoBoolean
2592 ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
2593 {
2594         char *address;
2595         struct sockaddr_in saddr;
2596         struct sockaddr_in6 saddr6;
2597         MonoAddressInfo *info = NULL;
2598         gint32 family;
2599         gchar hostname[NI_MAXHOST] = { 0 };
2600         gboolean ret;
2601
2602         address = mono_string_to_utf8 (addr);
2603
2604         if (inet_pton (AF_INET, address, &saddr.sin_addr ) == 1) {
2605                 family = AF_INET;
2606                 saddr.sin_family = AF_INET;
2607         } else if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) == 1) {
2608                 family = AF_INET6;
2609                 saddr6.sin6_family = AF_INET6;
2610         } else {
2611                 g_free (address);
2612                 return FALSE;
2613         }
2614
2615         g_free (address);
2616
2617         MONO_PREPARE_BLOCKING;
2618
2619         switch (family) {
2620         case AF_INET: {
2621 #if HAVE_SOCKADDR_IN_SIN_LEN
2622                 saddr.sin_len = sizeof (saddr);
2623 #endif
2624                 ret = getnameinfo ((struct sockaddr*)&saddr, sizeof(saddr), hostname, sizeof(hostname), NULL, 0, 0) == 0;
2625                 break;
2626         }
2627         case AF_INET6: {
2628 #if HAVE_SOCKADDR_IN6_SIN_LEN
2629                 saddr6.sin6_len = sizeof (saddr6);
2630 #endif
2631                 ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof(saddr6), hostname, sizeof(hostname), NULL, 0, 0) == 0;
2632                 break;
2633         }
2634         default:
2635                 g_assert_not_reached ();
2636         }
2637
2638         MONO_FINISH_BLOCKING;
2639
2640         if (!ret)
2641                 return FALSE;
2642
2643         if (mono_get_address_info (hostname, 0, get_addrinfo_family_hint () | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info) != 0)
2644                 return FALSE;
2645
2646         return addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list, FALSE);
2647 }
2648
2649 MonoBoolean
2650 ves_icall_System_Net_Dns_GetHostName_internal (MonoString **h_name)
2651 {
2652         gchar hostname[NI_MAXHOST] = { 0 };
2653         int ret;
2654
2655         ret = gethostname (hostname, sizeof (hostname));
2656         if (ret == -1)
2657                 return FALSE;
2658
2659         *h_name = mono_string_new(mono_domain_get (), hostname);
2660
2661         return TRUE;
2662 }
2663
2664 gboolean
2665 ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags)
2666 {
2667         HANDLE file;
2668         gint32 error;
2669         gboolean ret;
2670         gboolean interrupted;
2671         TRANSMIT_FILE_BUFFERS buffers;
2672
2673         if (filename == NULL)
2674                 return FALSE;
2675
2676         /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
2677
2678         file = ves_icall_System_IO_MonoIO_Open (filename, FileMode_Open, FileAccess_Read, FileShare_Read, 0, &error);
2679
2680         if (file == INVALID_HANDLE_VALUE) {
2681                 SetLastError (error);
2682                 return FALSE;
2683         }
2684
2685         memset (&buffers, 0, sizeof (buffers));
2686         if (pre_buffer != NULL) {
2687                 buffers.Head = mono_array_addr (pre_buffer, guchar, 0);
2688                 buffers.HeadLength = mono_array_length (pre_buffer);
2689         }
2690         if (post_buffer != NULL) {
2691                 buffers.Tail = mono_array_addr (post_buffer, guchar, 0);
2692                 buffers.TailLength = mono_array_length (post_buffer);
2693         }
2694
2695         mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
2696         if (interrupted) {
2697                 CloseHandle (file);
2698                 SetLastError (WSAEINTR);
2699                 return FALSE;
2700         }
2701
2702         MONO_PREPARE_BLOCKING;
2703
2704         ret = TransmitFile (sock, file, 0, 0, NULL, &buffers, flags);
2705
2706         MONO_FINISH_BLOCKING;
2707
2708         mono_thread_info_uninstall_interrupt (&interrupted);
2709         if (interrupted) {
2710                 CloseHandle (file);
2711                 SetLastError (WSAEINTR);
2712                 return FALSE;
2713         }
2714
2715         MONO_PREPARE_BLOCKING;
2716
2717         CloseHandle (file);
2718
2719         MONO_FINISH_BLOCKING;
2720
2721         return ret;
2722 }
2723
2724 gboolean
2725 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (void)
2726 {
2727 #if defined (SO_REUSEPORT) || defined (HOST_WIN32)
2728     return TRUE;
2729 #else
2730     return FALSE;
2731 #endif
2732 }
2733
2734 void
2735 mono_network_init(void)
2736 {
2737         mono_networking_init ();
2738 }
2739
2740 void
2741 mono_network_cleanup(void)
2742 {
2743         _wapi_cleanup_networking ();
2744         mono_networking_shutdown ();
2745 }
2746
2747 void
2748 icall_cancel_blocking_socket_operation (MonoThread *thread)
2749 {
2750         MonoInternalThread *internal;
2751
2752         internal = thread->internal_thread;
2753         g_assert (internal);
2754
2755         mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid));
2756 }
2757
2758 #endif /* #ifndef DISABLE_SOCKETS */