2 * socket-io.c: Socket IO internal calls
5 * Dick Porter (dick@ximian.com)
7 * (C) 2001 Ximian, Inc.
18 #include <mono/metadata/object.h>
19 #include <mono/io-layer/io-layer.h>
20 #include <mono/metadata/socket-io.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/appdomain.h>
29 #ifdef HAVE_SYS_FILIO_H
30 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
32 #ifdef HAVE_SYS_SOCKIO_H
33 #include <sys/sockio.h> /* defines SIOCATMARK */
40 /* This is a kludge to make this file build under cygwin:
41 * w32api/ws2tcpip.h has definitions for some AF_INET6 values and
42 * prototypes for some but not all required functions (notably
43 * inet_ntop() is missing), but the libws2_32 library is missing the
44 * actual implementations of these functions.
51 static gint32 convert_family(MonoAddressFamily mono_family)
56 case AddressFamily_Unknown:
57 case AddressFamily_ImpLink:
58 case AddressFamily_Pup:
59 case AddressFamily_Chaos:
60 case AddressFamily_Iso:
61 case AddressFamily_Ecma:
62 case AddressFamily_DataKit:
63 case AddressFamily_Ccitt:
64 case AddressFamily_DataLink:
65 case AddressFamily_Lat:
66 case AddressFamily_HyperChannel:
67 case AddressFamily_NetBios:
68 case AddressFamily_VoiceView:
69 case AddressFamily_FireFox:
70 case AddressFamily_Banyan:
71 case AddressFamily_Atm:
72 case AddressFamily_Cluster:
73 case AddressFamily_Ieee12844:
74 case AddressFamily_NetworkDesigners:
75 g_warning("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
78 case AddressFamily_Unspecified:
82 case AddressFamily_Unix:
86 case AddressFamily_InterNetwork:
91 case AddressFamily_Ipx:
96 case AddressFamily_Sna:
100 case AddressFamily_DecNet:
104 case AddressFamily_AppleTalk:
109 case AddressFamily_InterNetworkV6:
114 case AddressFamily_Irda:
119 g_warning("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
125 static MonoAddressFamily convert_to_mono_family(guint16 af_family)
127 MonoAddressFamily family=AddressFamily_Unknown;
131 family=AddressFamily_Unspecified;
135 family=AddressFamily_Unix;
139 family=AddressFamily_InterNetwork;
144 family=AddressFamily_Ipx;
149 family=AddressFamily_Sna;
153 family=AddressFamily_DecNet;
157 family=AddressFamily_AppleTalk;
162 family=AddressFamily_InterNetworkV6;
168 family=AddressFamily_Irda;
172 g_warning("unknown address family 0x%x", af_family);
178 static gint32 convert_type(MonoSocketType mono_type)
183 case SocketType_Stream:
187 case SocketType_Dgram:
199 case SocketType_Seqpacket:
203 case SocketType_Unknown:
204 g_warning("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
208 g_warning("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
214 static gint32 convert_proto(MonoProtocolType mono_proto)
219 case ProtocolType_IP:
220 case ProtocolType_IPv6:
221 case ProtocolType_Icmp:
222 case ProtocolType_Igmp:
223 case ProtocolType_Ggp:
224 case ProtocolType_Tcp:
225 case ProtocolType_Pup:
226 case ProtocolType_Udp:
227 case ProtocolType_Idp:
228 /* These protocols are known (on my system at least) */
232 case ProtocolType_ND:
233 case ProtocolType_Raw:
234 case ProtocolType_Ipx:
235 case ProtocolType_Spx:
236 case ProtocolType_SpxII:
237 case ProtocolType_Unknown:
238 /* These protocols arent */
239 g_warning("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
249 static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
250 MonoSocketOptionName mono_name,
254 switch (mono_level) {
255 case SocketOptionLevel_Socket:
256 *system_level = SOL_SOCKET;
259 case SocketOptionName_DontLinger:
260 /* This is SO_LINGER, because the setsockopt
261 * internal call maps DontLinger to SO_LINGER
264 *system_name = SO_LINGER;
266 case SocketOptionName_Debug:
267 *system_name = SO_DEBUG;
270 case SocketOptionName_AcceptConnection:
271 *system_name = SO_ACCEPTCONN;
274 case SocketOptionName_ReuseAddress:
275 *system_name = SO_REUSEADDR;
277 case SocketOptionName_KeepAlive:
278 *system_name = SO_KEEPALIVE;
280 case SocketOptionName_DontRoute:
281 *system_name = SO_DONTROUTE;
283 case SocketOptionName_Broadcast:
284 *system_name = SO_BROADCAST;
286 case SocketOptionName_Linger:
287 *system_name = SO_LINGER;
289 case SocketOptionName_OutOfBandInline:
290 *system_name = SO_OOBINLINE;
292 case SocketOptionName_SendBuffer:
293 *system_name = SO_SNDBUF;
295 case SocketOptionName_ReceiveBuffer:
296 *system_name = SO_RCVBUF;
298 case SocketOptionName_SendLowWater:
299 *system_name = SO_SNDLOWAT;
301 case SocketOptionName_ReceiveLowWater:
302 *system_name = SO_RCVLOWAT;
304 case SocketOptionName_SendTimeout:
305 *system_name = SO_SNDTIMEO;
307 case SocketOptionName_ReceiveTimeout:
308 *system_name = SO_RCVTIMEO;
310 case SocketOptionName_Error:
311 *system_name = SO_ERROR;
313 case SocketOptionName_Type:
314 *system_name = SO_TYPE;
316 case SocketOptionName_ExclusiveAddressUse:
317 case SocketOptionName_UseLoopback:
318 case SocketOptionName_MaxConnections:
319 /* Can't figure out how to map these, so fall
323 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
328 case SocketOptionLevel_IP:
330 *system_level = SOL_IP;
333 static int cached = 0;
337 struct protoent *pent;
339 pent = getprotobyname ("IP");
340 proto = pent ? pent->p_proto : 0 /* 0 a good default value?? */;
344 *system_level = proto;
346 #endif /* HAVE_SOL_IP */
349 case SocketOptionName_IPOptions:
350 *system_name = IP_OPTIONS;
353 case SocketOptionName_HeaderIncluded:
354 *system_name = IP_HDRINCL;
358 case SocketOptionName_TypeOfService:
359 *system_name = IP_TOS;
363 case SocketOptionName_IpTimeToLive:
364 *system_name = IP_TTL;
367 case SocketOptionName_MulticastInterface:
368 *system_name = IP_MULTICAST_IF;
370 case SocketOptionName_MulticastTimeToLive:
371 *system_name = IP_MULTICAST_TTL;
373 case SocketOptionName_MulticastLoopback:
374 *system_name = IP_MULTICAST_LOOP;
376 case SocketOptionName_AddMembership:
377 *system_name = IP_ADD_MEMBERSHIP;
379 case SocketOptionName_DropMembership:
380 *system_name = IP_DROP_MEMBERSHIP;
382 #ifdef HAVE_IP_PKTINFO
383 case SocketOptionName_PacketInformation:
384 *system_name = IP_PKTINFO;
386 #endif /* HAVE_IP_PKTINFO */
387 case SocketOptionName_DontFragment:
388 case SocketOptionName_AddSourceMembership:
389 case SocketOptionName_DropSourceMembership:
390 case SocketOptionName_BlockSource:
391 case SocketOptionName_UnblockSource:
392 /* Can't figure out how to map these, so fall
396 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
402 case SocketOptionLevel_IPv6:
404 *system_level = SOL_IPV6;
407 static int cached = 0;
411 struct protoent *pent;
413 pent = getprotobyname ("IPV6");
414 proto = pent ? pent->p_proto : 41 /* 41 a good default value?? */;
418 *system_level = proto;
420 #endif /* HAVE_SOL_IPV6 */
423 case SocketOptionName_IpTimeToLive:
424 *system_name = IPV6_UNICAST_HOPS;
426 case SocketOptionName_MulticastInterface:
427 *system_name = IPV6_MULTICAST_IF;
429 case SocketOptionName_MulticastTimeToLive:
430 *system_name = IPV6_MULTICAST_HOPS;
432 case SocketOptionName_MulticastLoopback:
433 *system_name = IPV6_MULTICAST_LOOP;
435 case SocketOptionName_AddMembership:
436 *system_name = IPV6_JOIN_GROUP;
438 case SocketOptionName_DropMembership:
439 *system_name = IPV6_LEAVE_GROUP;
441 case SocketOptionName_PacketInformation:
442 *system_name = IPV6_PKTINFO;
444 case SocketOptionName_HeaderIncluded:
445 case SocketOptionName_IPOptions:
446 case SocketOptionName_TypeOfService:
447 case SocketOptionName_DontFragment:
448 case SocketOptionName_AddSourceMembership:
449 case SocketOptionName_DropSourceMembership:
450 case SocketOptionName_BlockSource:
451 case SocketOptionName_UnblockSource:
452 /* Can't figure out how to map these, so fall
456 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name);
460 break; /// SocketOptionLevel_IPv6
463 case SocketOptionLevel_Tcp:
465 *system_level = SOL_TCP;
468 static int cached = 0;
472 struct protoent *pent;
474 pent = getprotobyname ("TCP");
475 proto = pent ? pent->p_proto : 6 /* is 6 a good default value?? */;
479 *system_level = proto;
481 #endif /* HAVE_SOL_TCP */
484 case SocketOptionName_NoDelay:
485 *system_name = TCP_NODELAY;
488 /* The documentation is talking complete
489 * bollocks here: rfc-1222 is titled
490 * 'Advancing the NSFNET Routing Architecture'
491 * and doesn't mention either of the words
492 * "expedite" or "urgent".
494 case SocketOptionName_BsdUrgent:
495 case SocketOptionName_Expedited:
498 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
503 case SocketOptionLevel_Udp:
504 g_warning("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
507 case SocketOptionName_NoChecksum:
508 case SocketOptionName_ChecksumCoverage:
510 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
517 g_warning("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
524 #define STASH_SYS_ASS(this) \
525 if(system_assembly == NULL) { \
526 system_assembly=mono_image_loaded ("System"); \
529 static MonoImage *system_assembly=NULL;
533 static gint32 get_family_hint(void)
535 MonoClass *socket_class;
536 MonoClassField *ipv6_field, *ipv4_field;
537 gint32 ipv6_enabled = -1, ipv4_enabled = -1;
540 socket_class = mono_class_from_name (system_assembly,
541 "System.Net.Sockets", "Socket");
542 ipv4_field = mono_class_get_field_from_name (socket_class,
544 ipv6_field = mono_class_get_field_from_name (socket_class,
546 vtable = mono_class_vtable (mono_domain_get (), socket_class);
548 mono_field_static_get_value(vtable, ipv4_field, &ipv4_enabled);
549 mono_field_static_get_value(vtable, ipv6_field, &ipv6_enabled);
551 if(ipv4_enabled == 1 && ipv6_enabled == 1) {
553 } else if(ipv4_enabled == 1) {
561 static MonoException *get_socket_exception(guint32 error_code)
563 /* Don't cache this exception, because we need the object
564 * constructor to set up the message from the sockets error code.
568 /* This is a bit of a kludge. The SocketException 0-arg
569 * constructor calls WSAGetLastError() to find the error code
570 * to use. Until we can init objects with parameters, this
573 WSASetLastError(error_code);
575 ex=(MonoException *)mono_exception_from_name(system_assembly,
576 "System.Net.Sockets",
581 gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto)
594 sock_family=convert_family(family);
595 if(sock_family==-1) {
596 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
600 sock_proto=convert_proto(proto);
602 mono_raise_exception(get_socket_exception(WSAEPROTONOSUPPORT));
606 sock_type=convert_type(type);
608 mono_raise_exception(get_socket_exception(WSAESOCKTNOSUPPORT));
612 sock=socket(sock_family, sock_type, sock_proto);
613 if(sock==INVALID_SOCKET) {
614 mono_raise_exception(get_socket_exception(WSAGetLastError()));
618 if (sock_family == AF_INET && sock_type == SOCK_DGRAM) {
619 return (GUINT_TO_POINTER (sock));
623 if (sock_family == AF_INET6 && sock_type == SOCK_DGRAM) {
624 return (GUINT_TO_POINTER (sock));
628 /* .net seems to set this by default for SOCK_STREAM,
629 * not for SOCK_DGRAM (see bug #36322)
631 ret=setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(true));
632 if(ret==SOCKET_ERROR) {
634 mono_raise_exception(get_socket_exception(WSAGetLastError()));
638 return(GUINT_TO_POINTER (sock));
641 /* FIXME: the SOCKET parameter (here and in other functions in this
642 * file) is really an IntPtr which needs to be converted to a guint32.
644 void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock)
649 g_message (G_GNUC_PRETTY_FUNCTION ": closing 0x%x", sock);
655 gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void)
660 g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", WSAGetLastError());
663 return(WSAGetLastError());
666 gint32 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock)
672 ret=ioctlsocket(sock, FIONREAD, &amount);
673 if(ret==SOCKET_ERROR) {
674 mono_raise_exception(get_socket_exception(WSAGetLastError()));
681 void ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock,
688 ret=ioctlsocket(sock, FIONBIO, &block);
689 if(ret==SOCKET_ERROR) {
690 mono_raise_exception(get_socket_exception(WSAGetLastError()));
694 gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock)
700 newsock=accept(sock, NULL, 0);
701 if(newsock==INVALID_SOCKET) {
702 mono_raise_exception(get_socket_exception(WSAGetLastError()));
706 return(GUINT_TO_POINTER (newsock));
709 void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock,
716 ret=listen(sock, backlog);
717 if(ret==SOCKET_ERROR) {
718 mono_raise_exception(get_socket_exception(WSAGetLastError()));
722 static MonoObject *create_object_from_sockaddr(struct sockaddr *saddr,
725 MonoDomain *domain = mono_domain_get ();
726 MonoObject *sockaddr_obj;
727 MonoClass *sockaddr_class;
728 MonoClassField *field;
730 MonoAddressFamily family;
732 /* Build a System.Net.SocketAddress object instance */
733 sockaddr_class=mono_class_from_name(system_assembly, "System.Net", "SocketAddress");
734 sockaddr_obj=mono_object_new(domain, sockaddr_class);
736 /* Locate the SocketAddress data buffer in the object */
737 field=mono_class_get_field_from_name(sockaddr_class, "data");
739 /* Make sure there is space for the family and size bytes */
740 data=mono_array_new(domain, mono_defaults.byte_class, sa_size+2);
742 /* The data buffer is laid out as follows:
743 * byte 0 is the address family
744 * byte 1 is the buffer length
745 * bytes 2 and 3 are the port info
746 * the rest is the address info
749 family=convert_to_mono_family(saddr->sa_family);
750 if(family==AddressFamily_Unknown) {
751 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
755 mono_array_set(data, guint8, 0, family & 0x0FF);
756 mono_array_set(data, guint8, 1, ((family << 8) & 0x0FFFF));
758 if(saddr->sa_family==AF_INET) {
759 struct sockaddr_in *sa_in=(struct sockaddr_in *)saddr;
760 guint16 port=ntohs(sa_in->sin_port);
761 guint32 address=ntohl(sa_in->sin_addr.s_addr);
764 mono_raise_exception((MonoException *)mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
767 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
768 mono_array_set(data, guint8, 3, (port) & 0xff);
769 mono_array_set(data, guint8, 4, (address>>24) & 0xff);
770 mono_array_set(data, guint8, 5, (address>>16) & 0xff);
771 mono_array_set(data, guint8, 6, (address>>8) & 0xff);
772 mono_array_set(data, guint8, 7, (address) & 0xff);
774 *(MonoArray **)(((char *)sockaddr_obj) + field->offset)=data;
776 return(sockaddr_obj);
778 } else if (saddr->sa_family == AF_INET6) {
779 struct sockaddr_in6 *sa_in=(struct sockaddr_in6 *)saddr;
782 guint16 port=ntohs(sa_in->sin6_port);
785 mono_raise_exception((MonoException *)mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
788 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
789 mono_array_set(data, guint8, 3, (port) & 0xff);
791 for(i=0; i<16; i++) {
792 mono_array_set(data, guint8, 8+i,
793 sa_in->sin6_addr.s6_addr[i]);
796 mono_array_set(data, guint8, 24, sa_in->sin6_scope_id & 0xff);
797 mono_array_set(data, guint8, 25,
798 (sa_in->sin6_scope_id >> 8) & 0xff);
799 mono_array_set(data, guint8, 26,
800 (sa_in->sin6_scope_id >> 16) & 0xff);
801 mono_array_set(data, guint8, 27,
802 (sa_in->sin6_scope_id >> 24) & 0xff);
804 *(MonoArray **)(((char *)sockaddr_obj) + field->offset)=data;
806 return(sockaddr_obj);
809 } else if (saddr->sa_family == AF_UNIX) {
812 for (i = 0; i < sa_size; i++) {
813 mono_array_set (data, guint8, i+2, saddr->sa_data[i]);
816 *(MonoArray **)(((char *)sockaddr_obj) + field->offset) = data;
821 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
826 extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock)
828 gchar sa[32]; /// sockaddr in not big enough for sockaddr_in6
835 ret=getsockname(sock, (struct sockaddr *)sa, &salen);
837 if(ret==SOCKET_ERROR) {
838 mono_raise_exception(get_socket_exception(WSAGetLastError()));
842 g_message(G_GNUC_PRETTY_FUNCTION ": bound to %s port %d", inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port));
845 return(create_object_from_sockaddr((struct sockaddr *)sa, salen));
848 extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock)
850 gchar sa[32]; /// sockaddr in not big enough for sockaddr_in6
857 ret=getpeername(sock, (struct sockaddr *)sa, &salen);
859 if(ret==SOCKET_ERROR) {
860 mono_raise_exception(get_socket_exception(WSAGetLastError()));
864 g_message(G_GNUC_PRETTY_FUNCTION ": connected to %s port %d", inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port));
867 return(create_object_from_sockaddr((struct sockaddr *)sa, salen));
870 static struct sockaddr *create_sockaddr_from_object(MonoObject *saddr_obj,
873 MonoClassField *field;
878 /* Dig the SocketAddress data buffer out of the object */
879 field=mono_class_get_field_from_name(saddr_obj->vtable->klass, "data");
880 data=*(MonoArray **)(((char *)saddr_obj) + field->offset);
882 /* The data buffer is laid out as follows:
883 * byte 0 is the address family low byte
884 * byte 1 is the address family high byte
886 * bytes 2 and 3 are the port info
887 * the rest is the address info
889 * the rest is the file name
891 len = mono_array_length (data);
893 mono_raise_exception (mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
896 family = convert_family (mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8));
897 if(family==AF_INET) {
898 struct sockaddr_in *sa=g_new0(struct sockaddr_in, 1);
899 guint16 port=(mono_array_get(data, guint8, 2) << 8) +
900 mono_array_get(data, guint8, 3);
901 guint32 address=(mono_array_get(data, guint8, 4) << 24) +
902 (mono_array_get(data, guint8, 5) << 16 ) +
903 (mono_array_get(data, guint8, 6) << 8) +
904 mono_array_get(data, guint8, 7);
906 sa->sin_family=family;
907 sa->sin_addr.s_addr=htonl(address);
908 sa->sin_port=htons(port);
910 *sa_size=sizeof(struct sockaddr_in);
911 return((struct sockaddr *)sa);
914 } else if (family == AF_INET6) {
915 struct sockaddr_in6 *sa=g_new0(struct sockaddr_in6, 1);
918 guint16 port = mono_array_get(data, guint8, 3) + (mono_array_get(data, guint8, 2) << 8);
919 guint32 scopeid = mono_array_get(data, guint8, 24) +
920 (mono_array_get(data, guint8, 25)<<8) +
921 (mono_array_get(data, guint8, 26)<<16) +
922 (mono_array_get(data, guint8, 27)<<24);
924 sa->sin6_family=family;
925 sa->sin6_port=htons(port);
926 sa->sin6_scope_id = scopeid;
929 sa->sin6_addr.s6_addr[i] = mono_array_get(data, guint8, 8+i);
931 *sa_size=sizeof(struct sockaddr_in6);
932 return((struct sockaddr *)sa);
935 } else if (family == AF_UNIX) {
936 struct sockaddr_un *sock_un = g_new0 (struct sockaddr_un, 1);
939 if (len - 2 > MONO_SIZEOF_SUNPATH)
940 mono_raise_exception (mono_get_exception_index_out_of_range ());
942 sock_un->sun_family = family;
943 for (i = 0; i < len - 2; i++)
944 sock_un->sun_path [i] = mono_array_get (data, guint8,
946 sock_un->sun_path [len - 2] = '\0';
947 *sa_size = sizeof (struct sockaddr_un);
949 return (struct sockaddr *)sock_un;
952 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
957 extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoObject *sockaddr)
965 sa=create_sockaddr_from_object(sockaddr, &sa_size);
968 g_message(G_GNUC_PRETTY_FUNCTION ": binding to %s port %d", inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port));
971 ret=bind(sock, sa, sa_size);
974 if(ret==SOCKET_ERROR) {
975 mono_raise_exception(get_socket_exception(WSAGetLastError()));
979 extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr)
987 sa=create_sockaddr_from_object(sockaddr, &sa_size);
990 g_message(G_GNUC_PRETTY_FUNCTION ": connecting to %s port %d", inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port));
993 ret=connect(sock, sa, sa_size);
996 if(ret==SOCKET_ERROR) {
997 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1001 gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
1008 MONO_ARCH_SAVE_REGS;
1010 alen=mono_array_length(buffer);
1011 if(offset+count>alen) {
1015 buf=mono_array_addr(buffer, guchar, offset);
1017 ret=recv(sock, buf, count, recvflags);
1018 if(ret==SOCKET_ERROR) {
1019 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1025 gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr)
1031 struct sockaddr *sa;
1034 MONO_ARCH_SAVE_REGS;
1036 alen=mono_array_length(buffer);
1037 if(offset+count>alen) {
1041 sa=create_sockaddr_from_object(*sockaddr, &sa_size);
1043 buf=mono_array_addr(buffer, guchar, offset);
1045 ret=recvfrom(sock, buf, count, recvflags, sa, &sa_size);
1047 if(ret==SOCKET_ERROR) {
1049 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1052 *sockaddr=create_object_from_sockaddr(sa, sa_size);
1058 gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
1065 MONO_ARCH_SAVE_REGS;
1067 alen=mono_array_length(buffer);
1068 if(offset+count>alen) {
1073 g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
1076 buf=mono_array_addr(buffer, guchar, offset);
1079 g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
1082 ret=send(sock, buf, count, sendflags);
1083 if(ret==SOCKET_ERROR) {
1084 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1090 gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr)
1096 struct sockaddr *sa;
1099 MONO_ARCH_SAVE_REGS;
1101 alen=mono_array_length(buffer);
1102 if(offset+count>alen) {
1106 sa=create_sockaddr_from_object(sockaddr, &sa_size);
1109 g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
1112 buf=mono_array_addr(buffer, guchar, offset);
1115 g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
1118 ret=sendto(sock, buf, count, sendflags, sa, sa_size);
1121 if(ret==SOCKET_ERROR) {
1122 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1128 static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
1131 MonoClassField *field;
1133 field=mono_class_get_field_from_name(sockobj->vtable->klass, "socket");
1134 sock=*(SOCKET *)(((char *)sockobj)+field->offset);
1139 void ves_icall_System_Net_Sockets_Socket_Select_internal(MonoArray **read_socks, MonoArray **write_socks, MonoArray **err_socks, gint32 timeout)
1141 fd_set readfds, writefds, errfds;
1142 fd_set *readptr = NULL, *writeptr = NULL, *errptr = NULL;
1146 int readarrsize = 0, writearrsize = 0, errarrsize = 0;
1147 MonoDomain *domain=mono_domain_get();
1148 MonoClass *sock_arr_class;
1154 MONO_ARCH_SAVE_REGS;
1157 readarrsize=mono_array_length(*read_socks);
1159 if(readarrsize>FD_SETSIZE) {
1160 mono_raise_exception(get_socket_exception(WSAEFAULT));
1167 for(i=0; i<readarrsize; i++) {
1168 handle = Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i));
1169 FD_SET(handle, &readfds);
1174 writearrsize=mono_array_length(*write_socks);
1176 if(writearrsize>FD_SETSIZE) {
1177 mono_raise_exception(get_socket_exception(WSAEFAULT));
1182 writeptr = &writefds;
1184 for(i=0; i<writearrsize; i++) {
1185 handle = Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i));
1186 FD_SET(handle, &writefds);
1191 errarrsize=mono_array_length(*err_socks);
1193 if(errarrsize>FD_SETSIZE) {
1194 mono_raise_exception(get_socket_exception(WSAEFAULT));
1201 for(i=0; i<errarrsize; i++) {
1202 handle = Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i));
1203 FD_SET(handle, &errfds);
1207 /* Negative timeout meaning block until ready is only
1208 * specified in Poll, not Select
1211 divvy = div (timeout, 1000000);
1215 tv.tv_sec=divvy.quot;
1216 tv.tv_usec=divvy.rem;
1218 ret=select(0, readptr, writeptr, errptr, &tv);
1220 ret=select(0, readptr, writeptr, errptr, NULL);
1222 } while ((ret==SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR));
1224 if(ret==SOCKET_ERROR) {
1225 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1230 sock_arr_class=((MonoObject *)*read_socks)->vtable->klass;
1233 for(i=0; i<readarrsize; i++) {
1234 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i)), &readfds)) {
1238 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1240 for(i=0; i<readarrsize; i++) {
1241 MonoObject *sock=mono_array_get(*read_socks, MonoObject *, i);
1243 if(FD_ISSET(Socket_to_SOCKET(sock), &readfds)) {
1244 mono_array_set(socks, MonoObject *, count, sock);
1254 sock_arr_class=((MonoObject *)*write_socks)->vtable->klass;
1256 for(i=0; i<writearrsize; i++) {
1257 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i)), &writefds)) {
1261 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1263 for(i=0; i<writearrsize; i++) {
1264 MonoObject *sock=mono_array_get(*write_socks, MonoObject *, i);
1266 if(FD_ISSET(Socket_to_SOCKET(sock), &writefds)) {
1267 mono_array_set(socks, MonoObject *, count, sock);
1273 *write_socks = NULL;
1277 sock_arr_class=((MonoObject *)*err_socks)->vtable->klass;
1279 for(i=0; i<errarrsize; i++) {
1280 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i)), &errfds)) {
1284 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1286 for(i=0; i<errarrsize; i++) {
1287 MonoObject *sock=mono_array_get(*err_socks, MonoObject *, i);
1289 if(FD_ISSET(Socket_to_SOCKET(sock), &errfds)) {
1290 mono_array_set(socks, MonoObject *, count, sock);
1298 static MonoObject* int_to_object (MonoDomain *domain, int val)
1300 /* construct an Int32 object to hold val */
1301 MonoObject* obj = mono_object_new(domain, mono_defaults.int32_class);
1303 /* Locate and set the "value" field */
1304 MonoClassField *field = mono_class_get_field_from_name(mono_defaults.int32_class,
1306 *(gint32 *)(((char *)obj)+field->offset)=val;
1311 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val)
1317 int valsize=sizeof(val);
1318 struct linger linger;
1319 int lingersize=sizeof(linger);
1321 int tvsize=sizeof(tv);
1322 MonoDomain *domain=mono_domain_get();
1324 MonoClass *obj_class;
1325 MonoClassField *field;
1327 MONO_ARCH_SAVE_REGS;
1329 ret=convert_sockopt_level_and_name(level, name, &system_level,
1332 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1336 /* No need to deal with MulticastOption names here, because
1337 * you cant getsockopt AddMembership or DropMembership (the
1338 * int getsockopt will error, causing an exception)
1341 case SocketOptionName_Linger:
1342 case SocketOptionName_DontLinger:
1343 ret=getsockopt(sock, system_level, system_name, &linger,
1347 case SocketOptionName_SendTimeout:
1348 case SocketOptionName_ReceiveTimeout:
1349 ret=getsockopt(sock, system_level, system_name, &tv,
1354 ret=getsockopt(sock, system_level, system_name, &val,
1358 if(ret==SOCKET_ERROR) {
1359 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1364 case SocketOptionName_Linger:
1365 /* build a System.Net.Sockets.LingerOption */
1366 obj_class=mono_class_from_name(system_assembly,
1367 "System.Net.Sockets",
1369 obj=mono_object_new(domain, obj_class);
1371 /* Locate and set the fields "bool enabled" and "int
1374 field=mono_class_get_field_from_name(obj_class, "enabled");
1375 *(guint8 *)(((char *)obj)+field->offset)=linger.l_onoff;
1377 field=mono_class_get_field_from_name(obj_class, "seconds");
1378 *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
1382 case SocketOptionName_DontLinger:
1383 /* construct a bool int in val - true if linger is off */
1384 obj = int_to_object (domain, !linger.l_onoff);
1387 case SocketOptionName_SendTimeout:
1388 case SocketOptionName_ReceiveTimeout:
1389 obj = int_to_object (domain, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
1393 obj = int_to_object (domain, val);
1399 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal(SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val)
1407 MONO_ARCH_SAVE_REGS;
1409 ret=convert_sockopt_level_and_name(level, name, &system_level,
1412 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1416 valsize=mono_array_length(*byte_val);
1417 buf=mono_array_addr(*byte_val, guchar, 0);
1419 ret=getsockopt(sock, system_level, system_name, buf, &valsize);
1420 if(ret==SOCKET_ERROR) {
1421 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1425 static struct in_addr ipaddress_to_struct_in_addr(MonoObject *ipaddr)
1427 struct in_addr inaddr;
1428 MonoClassField *field;
1430 field=mono_class_get_field_from_name(ipaddr->vtable->klass, "address");
1432 /* No idea why .net uses a 64bit type to hold a 32bit value...
1434 * Internal value of IPAddess is in Network Order, there is no need
1435 * to call htonl here.
1437 inaddr.s_addr=(guint32)*(guint64 *)(((char *)ipaddr)+field->offset);
1443 static struct in6_addr ipaddress_to_struct_in6_addr(MonoObject *ipaddr)
1445 struct in6_addr in6addr;
1446 MonoClassField *field;
1450 field=mono_class_get_field_from_name(ipaddr->vtable->klass, "_numbers");
1451 data=*(MonoArray **)(((char *)ipaddr) + field->offset);
1453 /* Solaris has only the 8 bit version. */
1455 for(i=0; i<8; i++) {
1456 guint16 s = mono_array_get (data, guint16, i);
1457 in6addr.s6_addr[2 * i] = (s >> 8) & 0xff;
1458 in6addr.s6_addr[2 * i + 1] = s & 0xff;
1462 in6addr.s6_addr16[i] = mono_array_get (data, guint16, i);
1466 #endif /* AF_INET6 */
1468 void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val)
1477 #ifdef HAVE_SOL_IPV6
1478 sol_ipv6 = SOL_IPV6;
1481 struct protoent *pent;
1482 pent = getprotobyname ("ipv6");
1483 sol_ipv6 = (pent != NULL) ? pent->p_proto : 41;
1491 struct protoent *pent;
1492 pent = getprotobyname ("ip");
1493 sol_ip = (pent != NULL) ? pent->p_proto : 0;
1496 #endif /* AF_INET6 */
1498 MONO_ARCH_SAVE_REGS;
1500 ret=convert_sockopt_level_and_name(level, name, &system_level,
1503 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1507 /* Only one of obj_val, byte_val or int_val has data */
1509 MonoClassField *field;
1510 struct linger linger;
1514 case SocketOptionName_DontLinger:
1517 valsize=sizeof(linger);
1518 ret=setsockopt(sock, system_level, system_name,
1522 case SocketOptionName_Linger:
1523 /* Dig out "bool enabled" and "int seconds"
1526 field=mono_class_get_field_from_name(obj_val->vtable->klass, "enabled");
1527 linger.l_onoff=*(guint8 *)(((char *)obj_val)+field->offset);
1528 field=mono_class_get_field_from_name(obj_val->vtable->klass, "seconds");
1529 linger.l_linger=*(guint32 *)(((char *)obj_val)+field->offset);
1531 valsize=sizeof(linger);
1532 ret=setsockopt(sock, system_level, system_name,
1535 case SocketOptionName_AddMembership:
1536 case SocketOptionName_DropMembership:
1537 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
1539 MonoObject *address = NULL;
1542 if(system_level == sol_ipv6) {
1543 struct ipv6_mreq mreq6;
1548 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
1549 address = *(gpointer *)(((char *)obj_val) + field->offset);
1552 mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
1555 field=mono_class_get_field_from_name(obj_val->vtable->klass, "ifIndex");
1556 mreq6.ipv6mr_interface =*(guint64 *)(((char *)obj_val)+field->offset);
1558 ret = setsockopt (sock, system_level,
1559 system_name, &mreq6,
1561 } else if(system_level == sol_ip)
1562 #endif /* AF_INET6 */
1564 #ifdef HAVE_STRUCT_IP_MREQN
1565 struct ip_mreqn mreq = {{0}};
1567 struct ip_mreq mreq = {{0}};
1568 #endif /* HAVE_STRUCT_IP_MREQN */
1570 /* pain! MulticastOption holds two IPAddress
1571 * members, so I have to dig the value out of
1574 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
1575 address = *(gpointer *)(((char *)obj_val) + field->offset);
1577 /* address might not be defined and if so, set the address to ADDR_ANY.
1580 mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
1583 field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
1584 address = *(gpointer *)(((char *)obj_val) + field->offset);
1586 #ifdef HAVE_STRUCT_IP_MREQN
1588 mreq.imr_address = ipaddress_to_struct_in_addr (address);
1592 mreq.imr_interface = ipaddress_to_struct_in_addr (address);
1594 #endif /* HAVE_STRUCT_IP_MREQN */
1596 ret = setsockopt (sock, system_level,
1602 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
1604 /* Throw an exception */
1605 mono_raise_exception(get_socket_exception(WSAEINVAL));
1607 } else if (byte_val!=NULL) {
1608 int valsize=mono_array_length(byte_val);
1609 guchar *buf=mono_array_addr(byte_val, guchar, 0);
1611 ret=setsockopt(sock, system_level, system_name, buf, valsize);
1612 if(ret==SOCKET_ERROR) {
1613 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1617 case SocketOptionName_SendTimeout:
1618 case SocketOptionName_ReceiveTimeout: {
1620 tv.tv_sec = int_val / 1000;
1621 tv.tv_usec = (int_val % 1000) * 1000;
1622 ret=setsockopt(sock, system_level, system_name, &tv, sizeof (tv));
1626 ret=setsockopt(sock, system_level, system_name, &int_val,
1631 if(ret==SOCKET_ERROR) {
1632 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1636 void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock,
1641 MONO_ARCH_SAVE_REGS;
1643 /* Currently, the values for how (recv=0, send=1, both=2) match
1646 ret=shutdown(sock, how);
1647 if(ret==SOCKET_ERROR) {
1648 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1653 static gboolean hostent_to_IPHostEntry(struct hostent *he, MonoString **h_name,
1654 MonoArray **h_aliases,
1655 MonoArray **h_addr_list)
1657 MonoDomain *domain = mono_domain_get ();
1660 if(he->h_length!=4 || he->h_addrtype!=AF_INET) {
1664 *h_name=mono_string_new(domain, he->h_name);
1667 while(he->h_aliases[i]!=NULL) {
1671 *h_aliases=mono_array_new(domain, mono_defaults.string_class, i);
1673 while(he->h_aliases[i]!=NULL) {
1676 alias=mono_string_new(domain, he->h_aliases[i]);
1677 mono_array_set(*h_aliases, MonoString *, i, alias);
1682 while(he->h_addr_list[i]!=NULL) {
1686 *h_addr_list=mono_array_new(domain, mono_defaults.string_class, i);
1688 while(he->h_addr_list[i]!=NULL) {
1689 MonoString *addr_string;
1692 g_snprintf(addr, 16, "%u.%u.%u.%u",
1693 (unsigned char)he->h_addr_list[i][0],
1694 (unsigned char)he->h_addr_list[i][1],
1695 (unsigned char)he->h_addr_list[i][2],
1696 (unsigned char)he->h_addr_list[i][3]);
1698 addr_string=mono_string_new(domain, addr);
1699 mono_array_set(*h_addr_list, MonoString *, i, addr_string);
1707 #if defined(AF_INET6) && defined(HAVE_GETHOSTBYNAME2_R)
1708 static gboolean hostent_to_IPHostEntry2(struct hostent *he1,struct hostent *he2, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1710 MonoDomain *domain = mono_domain_get ();
1711 int i, host_count, host_index, family_hint;
1713 family_hint = get_family_hint ();
1715 if(he1 == NULL && he2 == NULL) {
1720 * Check if address length and family are correct
1722 if (he1 != NULL && (he1->h_length!=4 || he1->h_addrtype!=AF_INET)) {
1726 if (he2 != NULL && (he2->h_length!=16 || he2->h_addrtype!=AF_INET6)) {
1731 * Get the aliases and host name from he1 or he2 whichever is
1732 * not null, if he1 is not null then take aliases from he1
1734 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1735 family_hint == PF_INET)) {
1736 *h_name=mono_string_new (domain, he1->h_name);
1739 while(he1->h_aliases[i]!=NULL) {
1743 *h_aliases=mono_array_new (domain, mono_defaults.string_class,
1746 while(he1->h_aliases[i]!=NULL) {
1749 alias=mono_string_new (domain, he1->h_aliases[i]);
1750 mono_array_set (*h_aliases, MonoString *, i, alias);
1753 } else if (family_hint == PF_UNSPEC || family_hint == PF_INET6) {
1754 *h_name=mono_string_new (domain, he2->h_name);
1757 while(he2->h_aliases [i] != NULL) {
1761 *h_aliases=mono_array_new (domain, mono_defaults.string_class,
1764 while(he2->h_aliases[i]!=NULL) {
1767 alias=mono_string_new (domain, he2->h_aliases[i]);
1768 mono_array_set (*h_aliases, MonoString *, i, alias);
1774 * Count the number of addresses in he1 + he2
1777 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1778 family_hint == PF_INET)) {
1780 while(he1->h_addr_list[i]!=NULL) {
1786 if (he2 != NULL && (family_hint == PF_UNSPEC ||
1787 family_hint == PF_INET6)) {
1789 while(he2->h_addr_list[i]!=NULL) {
1798 *h_addr_list=mono_array_new (domain, mono_defaults.string_class,
1803 if (he2 != NULL && (family_hint == PF_UNSPEC ||
1804 family_hint == PF_INET6)) {
1806 while(he2->h_addr_list[i] != NULL) {
1807 MonoString *addr_string;
1810 inet_ntop (AF_INET6, he2->h_addr_list[i], addr,
1813 addr_string = mono_string_new (domain, addr);
1814 mono_array_set (*h_addr_list, MonoString *, host_index,
1821 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1822 family_hint == PF_INET)) {
1824 while(he1->h_addr_list[i] != NULL) {
1825 MonoString *addr_string;
1828 inet_ntop (AF_INET, he1->h_addr_list[i], addr,
1831 addr_string=mono_string_new (domain, addr);
1832 mono_array_set (*h_addr_list, MonoString *, host_index,
1843 #if defined(AF_INET6)
1845 addrinfo_to_IPHostEntry(struct addrinfo *info, MonoString **h_name,
1846 MonoArray **h_aliases,
1847 MonoArray **h_addr_list)
1850 struct addrinfo *ai = NULL;
1852 MonoDomain *domain = mono_domain_get ();
1854 for (count=0, ai=info; ai!=NULL; ai=ai->ai_next) {
1855 if((ai->ai_family != PF_INET) && (ai->ai_family != PF_INET6)) {
1862 *h_aliases=mono_array_new(domain, mono_defaults.string_class, 0);
1863 *h_addr_list=mono_array_new(domain, mono_defaults.string_class, count);
1865 for (ai=info, i=0; ai!=NULL; ai=ai->ai_next) {
1866 MonoString *addr_string;
1869 gint32 buffer_size = 0;
1871 if((ai->ai_family != PF_INET) && (ai->ai_family != PF_INET6)) {
1877 buffer = g_malloc0(buffer_size);
1879 if(ai->ai_family == PF_INET) {
1880 ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in*)ai->ai_addr)->sin_addr), buffer, buffer_size);
1882 ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr), buffer, buffer_size);
1889 } while(ret == 0 && errno == ENOSPC);
1892 addr_string=mono_string_new(domain, buffer);
1895 addr_string=mono_string_new(domain, "");
1898 mono_array_set(*h_addr_list, MonoString *, i, addr_string);
1901 *h_name=mono_string_new(domain, ai->ai_canonname);
1916 MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1918 #if !defined(HAVE_GETHOSTBYNAME2_R)
1919 struct addrinfo *info = NULL, hints;
1922 MONO_ARCH_SAVE_REGS;
1924 hostname=mono_string_to_utf8 (host);
1926 memset(&hints, 0, sizeof(hints));
1927 hints.ai_family = get_family_hint ();
1928 hints.ai_socktype = SOCK_STREAM;
1929 hints.ai_flags = AI_CANONNAME;
1931 if (getaddrinfo(hostname, NULL, &hints, &info) == -1) {
1937 return(addrinfo_to_IPHostEntry(info, h_name, h_aliases, h_addr_list));
1939 struct hostent he1,*hp1, he2, *hp2;
1940 int buffer_size1, buffer_size2;
1941 char *buffer1, *buffer2;
1943 gboolean return_value;
1946 MONO_ARCH_SAVE_REGS;
1948 hostname=mono_string_to_utf8 (host);
1952 buffer1 = g_malloc0(buffer_size1);
1953 buffer2 = g_malloc0(buffer_size2);
1955 while (gethostbyname2_r(hostname, AF_INET, &he1, buffer1, buffer_size1,
1956 &hp1, &herr) == ERANGE) {
1958 buffer1 = g_realloc(buffer1, buffer_size1);
1961 while (gethostbyname2_r(hostname, AF_INET6, &he2, buffer2,
1962 buffer_size2, &hp2, &herr) == ERANGE) {
1964 buffer2 = g_realloc(buffer2, buffer_size2);
1967 return_value = hostent_to_IPHostEntry2(hp1, hp2, h_name, h_aliases,
1973 return(return_value);
1974 #endif /* HAVE_GETHOSTBYNAME2_R */
1976 #else /* AF_INET6 */
1977 MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1982 MONO_ARCH_SAVE_REGS;
1984 hostname=mono_string_to_utf8(host);
1986 he=gethostbyname(hostname);
1993 return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
1995 #endif /* AF_INET6 */
1997 #ifndef HAVE_INET_PTON
1999 inet_pton (int family, const char *address, void *inaddrp)
2001 if (family == AF_INET) {
2002 #ifdef HAVE_INET_ATON
2003 struct in_addr inaddr;
2005 if (!inet_aton (address, &inaddr))
2008 memcpy (inaddrp, &inaddr, sizeof (struct in_addr));
2011 /* assume the system has inet_addr(), if it doesn't
2012 have that we're pretty much screwed... */
2015 if (!strcmp (address, "255.255.255.255")) {
2016 /* special-case hack */
2017 inaddr = 0xffffffff;
2019 inaddr = inet_addr (address);
2021 #define INADDR_NONE ((in_addr_t) -1)
2023 if (inaddr == INADDR_NONE)
2027 memcpy (inaddrp, &inaddr, sizeof (guint32));
2029 #endif /* HAVE_INET_ATON */
2034 #endif /* !HAVE_INET_PTON */
2036 extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
2041 struct sockaddr_in saddr;
2042 struct sockaddr_in6 saddr6;
2043 struct addrinfo *info = NULL, hints;
2045 char hostname[1024] = {0};
2047 struct in_addr inaddr;
2051 MONO_ARCH_SAVE_REGS;
2053 address = mono_string_to_utf8 (addr);
2056 if (inet_pton (AF_INET, address, &saddr.sin_addr ) <= 0) {
2057 /* Maybe an ipv6 address */
2058 if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) <= 0) {
2064 saddr6.sin6_family = AF_INET6;
2069 saddr.sin_family = AF_INET;
2073 if(family == AF_INET) {
2074 if(getnameinfo ((struct sockaddr*)&saddr, sizeof(saddr),
2075 hostname, sizeof(hostname), NULL, 0,
2076 NI_NAMEREQD) != 0) {
2079 } else if(family == AF_INET6) {
2080 if(getnameinfo ((struct sockaddr*)&saddr6, sizeof(saddr6),
2081 hostname, sizeof(hostname), NULL, 0,
2082 NI_NAMEREQD) != 0) {
2087 memset (&hints, 0, sizeof(hints));
2088 hints.ai_family = get_family_hint ();
2089 hints.ai_socktype = SOCK_STREAM;
2090 hints.ai_flags = AI_CANONNAME;
2092 if( getaddrinfo (hostname, NULL, &hints, &info) == -1 ) {
2096 return(addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list));
2098 if (inet_pton (AF_INET, address, &inaddr) <= 0) {
2104 if ((he = gethostbyaddr ((char *) &inaddr, sizeof (inaddr), AF_INET)) == NULL) {
2108 return(hostent_to_IPHostEntry (he, h_name, h_aliases, h_addr_list));
2112 extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name)
2114 guchar hostname[256];
2117 MONO_ARCH_SAVE_REGS;
2119 ret=gethostname (hostname, sizeof(hostname));
2124 *h_name=mono_string_new(mono_domain_get (), hostname);
2130 void mono_network_init(void)
2135 err=WSAStartup(MAKEWORD(2,0), &wsadata);
2137 g_error(G_GNUC_PRETTY_FUNCTION ": Couldn't initialise networking");
2142 g_message(G_GNUC_PRETTY_FUNCTION ": Using socket library: %s", wsadata.szDescription);
2143 g_message(G_GNUC_PRETTY_FUNCTION ": Socket system status: %s", wsadata.szSystemStatus);
2147 void mono_network_cleanup(void)