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 */
39 #include "mono/io-layer/socket-wrappers.h"
42 /* This is a kludge to make this file build under cygwin:
43 * w32api/ws2tcpip.h has definitions for some AF_INET6 values and
44 * prototypes for some but not all required functions (notably
45 * inet_ntop() is missing), but the libws2_32 library is missing the
46 * actual implementations of these functions.
53 static gint32 convert_family(MonoAddressFamily mono_family)
58 case AddressFamily_Unknown:
59 case AddressFamily_ImpLink:
60 case AddressFamily_Pup:
61 case AddressFamily_Chaos:
62 case AddressFamily_Iso:
63 case AddressFamily_Ecma:
64 case AddressFamily_DataKit:
65 case AddressFamily_Ccitt:
66 case AddressFamily_DataLink:
67 case AddressFamily_Lat:
68 case AddressFamily_HyperChannel:
69 case AddressFamily_NetBios:
70 case AddressFamily_VoiceView:
71 case AddressFamily_FireFox:
72 case AddressFamily_Banyan:
73 case AddressFamily_Atm:
74 case AddressFamily_Cluster:
75 case AddressFamily_Ieee12844:
76 case AddressFamily_NetworkDesigners:
77 g_warning("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
80 case AddressFamily_Unspecified:
84 case AddressFamily_Unix:
88 case AddressFamily_InterNetwork:
93 case AddressFamily_Ipx:
98 case AddressFamily_Sna:
102 case AddressFamily_DecNet:
106 case AddressFamily_AppleTalk:
111 case AddressFamily_InterNetworkV6:
116 case AddressFamily_Irda:
121 g_warning("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
127 static MonoAddressFamily convert_to_mono_family(guint16 af_family)
129 MonoAddressFamily family=AddressFamily_Unknown;
133 family=AddressFamily_Unspecified;
137 family=AddressFamily_Unix;
141 family=AddressFamily_InterNetwork;
146 family=AddressFamily_Ipx;
151 family=AddressFamily_Sna;
155 family=AddressFamily_DecNet;
159 family=AddressFamily_AppleTalk;
164 family=AddressFamily_InterNetworkV6;
170 family=AddressFamily_Irda;
174 g_warning("unknown address family 0x%x", af_family);
180 static gint32 convert_type(MonoSocketType mono_type)
185 case SocketType_Stream:
189 case SocketType_Dgram:
201 case SocketType_Seqpacket:
205 case SocketType_Unknown:
206 g_warning("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
210 g_warning("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
216 static gint32 convert_proto(MonoProtocolType mono_proto)
221 case ProtocolType_IP:
222 case ProtocolType_IPv6:
223 case ProtocolType_Icmp:
224 case ProtocolType_Igmp:
225 case ProtocolType_Ggp:
226 case ProtocolType_Tcp:
227 case ProtocolType_Pup:
228 case ProtocolType_Udp:
229 case ProtocolType_Idp:
230 /* These protocols are known (on my system at least) */
234 case ProtocolType_ND:
235 case ProtocolType_Raw:
236 case ProtocolType_Ipx:
237 case ProtocolType_Spx:
238 case ProtocolType_SpxII:
239 case ProtocolType_Unknown:
240 /* These protocols arent */
241 g_warning("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
251 static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
252 MonoSocketOptionName mono_name,
256 switch (mono_level) {
257 case SocketOptionLevel_Socket:
258 *system_level = SOL_SOCKET;
261 case SocketOptionName_DontLinger:
262 /* This is SO_LINGER, because the setsockopt
263 * internal call maps DontLinger to SO_LINGER
266 *system_name = SO_LINGER;
268 case SocketOptionName_Debug:
269 *system_name = SO_DEBUG;
272 case SocketOptionName_AcceptConnection:
273 *system_name = SO_ACCEPTCONN;
276 case SocketOptionName_ReuseAddress:
277 *system_name = SO_REUSEADDR;
279 case SocketOptionName_KeepAlive:
280 *system_name = SO_KEEPALIVE;
282 case SocketOptionName_DontRoute:
283 *system_name = SO_DONTROUTE;
285 case SocketOptionName_Broadcast:
286 *system_name = SO_BROADCAST;
288 case SocketOptionName_Linger:
289 *system_name = SO_LINGER;
291 case SocketOptionName_OutOfBandInline:
292 *system_name = SO_OOBINLINE;
294 case SocketOptionName_SendBuffer:
295 *system_name = SO_SNDBUF;
297 case SocketOptionName_ReceiveBuffer:
298 *system_name = SO_RCVBUF;
300 case SocketOptionName_SendLowWater:
301 *system_name = SO_SNDLOWAT;
303 case SocketOptionName_ReceiveLowWater:
304 *system_name = SO_RCVLOWAT;
306 case SocketOptionName_SendTimeout:
307 *system_name = SO_SNDTIMEO;
309 case SocketOptionName_ReceiveTimeout:
310 *system_name = SO_RCVTIMEO;
312 case SocketOptionName_Error:
313 *system_name = SO_ERROR;
315 case SocketOptionName_Type:
316 *system_name = SO_TYPE;
318 case SocketOptionName_ExclusiveAddressUse:
319 case SocketOptionName_UseLoopback:
320 case SocketOptionName_MaxConnections:
321 /* Can't figure out how to map these, so fall
325 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
330 case SocketOptionLevel_IP:
332 *system_level = SOL_IP;
335 static int cached = 0;
339 struct protoent *pent;
341 pent = getprotobyname ("IP");
342 proto = pent ? pent->p_proto : 0 /* 0 a good default value?? */;
346 *system_level = proto;
348 #endif /* HAVE_SOL_IP */
351 case SocketOptionName_IPOptions:
352 *system_name = IP_OPTIONS;
355 case SocketOptionName_HeaderIncluded:
356 *system_name = IP_HDRINCL;
360 case SocketOptionName_TypeOfService:
361 *system_name = IP_TOS;
365 case SocketOptionName_IpTimeToLive:
366 *system_name = IP_TTL;
369 case SocketOptionName_MulticastInterface:
370 *system_name = IP_MULTICAST_IF;
372 case SocketOptionName_MulticastTimeToLive:
373 *system_name = IP_MULTICAST_TTL;
375 case SocketOptionName_MulticastLoopback:
376 *system_name = IP_MULTICAST_LOOP;
378 case SocketOptionName_AddMembership:
379 *system_name = IP_ADD_MEMBERSHIP;
381 case SocketOptionName_DropMembership:
382 *system_name = IP_DROP_MEMBERSHIP;
384 #ifdef HAVE_IP_PKTINFO
385 case SocketOptionName_PacketInformation:
386 *system_name = IP_PKTINFO;
388 #endif /* HAVE_IP_PKTINFO */
389 case SocketOptionName_DontFragment:
390 case SocketOptionName_AddSourceMembership:
391 case SocketOptionName_DropSourceMembership:
392 case SocketOptionName_BlockSource:
393 case SocketOptionName_UnblockSource:
394 /* Can't figure out how to map these, so fall
398 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
404 case SocketOptionLevel_IPv6:
406 *system_level = SOL_IPV6;
409 static int cached = 0;
413 struct protoent *pent;
415 pent = getprotobyname ("IPV6");
416 proto = pent ? pent->p_proto : 41 /* 41 a good default value?? */;
420 *system_level = proto;
422 #endif /* HAVE_SOL_IPV6 */
425 case SocketOptionName_IpTimeToLive:
426 *system_name = IPV6_UNICAST_HOPS;
428 case SocketOptionName_MulticastInterface:
429 *system_name = IPV6_MULTICAST_IF;
431 case SocketOptionName_MulticastTimeToLive:
432 *system_name = IPV6_MULTICAST_HOPS;
434 case SocketOptionName_MulticastLoopback:
435 *system_name = IPV6_MULTICAST_LOOP;
437 case SocketOptionName_AddMembership:
438 *system_name = IPV6_JOIN_GROUP;
440 case SocketOptionName_DropMembership:
441 *system_name = IPV6_LEAVE_GROUP;
443 case SocketOptionName_PacketInformation:
444 *system_name = IPV6_PKTINFO;
446 case SocketOptionName_HeaderIncluded:
447 case SocketOptionName_IPOptions:
448 case SocketOptionName_TypeOfService:
449 case SocketOptionName_DontFragment:
450 case SocketOptionName_AddSourceMembership:
451 case SocketOptionName_DropSourceMembership:
452 case SocketOptionName_BlockSource:
453 case SocketOptionName_UnblockSource:
454 /* Can't figure out how to map these, so fall
458 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name);
462 break; /// SocketOptionLevel_IPv6
465 case SocketOptionLevel_Tcp:
467 *system_level = SOL_TCP;
470 static int cached = 0;
474 struct protoent *pent;
476 pent = getprotobyname ("TCP");
477 proto = pent ? pent->p_proto : 6 /* is 6 a good default value?? */;
481 *system_level = proto;
483 #endif /* HAVE_SOL_TCP */
486 case SocketOptionName_NoDelay:
487 *system_name = TCP_NODELAY;
490 /* The documentation is talking complete
491 * bollocks here: rfc-1222 is titled
492 * 'Advancing the NSFNET Routing Architecture'
493 * and doesn't mention either of the words
494 * "expedite" or "urgent".
496 case SocketOptionName_BsdUrgent:
497 case SocketOptionName_Expedited:
500 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
505 case SocketOptionLevel_Udp:
506 g_warning("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
509 case SocketOptionName_NoChecksum:
510 case SocketOptionName_ChecksumCoverage:
512 g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
519 g_warning("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
526 #define STASH_SYS_ASS(this) \
527 if(system_assembly == NULL) { \
528 system_assembly=mono_image_loaded ("System"); \
531 static MonoImage *system_assembly=NULL;
535 static gint32 get_family_hint(void)
537 MonoClass *socket_class;
538 MonoClassField *ipv6_field, *ipv4_field;
539 gint32 ipv6_enabled = -1, ipv4_enabled = -1;
542 socket_class = mono_class_from_name (system_assembly,
543 "System.Net.Sockets", "Socket");
544 ipv4_field = mono_class_get_field_from_name (socket_class,
546 ipv6_field = mono_class_get_field_from_name (socket_class,
548 vtable = mono_class_vtable (mono_domain_get (), socket_class);
550 mono_field_static_get_value(vtable, ipv4_field, &ipv4_enabled);
551 mono_field_static_get_value(vtable, ipv6_field, &ipv6_enabled);
553 if(ipv4_enabled == 1 && ipv6_enabled == 1) {
555 } else if(ipv4_enabled == 1) {
563 static MonoException *get_socket_exception(guint32 error_code)
565 /* Don't cache this exception, because we need the object
566 * constructor to set up the message from the sockets error code.
570 /* This is a bit of a kludge. The SocketException 0-arg
571 * constructor calls WSAGetLastError() to find the error code
572 * to use. Until we can init objects with parameters, this
575 WSASetLastError(error_code);
577 ex=(MonoException *)mono_exception_from_name(system_assembly,
578 "System.Net.Sockets",
583 gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto)
596 sock_family=convert_family(family);
597 if(sock_family==-1) {
598 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
602 sock_proto=convert_proto(proto);
604 mono_raise_exception(get_socket_exception(WSAEPROTONOSUPPORT));
608 sock_type=convert_type(type);
610 mono_raise_exception(get_socket_exception(WSAESOCKTNOSUPPORT));
614 sock = _wapi_socket (sock_family, sock_type, sock_proto);
615 if(sock==INVALID_SOCKET) {
616 mono_raise_exception(get_socket_exception(WSAGetLastError()));
620 if (sock_family == AF_INET && sock_type == SOCK_DGRAM) {
621 return (GUINT_TO_POINTER (sock));
625 if (sock_family == AF_INET6 && sock_type == SOCK_DGRAM) {
626 return (GUINT_TO_POINTER (sock));
630 /* .net seems to set this by default for SOCK_STREAM,
631 * not for SOCK_DGRAM (see bug #36322)
633 ret = _wapi_setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true, sizeof (true));
634 if(ret==SOCKET_ERROR) {
636 mono_raise_exception(get_socket_exception(WSAGetLastError()));
640 return(GUINT_TO_POINTER (sock));
643 /* FIXME: the SOCKET parameter (here and in other functions in this
644 * file) is really an IntPtr which needs to be converted to a guint32.
646 void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock)
651 g_message (G_GNUC_PRETTY_FUNCTION ": closing 0x%x", sock);
657 gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void)
662 g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", WSAGetLastError());
665 return(WSAGetLastError());
668 gint32 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock)
674 ret=ioctlsocket(sock, FIONREAD, &amount);
675 if(ret==SOCKET_ERROR) {
676 mono_raise_exception(get_socket_exception(WSAGetLastError()));
683 void ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock,
690 ret=ioctlsocket(sock, FIONBIO, &block);
691 if(ret==SOCKET_ERROR) {
692 mono_raise_exception(get_socket_exception(WSAGetLastError()));
696 gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock)
702 newsock = _wapi_accept (sock, NULL, 0);
703 if(newsock==INVALID_SOCKET) {
704 mono_raise_exception(get_socket_exception(WSAGetLastError()));
708 return(GUINT_TO_POINTER (newsock));
711 void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock,
718 ret = _wapi_listen (sock, backlog);
719 if(ret==SOCKET_ERROR) {
720 mono_raise_exception(get_socket_exception(WSAGetLastError()));
724 static MonoObject *create_object_from_sockaddr(struct sockaddr *saddr,
727 MonoDomain *domain = mono_domain_get ();
728 MonoObject *sockaddr_obj;
729 MonoClass *sockaddr_class;
730 MonoClassField *field;
732 MonoAddressFamily family;
734 /* Build a System.Net.SocketAddress object instance */
735 sockaddr_class=mono_class_from_name(system_assembly, "System.Net", "SocketAddress");
736 sockaddr_obj=mono_object_new(domain, sockaddr_class);
738 /* Locate the SocketAddress data buffer in the object */
739 field=mono_class_get_field_from_name(sockaddr_class, "data");
741 /* Make sure there is space for the family and size bytes */
742 data=mono_array_new(domain, mono_defaults.byte_class, sa_size+2);
744 /* The data buffer is laid out as follows:
745 * byte 0 is the address family
746 * byte 1 is the buffer length
747 * bytes 2 and 3 are the port info
748 * the rest is the address info
751 family=convert_to_mono_family(saddr->sa_family);
752 if(family==AddressFamily_Unknown) {
753 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
757 mono_array_set(data, guint8, 0, family & 0x0FF);
758 mono_array_set(data, guint8, 1, ((family << 8) & 0x0FFFF));
760 if(saddr->sa_family==AF_INET) {
761 struct sockaddr_in *sa_in=(struct sockaddr_in *)saddr;
762 guint16 port=ntohs(sa_in->sin_port);
763 guint32 address=ntohl(sa_in->sin_addr.s_addr);
766 mono_raise_exception((MonoException *)mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
769 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
770 mono_array_set(data, guint8, 3, (port) & 0xff);
771 mono_array_set(data, guint8, 4, (address>>24) & 0xff);
772 mono_array_set(data, guint8, 5, (address>>16) & 0xff);
773 mono_array_set(data, guint8, 6, (address>>8) & 0xff);
774 mono_array_set(data, guint8, 7, (address) & 0xff);
776 *(MonoArray **)(((char *)sockaddr_obj) + field->offset)=data;
778 return(sockaddr_obj);
780 } else if (saddr->sa_family == AF_INET6) {
781 struct sockaddr_in6 *sa_in=(struct sockaddr_in6 *)saddr;
784 guint16 port=ntohs(sa_in->sin6_port);
787 mono_raise_exception((MonoException *)mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
790 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
791 mono_array_set(data, guint8, 3, (port) & 0xff);
793 for(i=0; i<16; i++) {
794 mono_array_set(data, guint8, 8+i,
795 sa_in->sin6_addr.s6_addr[i]);
798 mono_array_set(data, guint8, 24, sa_in->sin6_scope_id & 0xff);
799 mono_array_set(data, guint8, 25,
800 (sa_in->sin6_scope_id >> 8) & 0xff);
801 mono_array_set(data, guint8, 26,
802 (sa_in->sin6_scope_id >> 16) & 0xff);
803 mono_array_set(data, guint8, 27,
804 (sa_in->sin6_scope_id >> 24) & 0xff);
806 *(MonoArray **)(((char *)sockaddr_obj) + field->offset)=data;
808 return(sockaddr_obj);
811 } else if (saddr->sa_family == AF_UNIX) {
814 for (i = 0; i < sa_size; i++) {
815 mono_array_set (data, guint8, i+2, saddr->sa_data[i]);
818 *(MonoArray **)(((char *)sockaddr_obj) + field->offset) = data;
823 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
828 extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock)
830 gchar sa[32]; /// sockaddr in not big enough for sockaddr_in6
837 ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen);
839 if(ret==SOCKET_ERROR) {
840 mono_raise_exception(get_socket_exception(WSAGetLastError()));
844 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));
847 return(create_object_from_sockaddr((struct sockaddr *)sa, salen));
850 extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock)
852 gchar sa[32]; /// sockaddr in not big enough for sockaddr_in6
859 ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen);
861 if(ret==SOCKET_ERROR) {
862 mono_raise_exception(get_socket_exception(WSAGetLastError()));
866 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));
869 return(create_object_from_sockaddr((struct sockaddr *)sa, salen));
872 static struct sockaddr *create_sockaddr_from_object(MonoObject *saddr_obj,
875 MonoClassField *field;
880 /* Dig the SocketAddress data buffer out of the object */
881 field=mono_class_get_field_from_name(saddr_obj->vtable->klass, "data");
882 data=*(MonoArray **)(((char *)saddr_obj) + field->offset);
884 /* The data buffer is laid out as follows:
885 * byte 0 is the address family low byte
886 * byte 1 is the address family high byte
888 * bytes 2 and 3 are the port info
889 * the rest is the address info
891 * the rest is the file name
893 len = mono_array_length (data);
895 mono_raise_exception (mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
898 family = convert_family (mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8));
899 if(family==AF_INET) {
900 struct sockaddr_in *sa=g_new0(struct sockaddr_in, 1);
901 guint16 port=(mono_array_get(data, guint8, 2) << 8) +
902 mono_array_get(data, guint8, 3);
903 guint32 address=(mono_array_get(data, guint8, 4) << 24) +
904 (mono_array_get(data, guint8, 5) << 16 ) +
905 (mono_array_get(data, guint8, 6) << 8) +
906 mono_array_get(data, guint8, 7);
908 sa->sin_family=family;
909 sa->sin_addr.s_addr=htonl(address);
910 sa->sin_port=htons(port);
912 *sa_size=sizeof(struct sockaddr_in);
913 return((struct sockaddr *)sa);
916 } else if (family == AF_INET6) {
917 struct sockaddr_in6 *sa=g_new0(struct sockaddr_in6, 1);
920 guint16 port = mono_array_get(data, guint8, 3) + (mono_array_get(data, guint8, 2) << 8);
921 guint32 scopeid = mono_array_get(data, guint8, 24) +
922 (mono_array_get(data, guint8, 25)<<8) +
923 (mono_array_get(data, guint8, 26)<<16) +
924 (mono_array_get(data, guint8, 27)<<24);
926 sa->sin6_family=family;
927 sa->sin6_port=htons(port);
928 sa->sin6_scope_id = scopeid;
931 sa->sin6_addr.s6_addr[i] = mono_array_get(data, guint8, 8+i);
933 *sa_size=sizeof(struct sockaddr_in6);
934 return((struct sockaddr *)sa);
937 } else if (family == AF_UNIX) {
938 struct sockaddr_un *sock_un = g_new0 (struct sockaddr_un, 1);
941 if (len - 2 > MONO_SIZEOF_SUNPATH)
942 mono_raise_exception (mono_get_exception_index_out_of_range ());
944 sock_un->sun_family = family;
945 for (i = 0; i < len - 2; i++)
946 sock_un->sun_path [i] = mono_array_get (data, guint8,
948 sock_un->sun_path [len - 2] = '\0';
949 *sa_size = sizeof (struct sockaddr_un);
951 return (struct sockaddr *)sock_un;
954 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
959 extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoObject *sockaddr)
967 sa=create_sockaddr_from_object(sockaddr, &sa_size);
970 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));
973 ret = _wapi_bind (sock, sa, sa_size);
976 if(ret==SOCKET_ERROR) {
977 mono_raise_exception(get_socket_exception(WSAGetLastError()));
981 extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr)
989 sa=create_sockaddr_from_object(sockaddr, &sa_size);
992 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));
995 ret = _wapi_connect (sock, sa, sa_size);
998 if(ret==SOCKET_ERROR) {
999 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1003 gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
1010 MONO_ARCH_SAVE_REGS;
1012 alen=mono_array_length(buffer);
1013 if(offset+count>alen) {
1017 buf=mono_array_addr(buffer, guchar, offset);
1019 ret = _wapi_recv (sock, buf, count, recvflags);
1020 if(ret==SOCKET_ERROR) {
1021 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1027 gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr)
1033 struct sockaddr *sa;
1036 MONO_ARCH_SAVE_REGS;
1038 alen=mono_array_length(buffer);
1039 if(offset+count>alen) {
1043 sa=create_sockaddr_from_object(*sockaddr, &sa_size);
1045 buf=mono_array_addr(buffer, guchar, offset);
1047 ret = _wapi_recvfrom (sock, buf, count, recvflags, sa, &sa_size);
1049 if(ret==SOCKET_ERROR) {
1051 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1054 *sockaddr=create_object_from_sockaddr(sa, sa_size);
1060 gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
1067 MONO_ARCH_SAVE_REGS;
1069 alen=mono_array_length(buffer);
1070 if(offset+count>alen) {
1075 g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
1078 buf=mono_array_addr(buffer, guchar, offset);
1081 g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
1084 ret = _wapi_send (sock, buf, count, sendflags);
1085 if(ret==SOCKET_ERROR) {
1086 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1092 gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr)
1098 struct sockaddr *sa;
1101 MONO_ARCH_SAVE_REGS;
1103 alen=mono_array_length(buffer);
1104 if(offset+count>alen) {
1108 sa=create_sockaddr_from_object(sockaddr, &sa_size);
1111 g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
1114 buf=mono_array_addr(buffer, guchar, offset);
1117 g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
1120 ret = _wapi_sendto (sock, buf, count, sendflags, sa, sa_size);
1123 if(ret==SOCKET_ERROR) {
1124 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1130 static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
1133 MonoClassField *field;
1135 field=mono_class_get_field_from_name(sockobj->vtable->klass, "socket");
1136 sock=*(SOCKET *)(((char *)sockobj)+field->offset);
1141 void ves_icall_System_Net_Sockets_Socket_Select_internal(MonoArray **read_socks, MonoArray **write_socks, MonoArray **err_socks, gint32 timeout)
1143 fd_set readfds, writefds, errfds;
1144 fd_set *readptr = NULL, *writeptr = NULL, *errptr = NULL;
1148 int readarrsize = 0, writearrsize = 0, errarrsize = 0;
1149 MonoDomain *domain=mono_domain_get();
1150 MonoClass *sock_arr_class;
1156 MONO_ARCH_SAVE_REGS;
1159 readarrsize=mono_array_length(*read_socks);
1161 if(readarrsize>FD_SETSIZE) {
1162 mono_raise_exception(get_socket_exception(WSAEFAULT));
1169 for(i=0; i<readarrsize; i++) {
1170 handle = Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i));
1171 _wapi_FD_SET(handle, &readfds);
1176 writearrsize=mono_array_length(*write_socks);
1178 if(writearrsize>FD_SETSIZE) {
1179 mono_raise_exception(get_socket_exception(WSAEFAULT));
1184 writeptr = &writefds;
1186 for(i=0; i<writearrsize; i++) {
1187 handle = Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i));
1188 _wapi_FD_SET(handle, &writefds);
1193 errarrsize=mono_array_length(*err_socks);
1195 if(errarrsize>FD_SETSIZE) {
1196 mono_raise_exception(get_socket_exception(WSAEFAULT));
1203 for(i=0; i<errarrsize; i++) {
1204 handle = Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i));
1205 _wapi_FD_SET(handle, &errfds);
1209 /* Negative timeout meaning block until ready is only
1210 * specified in Poll, not Select
1213 divvy = div (timeout, 1000000);
1217 tv.tv_sec=divvy.quot;
1218 tv.tv_usec=divvy.rem;
1220 ret = _wapi_select (0, readptr, writeptr, errptr, &tv);
1222 ret = _wapi_select (0, readptr, writeptr, errptr, NULL);
1224 } while ((ret==SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR));
1226 if(ret==SOCKET_ERROR) {
1227 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1232 sock_arr_class=((MonoObject *)*read_socks)->vtable->klass;
1235 for(i=0; i<readarrsize; i++) {
1236 if(_wapi_FD_ISSET(Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i)), &readfds)) {
1240 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1242 for(i=0; i<readarrsize; i++) {
1243 MonoObject *sock=mono_array_get(*read_socks, MonoObject *, i);
1245 if(_wapi_FD_ISSET(Socket_to_SOCKET(sock), &readfds)) {
1246 mono_array_set(socks, MonoObject *, count, sock);
1256 sock_arr_class=((MonoObject *)*write_socks)->vtable->klass;
1258 for(i=0; i<writearrsize; i++) {
1259 if(_wapi_FD_ISSET(Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i)), &writefds)) {
1263 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1265 for(i=0; i<writearrsize; i++) {
1266 MonoObject *sock=mono_array_get(*write_socks, MonoObject *, i);
1268 if(_wapi_FD_ISSET(Socket_to_SOCKET(sock), &writefds)) {
1269 mono_array_set(socks, MonoObject *, count, sock);
1275 *write_socks = NULL;
1279 sock_arr_class=((MonoObject *)*err_socks)->vtable->klass;
1281 for(i=0; i<errarrsize; i++) {
1282 if(_wapi_FD_ISSET(Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i)), &errfds)) {
1286 socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1288 for(i=0; i<errarrsize; i++) {
1289 MonoObject *sock=mono_array_get(*err_socks, MonoObject *, i);
1291 if(_wapi_FD_ISSET(Socket_to_SOCKET(sock), &errfds)) {
1292 mono_array_set(socks, MonoObject *, count, sock);
1300 static MonoObject* int_to_object (MonoDomain *domain, int val)
1302 /* construct an Int32 object to hold val */
1303 MonoObject* obj = mono_object_new(domain, mono_defaults.int32_class);
1305 /* Locate and set the "value" field */
1306 MonoClassField *field = mono_class_get_field_from_name(mono_defaults.int32_class,
1308 *(gint32 *)(((char *)obj)+field->offset)=val;
1313 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val)
1319 int valsize=sizeof(val);
1320 struct linger linger;
1321 int lingersize=sizeof(linger);
1323 int tvsize=sizeof(tv);
1324 MonoDomain *domain=mono_domain_get();
1326 MonoClass *obj_class;
1327 MonoClassField *field;
1329 MONO_ARCH_SAVE_REGS;
1331 ret=convert_sockopt_level_and_name(level, name, &system_level,
1334 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1338 /* No need to deal with MulticastOption names here, because
1339 * you cant getsockopt AddMembership or DropMembership (the
1340 * int getsockopt will error, causing an exception)
1343 case SocketOptionName_Linger:
1344 case SocketOptionName_DontLinger:
1345 ret = _wapi_getsockopt(sock, system_level, system_name, &linger,
1349 case SocketOptionName_SendTimeout:
1350 case SocketOptionName_ReceiveTimeout:
1351 ret = _wapi_getsockopt (sock, system_level, system_name, &tv,
1356 ret = _wapi_getsockopt (sock, system_level, system_name, &val,
1360 if(ret==SOCKET_ERROR) {
1361 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1366 case SocketOptionName_Linger:
1367 /* build a System.Net.Sockets.LingerOption */
1368 obj_class=mono_class_from_name(system_assembly,
1369 "System.Net.Sockets",
1371 obj=mono_object_new(domain, obj_class);
1373 /* Locate and set the fields "bool enabled" and "int
1376 field=mono_class_get_field_from_name(obj_class, "enabled");
1377 *(guint8 *)(((char *)obj)+field->offset)=linger.l_onoff;
1379 field=mono_class_get_field_from_name(obj_class, "seconds");
1380 *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
1384 case SocketOptionName_DontLinger:
1385 /* construct a bool int in val - true if linger is off */
1386 obj = int_to_object (domain, !linger.l_onoff);
1389 case SocketOptionName_SendTimeout:
1390 case SocketOptionName_ReceiveTimeout:
1391 obj = int_to_object (domain, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
1395 obj = int_to_object (domain, val);
1401 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal(SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val)
1409 MONO_ARCH_SAVE_REGS;
1411 ret=convert_sockopt_level_and_name(level, name, &system_level,
1414 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1418 valsize=mono_array_length(*byte_val);
1419 buf=mono_array_addr(*byte_val, guchar, 0);
1421 ret = _wapi_getsockopt (sock, system_level, system_name, buf, &valsize);
1422 if(ret==SOCKET_ERROR) {
1423 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1427 static struct in_addr ipaddress_to_struct_in_addr(MonoObject *ipaddr)
1429 struct in_addr inaddr;
1430 MonoClassField *field;
1432 field=mono_class_get_field_from_name(ipaddr->vtable->klass, "address");
1434 /* No idea why .net uses a 64bit type to hold a 32bit value...
1436 * Internal value of IPAddess is in Network Order, there is no need
1437 * to call htonl here.
1439 inaddr.s_addr=(guint32)*(guint64 *)(((char *)ipaddr)+field->offset);
1445 static struct in6_addr ipaddress_to_struct_in6_addr(MonoObject *ipaddr)
1447 struct in6_addr in6addr;
1448 MonoClassField *field;
1452 field=mono_class_get_field_from_name(ipaddr->vtable->klass, "_numbers");
1453 data=*(MonoArray **)(((char *)ipaddr) + field->offset);
1455 /* Solaris has only the 8 bit version. */
1457 for(i=0; i<8; i++) {
1458 guint16 s = mono_array_get (data, guint16, i);
1459 in6addr.s6_addr[2 * i] = (s >> 8) & 0xff;
1460 in6addr.s6_addr[2 * i + 1] = s & 0xff;
1464 in6addr.s6_addr16[i] = mono_array_get (data, guint16, i);
1468 #endif /* AF_INET6 */
1470 void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val)
1479 #ifdef HAVE_SOL_IPV6
1480 sol_ipv6 = SOL_IPV6;
1483 struct protoent *pent;
1484 pent = getprotobyname ("ipv6");
1485 sol_ipv6 = (pent != NULL) ? pent->p_proto : 41;
1493 struct protoent *pent;
1494 pent = getprotobyname ("ip");
1495 sol_ip = (pent != NULL) ? pent->p_proto : 0;
1498 #endif /* AF_INET6 */
1500 MONO_ARCH_SAVE_REGS;
1502 ret=convert_sockopt_level_and_name(level, name, &system_level,
1505 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1509 /* Only one of obj_val, byte_val or int_val has data */
1511 MonoClassField *field;
1512 struct linger linger;
1516 case SocketOptionName_DontLinger:
1519 valsize=sizeof(linger);
1520 ret = _wapi_setsockopt (sock, system_level, system_name,
1524 case SocketOptionName_Linger:
1525 /* Dig out "bool enabled" and "int seconds"
1528 field=mono_class_get_field_from_name(obj_val->vtable->klass, "enabled");
1529 linger.l_onoff=*(guint8 *)(((char *)obj_val)+field->offset);
1530 field=mono_class_get_field_from_name(obj_val->vtable->klass, "seconds");
1531 linger.l_linger=*(guint32 *)(((char *)obj_val)+field->offset);
1533 valsize=sizeof(linger);
1534 ret = _wapi_setsockopt (sock, system_level, system_name,
1537 case SocketOptionName_AddMembership:
1538 case SocketOptionName_DropMembership:
1539 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
1541 MonoObject *address = NULL;
1544 if(system_level == sol_ipv6) {
1545 struct ipv6_mreq mreq6;
1550 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
1551 address = *(gpointer *)(((char *)obj_val) + field->offset);
1554 mreq6.ipv6mr_multiaddr = ipaddress_to_struct_in6_addr (address);
1557 field=mono_class_get_field_from_name(obj_val->vtable->klass, "ifIndex");
1558 mreq6.ipv6mr_interface =*(guint64 *)(((char *)obj_val)+field->offset);
1560 ret = _wapi_setsockopt (sock, system_level,
1561 system_name, &mreq6,
1563 } else if(system_level == sol_ip)
1564 #endif /* AF_INET6 */
1566 #ifdef HAVE_STRUCT_IP_MREQN
1567 struct ip_mreqn mreq = {{0}};
1569 struct ip_mreq mreq = {{0}};
1570 #endif /* HAVE_STRUCT_IP_MREQN */
1572 /* pain! MulticastOption holds two IPAddress
1573 * members, so I have to dig the value out of
1576 field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
1577 address = *(gpointer *)(((char *)obj_val) + field->offset);
1579 /* address might not be defined and if so, set the address to ADDR_ANY.
1582 mreq.imr_multiaddr = ipaddress_to_struct_in_addr (address);
1585 field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
1586 address = *(gpointer *)(((char *)obj_val) + field->offset);
1588 #ifdef HAVE_STRUCT_IP_MREQN
1590 mreq.imr_address = ipaddress_to_struct_in_addr (address);
1594 mreq.imr_interface = ipaddress_to_struct_in_addr (address);
1596 #endif /* HAVE_STRUCT_IP_MREQN */
1598 ret = _wapi_setsockopt (sock, system_level,
1604 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
1606 /* Throw an exception */
1607 mono_raise_exception(get_socket_exception(WSAEINVAL));
1609 } else if (byte_val!=NULL) {
1610 int valsize=mono_array_length(byte_val);
1611 guchar *buf=mono_array_addr(byte_val, guchar, 0);
1613 ret = _wapi_setsockopt (sock, system_level, system_name, buf, valsize);
1614 if(ret==SOCKET_ERROR) {
1615 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1619 case SocketOptionName_SendTimeout:
1620 case SocketOptionName_ReceiveTimeout: {
1622 tv.tv_sec = int_val / 1000;
1623 tv.tv_usec = (int_val % 1000) * 1000;
1624 ret = _wapi_setsockopt (sock, system_level, system_name, &tv, sizeof (tv));
1628 ret = _wapi_setsockopt (sock, system_level, system_name, &int_val,
1633 if(ret==SOCKET_ERROR) {
1634 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1638 void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock,
1643 MONO_ARCH_SAVE_REGS;
1645 /* Currently, the values for how (recv=0, send=1, both=2) match
1648 ret = _wapi_shutdown (sock, how);
1649 if(ret==SOCKET_ERROR) {
1650 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1655 static gboolean hostent_to_IPHostEntry(struct hostent *he, MonoString **h_name,
1656 MonoArray **h_aliases,
1657 MonoArray **h_addr_list)
1659 MonoDomain *domain = mono_domain_get ();
1662 if(he->h_length!=4 || he->h_addrtype!=AF_INET) {
1666 *h_name=mono_string_new(domain, he->h_name);
1669 while(he->h_aliases[i]!=NULL) {
1673 *h_aliases=mono_array_new(domain, mono_defaults.string_class, i);
1675 while(he->h_aliases[i]!=NULL) {
1678 alias=mono_string_new(domain, he->h_aliases[i]);
1679 mono_array_set(*h_aliases, MonoString *, i, alias);
1684 while(he->h_addr_list[i]!=NULL) {
1688 *h_addr_list=mono_array_new(domain, mono_defaults.string_class, i);
1690 while(he->h_addr_list[i]!=NULL) {
1691 MonoString *addr_string;
1694 g_snprintf(addr, 16, "%u.%u.%u.%u",
1695 (unsigned char)he->h_addr_list[i][0],
1696 (unsigned char)he->h_addr_list[i][1],
1697 (unsigned char)he->h_addr_list[i][2],
1698 (unsigned char)he->h_addr_list[i][3]);
1700 addr_string=mono_string_new(domain, addr);
1701 mono_array_set(*h_addr_list, MonoString *, i, addr_string);
1709 #if defined(AF_INET6) && defined(HAVE_GETHOSTBYNAME2_R)
1710 static gboolean hostent_to_IPHostEntry2(struct hostent *he1,struct hostent *he2, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1712 MonoDomain *domain = mono_domain_get ();
1713 int i, host_count, host_index, family_hint;
1715 family_hint = get_family_hint ();
1717 if(he1 == NULL && he2 == NULL) {
1722 * Check if address length and family are correct
1724 if (he1 != NULL && (he1->h_length!=4 || he1->h_addrtype!=AF_INET)) {
1728 if (he2 != NULL && (he2->h_length!=16 || he2->h_addrtype!=AF_INET6)) {
1733 * Get the aliases and host name from he1 or he2 whichever is
1734 * not null, if he1 is not null then take aliases from he1
1736 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1737 family_hint == PF_INET)) {
1738 *h_name=mono_string_new (domain, he1->h_name);
1741 while(he1->h_aliases[i]!=NULL) {
1745 *h_aliases=mono_array_new (domain, mono_defaults.string_class,
1748 while(he1->h_aliases[i]!=NULL) {
1751 alias=mono_string_new (domain, he1->h_aliases[i]);
1752 mono_array_set (*h_aliases, MonoString *, i, alias);
1755 } else if (family_hint == PF_UNSPEC || family_hint == PF_INET6) {
1756 *h_name=mono_string_new (domain, he2->h_name);
1759 while(he2->h_aliases [i] != NULL) {
1763 *h_aliases=mono_array_new (domain, mono_defaults.string_class,
1766 while(he2->h_aliases[i]!=NULL) {
1769 alias=mono_string_new (domain, he2->h_aliases[i]);
1770 mono_array_set (*h_aliases, MonoString *, i, alias);
1776 * Count the number of addresses in he1 + he2
1779 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1780 family_hint == PF_INET)) {
1782 while(he1->h_addr_list[i]!=NULL) {
1788 if (he2 != NULL && (family_hint == PF_UNSPEC ||
1789 family_hint == PF_INET6)) {
1791 while(he2->h_addr_list[i]!=NULL) {
1800 *h_addr_list=mono_array_new (domain, mono_defaults.string_class,
1805 if (he2 != NULL && (family_hint == PF_UNSPEC ||
1806 family_hint == PF_INET6)) {
1808 while(he2->h_addr_list[i] != NULL) {
1809 MonoString *addr_string;
1812 inet_ntop (AF_INET6, he2->h_addr_list[i], addr,
1815 addr_string = mono_string_new (domain, addr);
1816 mono_array_set (*h_addr_list, MonoString *, host_index,
1823 if (he1 != NULL && (family_hint == PF_UNSPEC ||
1824 family_hint == PF_INET)) {
1826 while(he1->h_addr_list[i] != NULL) {
1827 MonoString *addr_string;
1830 inet_ntop (AF_INET, he1->h_addr_list[i], addr,
1833 addr_string=mono_string_new (domain, addr);
1834 mono_array_set (*h_addr_list, MonoString *, host_index,
1845 #if defined(AF_INET6)
1847 addrinfo_to_IPHostEntry(struct addrinfo *info, MonoString **h_name,
1848 MonoArray **h_aliases,
1849 MonoArray **h_addr_list)
1852 struct addrinfo *ai = NULL;
1854 MonoDomain *domain = mono_domain_get ();
1856 for (count=0, ai=info; ai!=NULL; ai=ai->ai_next) {
1857 if((ai->ai_family != PF_INET) && (ai->ai_family != PF_INET6)) {
1864 *h_aliases=mono_array_new(domain, mono_defaults.string_class, 0);
1865 *h_addr_list=mono_array_new(domain, mono_defaults.string_class, count);
1867 for (ai=info, i=0; ai!=NULL; ai=ai->ai_next) {
1868 MonoString *addr_string;
1871 gint32 buffer_size = 0;
1873 if((ai->ai_family != PF_INET) && (ai->ai_family != PF_INET6)) {
1879 buffer = g_malloc0(buffer_size);
1881 if(ai->ai_family == PF_INET) {
1882 ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in*)ai->ai_addr)->sin_addr), buffer, buffer_size);
1884 ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr), buffer, buffer_size);
1891 } while(ret == 0 && errno == ENOSPC);
1894 addr_string=mono_string_new(domain, buffer);
1897 addr_string=mono_string_new(domain, "");
1900 mono_array_set(*h_addr_list, MonoString *, i, addr_string);
1903 *h_name=mono_string_new(domain, ai->ai_canonname);
1918 MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1920 #if !defined(HAVE_GETHOSTBYNAME2_R)
1921 struct addrinfo *info = NULL, hints;
1924 MONO_ARCH_SAVE_REGS;
1926 hostname=mono_string_to_utf8 (host);
1928 memset(&hints, 0, sizeof(hints));
1929 hints.ai_family = get_family_hint ();
1930 hints.ai_socktype = SOCK_STREAM;
1931 hints.ai_flags = AI_CANONNAME;
1933 if (getaddrinfo(hostname, NULL, &hints, &info) == -1) {
1939 return(addrinfo_to_IPHostEntry(info, h_name, h_aliases, h_addr_list));
1941 struct hostent he1,*hp1, he2, *hp2;
1942 int buffer_size1, buffer_size2;
1943 char *buffer1, *buffer2;
1945 gboolean return_value;
1948 MONO_ARCH_SAVE_REGS;
1950 hostname=mono_string_to_utf8 (host);
1954 buffer1 = g_malloc0(buffer_size1);
1955 buffer2 = g_malloc0(buffer_size2);
1957 while (gethostbyname2_r(hostname, AF_INET, &he1, buffer1, buffer_size1,
1958 &hp1, &herr) == ERANGE) {
1960 buffer1 = g_realloc(buffer1, buffer_size1);
1963 while (gethostbyname2_r(hostname, AF_INET6, &he2, buffer2,
1964 buffer_size2, &hp2, &herr) == ERANGE) {
1966 buffer2 = g_realloc(buffer2, buffer_size2);
1969 return_value = hostent_to_IPHostEntry2(hp1, hp2, h_name, h_aliases,
1975 return(return_value);
1976 #endif /* HAVE_GETHOSTBYNAME2_R */
1978 #else /* AF_INET6 */
1979 MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1984 MONO_ARCH_SAVE_REGS;
1986 hostname=mono_string_to_utf8(host);
1988 he = _wapi_gethostbyname (hostname);
1995 return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
1997 #endif /* AF_INET6 */
1999 #ifndef HAVE_INET_PTON
2001 inet_pton (int family, const char *address, void *inaddrp)
2003 if (family == AF_INET) {
2004 #ifdef HAVE_INET_ATON
2005 struct in_addr inaddr;
2007 if (!inet_aton (address, &inaddr))
2010 memcpy (inaddrp, &inaddr, sizeof (struct in_addr));
2013 /* assume the system has inet_addr(), if it doesn't
2014 have that we're pretty much screwed... */
2017 if (!strcmp (address, "255.255.255.255")) {
2018 /* special-case hack */
2019 inaddr = 0xffffffff;
2021 inaddr = inet_addr (address);
2023 #define INADDR_NONE ((in_addr_t) -1)
2025 if (inaddr == INADDR_NONE)
2029 memcpy (inaddrp, &inaddr, sizeof (guint32));
2031 #endif /* HAVE_INET_ATON */
2036 #endif /* !HAVE_INET_PTON */
2038 extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
2043 struct sockaddr_in saddr;
2044 struct sockaddr_in6 saddr6;
2045 struct addrinfo *info = NULL, hints;
2047 char hostname[1024] = {0};
2049 struct in_addr inaddr;
2053 MONO_ARCH_SAVE_REGS;
2055 address = mono_string_to_utf8 (addr);
2058 if (inet_pton (AF_INET, address, &saddr.sin_addr ) <= 0) {
2059 /* Maybe an ipv6 address */
2060 if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) <= 0) {
2066 saddr6.sin6_family = AF_INET6;
2071 saddr.sin_family = AF_INET;
2075 if(family == AF_INET) {
2076 if(getnameinfo ((struct sockaddr*)&saddr, sizeof(saddr),
2077 hostname, sizeof(hostname), NULL, 0,
2078 NI_NAMEREQD) != 0) {
2081 } else if(family == AF_INET6) {
2082 if(getnameinfo ((struct sockaddr*)&saddr6, sizeof(saddr6),
2083 hostname, sizeof(hostname), NULL, 0,
2084 NI_NAMEREQD) != 0) {
2089 memset (&hints, 0, sizeof(hints));
2090 hints.ai_family = get_family_hint ();
2091 hints.ai_socktype = SOCK_STREAM;
2092 hints.ai_flags = AI_CANONNAME;
2094 if( getaddrinfo (hostname, NULL, &hints, &info) == -1 ) {
2098 return(addrinfo_to_IPHostEntry (info, h_name, h_aliases, h_addr_list));
2100 if (inet_pton (AF_INET, address, &inaddr) <= 0) {
2106 if ((he = gethostbyaddr ((char *) &inaddr, sizeof (inaddr), AF_INET)) == NULL) {
2110 return(hostent_to_IPHostEntry (he, h_name, h_aliases, h_addr_list));
2114 extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name)
2116 guchar hostname[256];
2119 MONO_ARCH_SAVE_REGS;
2121 ret = gethostname (hostname, sizeof (hostname));
2126 *h_name=mono_string_new(mono_domain_get (), hostname);
2132 void mono_network_init(void)
2137 err=WSAStartup(MAKEWORD(2,0), &wsadata);
2139 g_error(G_GNUC_PRETTY_FUNCTION ": Couldn't initialise networking");
2144 g_message(G_GNUC_PRETTY_FUNCTION ": Using socket library: %s", wsadata.szDescription);
2145 g_message(G_GNUC_PRETTY_FUNCTION ": Socket system status: %s", wsadata.szSystemStatus);
2149 void mono_network_cleanup(void)