2003-02-21 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / socket-io.c
1 /*
2  * socket-io.c: Socket IO internal calls
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11
12 #include <glib.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16
17 #include <mono/metadata/object.h>
18 #include <mono/io-layer/io-layer.h>
19 #include <mono/metadata/socket-io.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/metadata/appdomain.h>
22
23 #include <sys/time.h> 
24
25 #ifdef HAVE_NETDB_H
26 #include <netdb.h>
27 #endif
28 #ifdef HAVE_SYS_FILIO_H
29 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
30 #endif
31 #ifdef HAVE_SYS_SOCKIO_H
32 #include <sys/sockio.h>    /* defines SIOCATMARK */
33 #endif
34 #ifdef HAVE_SYS_UN_H
35 #include <sys/un.h>
36 #endif
37
38
39
40 #undef DEBUG
41
42 static gint32 convert_family(MonoAddressFamily mono_family)
43 {
44         gint32 family=-1;
45         
46         switch(mono_family) {
47         case AddressFamily_Unknown:
48         case AddressFamily_ImpLink:
49         case AddressFamily_Pup:
50         case AddressFamily_Chaos:
51         case AddressFamily_Iso:
52         case AddressFamily_Ecma:
53         case AddressFamily_DataKit:
54         case AddressFamily_Ccitt:
55         case AddressFamily_DataLink:
56         case AddressFamily_Lat:
57         case AddressFamily_HyperChannel:
58         case AddressFamily_NetBios:
59         case AddressFamily_VoiceView:
60         case AddressFamily_FireFox:
61         case AddressFamily_Banyan:
62         case AddressFamily_Atm:
63         case AddressFamily_Cluster:
64         case AddressFamily_Ieee12844:
65         case AddressFamily_NetworkDesigners:
66                 g_warning("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family);
67                 break;
68                 
69         case AddressFamily_Unspecified:
70                 family=AF_UNSPEC;
71                 break;
72                 
73         case AddressFamily_Unix:
74                 family=AF_UNIX;
75                 break;
76                 
77         case AddressFamily_InterNetwork:
78                 family=AF_INET;
79                 break;
80                 
81         case AddressFamily_Ipx:
82                 family=AF_IPX;
83                 break;
84                 
85         case AddressFamily_Sna:
86                 family=AF_SNA;
87                 break;
88                 
89         case AddressFamily_DecNet:
90                 family=AF_DECnet;
91                 break;
92                 
93         case AddressFamily_AppleTalk:
94                 family=AF_APPLETALK;
95                 break;
96                 
97         case AddressFamily_InterNetworkV6:
98                 family=AF_INET6;
99                 break;
100 #ifdef AF_IRDA  
101         case AddressFamily_Irda:
102                 family=AF_IRDA;
103                 break;
104 #endif
105         default:
106                 g_warning("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family);
107         }
108
109         return(family);
110 }
111
112 static MonoAddressFamily convert_to_mono_family(guint16 af_family)
113 {
114         MonoAddressFamily family=AddressFamily_Unknown;
115         
116         switch(af_family) {
117         case AF_UNSPEC:
118                 family=AddressFamily_Unspecified;
119                 break;
120                 
121         case AF_UNIX:
122                 family=AddressFamily_Unix;
123                 break;
124                 
125         case AF_INET:
126                 family=AddressFamily_InterNetwork;
127                 break;
128                 
129         case AF_IPX:
130                 family=AddressFamily_Ipx;
131                 break;
132                 
133         case AF_SNA:
134                 family=AddressFamily_Sna;
135                 break;
136                 
137         case AF_DECnet:
138                 family=AddressFamily_DecNet;
139                 break;
140                 
141         case AF_APPLETALK:
142                 family=AddressFamily_AppleTalk;
143                 break;
144                 
145         case AF_INET6:
146                 family=AddressFamily_InterNetworkV6;
147                 break;
148                 
149 #ifdef AF_IRDA  
150         case AF_IRDA:
151                 family=AddressFamily_Irda;
152                 break;
153 #endif
154         default:
155                 g_warning("unknown address family 0x%x", af_family);
156         }
157
158         return(family);
159 }
160
161 static gint32 convert_type(MonoSocketType mono_type)
162 {
163         gint32 type=-1;
164         
165         switch(mono_type) {
166         case SocketType_Stream:
167                 type=SOCK_STREAM;
168                 break;
169
170         case SocketType_Dgram:
171                 type=SOCK_DGRAM;
172                 break;
173                 
174         case SocketType_Raw:
175                 type=SOCK_RAW;
176                 break;
177
178         case SocketType_Rdm:
179                 type=SOCK_RDM;
180                 break;
181
182         case SocketType_Seqpacket:
183                 type=SOCK_SEQPACKET;
184                 break;
185
186         case SocketType_Unknown:
187                 g_warning("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type);
188                 break;
189
190         default:
191                 g_warning("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type);
192         }
193
194         return(type);
195 }
196
197 static gint32 convert_proto(MonoProtocolType mono_proto)
198 {
199         gint32 proto=-1;
200         
201         switch(mono_proto) {
202         case ProtocolType_IP:
203         case ProtocolType_Icmp:
204         case ProtocolType_Igmp:
205         case ProtocolType_Ggp:
206         case ProtocolType_Tcp:
207         case ProtocolType_Pup:
208         case ProtocolType_Udp:
209         case ProtocolType_Idp:
210                 /* These protocols are known (on my system at least) */
211                 proto=mono_proto;
212                 break;
213                 
214         case ProtocolType_ND:
215         case ProtocolType_Raw:
216         case ProtocolType_Ipx:
217         case ProtocolType_Spx:
218         case ProtocolType_SpxII:
219         case ProtocolType_Unknown:
220                 /* These protocols arent */
221                 g_warning("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto);
222                 break;
223                 
224         default:
225                 break;
226         }
227
228         return(proto);
229 }
230
231 static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
232                                              MonoSocketOptionName mono_name,
233                                              int *system_level,
234                                              int *system_name)
235 {
236         switch (mono_level) {
237         case SocketOptionLevel_Socket:
238                 *system_level = SOL_SOCKET;
239                 
240                 switch(mono_name) {
241                 case SocketOptionName_DontLinger:
242                         /* This is SO_LINGER, because the setsockopt
243                          * internal call maps DontLinger to SO_LINGER
244                          * with l_onoff=0
245                          */
246                         *system_name = SO_LINGER;
247                         break;
248                 case SocketOptionName_Debug:
249                         *system_name = SO_DEBUG;
250                         break;
251 #ifdef SO_ACCEPTCONN
252                 case SocketOptionName_AcceptConnection:
253                         *system_name = SO_ACCEPTCONN;
254                         break;
255 #endif
256                 case SocketOptionName_ReuseAddress:
257                         *system_name = SO_REUSEADDR;
258                         break;
259                 case SocketOptionName_KeepAlive:
260                         *system_name = SO_KEEPALIVE;
261                         break;
262                 case SocketOptionName_DontRoute:
263                         *system_name = SO_DONTROUTE;
264                         break;
265                 case SocketOptionName_Broadcast:
266                         *system_name = SO_BROADCAST;
267                         break;
268                 case SocketOptionName_Linger:
269                         *system_name = SO_LINGER;
270                         break;
271                 case SocketOptionName_OutOfBandInline:
272                         *system_name = SO_OOBINLINE;
273                         break;
274                 case SocketOptionName_SendBuffer:
275                         *system_name = SO_SNDBUF;
276                         break;
277                 case SocketOptionName_ReceiveBuffer:
278                         *system_name = SO_RCVBUF;
279                         break;
280                 case SocketOptionName_SendLowWater:
281                         *system_name = SO_SNDLOWAT;
282                         break;
283                 case SocketOptionName_ReceiveLowWater:
284                         *system_name = SO_RCVLOWAT;
285                         break;
286                 case SocketOptionName_SendTimeout:
287                         *system_name = SO_SNDTIMEO;
288                         break;
289                 case SocketOptionName_ReceiveTimeout:
290                         *system_name = SO_RCVTIMEO;
291                         break;
292                 case SocketOptionName_Error:
293                         *system_name = SO_ERROR;
294                         break;
295                 case SocketOptionName_Type:
296                         *system_name = SO_TYPE;
297                         break;
298                 case SocketOptionName_ExclusiveAddressUse:
299                 case SocketOptionName_UseLoopback:
300                 case SocketOptionName_MaxConnections:
301                         /* Can't figure out how to map these, so fall
302                          * through
303                          */
304                 default:
305                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name);
306                         return(-1);
307                 }
308                 break;
309                 
310         case SocketOptionLevel_IP:
311 #ifdef HAVE_SOL_IP
312                 *system_level = SOL_IP;
313 #else
314                 if (1) {
315                         static int cached = 0;
316                         static int proto;
317                         
318                         if (!cached) {
319                                 struct protoent *pent;
320                                 
321                                 pent = getprotobyname ("IP");
322                                 proto = pent ? pent->p_proto : 0 /* 0 a good default value?? */;
323                                 cached = 1;
324                         }
325                         
326                         *system_level = proto;
327                 }
328 #endif /* HAVE_SOL_IP */
329                 
330                 switch(mono_name) {
331                 case SocketOptionName_IPOptions:
332                         *system_name = IP_OPTIONS;
333                         break;
334 #ifdef IP_HDRINCL
335                 case SocketOptionName_HeaderIncluded:
336                         *system_name = IP_HDRINCL;
337                         break;
338 #endif
339 #ifdef IP_TOS
340                 case SocketOptionName_TypeOfService:
341                         *system_name = IP_TOS;
342                         break;
343 #endif
344 #ifdef IP_TTL
345                 case SocketOptionName_IpTimeToLive:
346                         *system_name = IP_TTL;
347                         break;
348 #endif
349                 case SocketOptionName_MulticastInterface:
350                         *system_name = IP_MULTICAST_IF;
351                         break;
352                 case SocketOptionName_MulticastTimeToLive:
353                         *system_name = IP_MULTICAST_TTL;
354                         break;
355                 case SocketOptionName_MulticastLoopback:
356                         *system_name = IP_MULTICAST_LOOP;
357                         break;
358                 case SocketOptionName_AddMembership:
359                         *system_name = IP_ADD_MEMBERSHIP;
360                         break;
361                 case SocketOptionName_DropMembership:
362                         *system_name = IP_DROP_MEMBERSHIP;
363                         break;
364 #ifdef HAVE_IP_PKTINFO
365                 case SocketOptionName_PacketInformation:
366                         *system_name = IP_PKTINFO;
367                         break;
368 #endif /* HAVE_IP_PKTINFO */
369                 case SocketOptionName_DontFragment:
370                 case SocketOptionName_AddSourceMembership:
371                 case SocketOptionName_DropSourceMembership:
372                 case SocketOptionName_BlockSource:
373                 case SocketOptionName_UnblockSource:
374                         /* Can't figure out how to map these, so fall
375                          * through
376                          */
377                 default:
378                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name);
379                         return(-1);
380                 }
381                 break;
382                 
383         case SocketOptionLevel_Tcp:
384 #ifdef HAVE_SOL_TCP
385                 *system_level = SOL_TCP;
386 #else
387                 if (1) {
388                         static int cached = 0;
389                         static int proto;
390                         
391                         if (!cached) {
392                                 struct protoent *pent;
393                                 
394                                 pent = getprotobyname ("TCP");
395                                 proto = pent ? pent->p_proto : 6 /* is 6 a good default value?? */;
396                                 cached = 1;
397                         }
398                         
399                         *system_level = proto;
400                 }
401 #endif /* HAVE_SOL_TCP */
402                 
403                 switch(mono_name) {
404                 case SocketOptionName_NoDelay:
405                         *system_name = TCP_NODELAY;
406                         break;
407 #if 0
408                         /* The documentation is talking complete
409                          * bollocks here: rfc-1222 is titled
410                          * 'Advancing the NSFNET Routing Architecture'
411                          * and doesn't mention either of the words
412                          * "expedite" or "urgent".
413                          */
414                 case SocketOptionName_BsdUrgent:
415                 case SocketOptionName_Expedited:
416 #endif
417                 default:
418                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name);
419                         return(-1);
420                 }
421                 break;
422                 
423         case SocketOptionLevel_Udp:
424                 g_warning("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level);
425
426                 switch(mono_name) {
427                 case SocketOptionName_NoChecksum:
428                 case SocketOptionName_ChecksumCoverage:
429                 default:
430                         g_warning("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name);
431                         return(-1);
432                 }
433                 return(-1);
434                 break;
435
436         default:
437                 g_warning("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level);
438                 return(-1);
439         }
440
441         return(0);
442 }
443
444 #define STASH_SYS_ASS(this) \
445         if(system_assembly == NULL) { \
446                 system_assembly=this->vtable->klass->image; \
447         }
448
449 static MonoImage *system_assembly=NULL;
450
451 static MonoException *get_socket_exception(guint32 error_code)
452 {
453         /* Don't cache this exception, because we need the object
454          * constructor to set up the message from the sockets error code.
455          */
456         MonoException *ex;
457         
458         /* This is a bit of a kludge.  The SocketException 0-arg
459          * constructor calls WSAGetLastError() to find the error code
460          * to use.  Until we can init objects with parameters, this
461          * will have to do.
462          */
463         WSASetLastError(error_code);
464         
465         ex=(MonoException *)mono_exception_from_name(system_assembly,
466                                                      "System.Net.Sockets",
467                                                      "SocketException");
468         return(ex);
469 }
470
471 gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto)
472 {
473         SOCKET sock;
474         gint32 sock_family;
475         gint32 sock_proto;
476         gint32 sock_type;
477         int ret;
478         int true=1;
479         
480         MONO_ARCH_SAVE_REGS;
481
482         STASH_SYS_ASS(this);
483         
484         sock_family=convert_family(family);
485         if(sock_family==-1) {
486                 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
487                 return(NULL);
488         }
489
490         sock_proto=convert_proto(proto);
491         if(sock_proto==-1) {
492                 mono_raise_exception(get_socket_exception(WSAEPROTONOSUPPORT));
493                 return(NULL);
494         }
495         
496         sock_type=convert_type(type);
497         if(sock_type==-1) {
498                 mono_raise_exception(get_socket_exception(WSAESOCKTNOSUPPORT));
499                 return(NULL);
500         }
501         
502         sock=socket(sock_family, sock_type, sock_proto);
503         if(sock==INVALID_SOCKET) {
504                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
505                 return(NULL);
506         }
507
508         if (sock_family == AF_INET && sock_type == SOCK_DGRAM)
509                 return (GUINT_TO_POINTER (sock));
510
511         /* .net seems to set this by default for SOCK_STREAM,
512          * not for SOCK_DGRAM (see bug #36322) */
513         ret=setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(true));
514         if(ret==SOCKET_ERROR) {
515                 closesocket(sock);
516                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
517                 return(NULL);
518         }
519         
520         return(GUINT_TO_POINTER (sock));
521 }
522
523 /* FIXME: the SOCKET parameter (here and in other functions in this
524  * file) is really an IntPtr which needs to be converted to a guint32.
525  */
526 void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock)
527 {
528         MONO_ARCH_SAVE_REGS;
529
530 #ifdef DEBUG
531         g_message (G_GNUC_PRETTY_FUNCTION ": closing 0x%x", sock);
532 #endif
533
534         closesocket(sock);
535 }
536
537 gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void)
538 {
539         MONO_ARCH_SAVE_REGS;
540
541 #ifdef DEBUG
542         g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", WSAGetLastError());
543 #endif
544
545         return(WSAGetLastError());
546 }
547
548 gint32 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock)
549 {
550         int ret, amount;
551         
552         MONO_ARCH_SAVE_REGS;
553
554         ret=ioctlsocket(sock, FIONREAD, &amount);
555         if(ret==SOCKET_ERROR) {
556                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
557                 return(0);
558         }
559         
560         return(amount);
561 }
562
563 void ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock,
564                                                            gboolean block)
565 {
566         int ret;
567         
568         MONO_ARCH_SAVE_REGS;
569
570         ret=ioctlsocket(sock, FIONBIO, &block);
571         if(ret==SOCKET_ERROR) {
572                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
573         }
574 }
575
576 gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock)
577 {
578         SOCKET newsock;
579         
580         MONO_ARCH_SAVE_REGS;
581
582         newsock=accept(sock, NULL, 0);
583         if(newsock==INVALID_SOCKET) {
584                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
585                 return(NULL);
586         }
587         
588         return(GUINT_TO_POINTER (newsock));
589 }
590
591 void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock,
592                                                          guint32 backlog)
593 {
594         int ret;
595         
596         MONO_ARCH_SAVE_REGS;
597
598         ret=listen(sock, backlog);
599         if(ret==SOCKET_ERROR) {
600                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
601         }
602 }
603
604 static MonoObject *create_object_from_sockaddr(struct sockaddr *saddr,
605                                                int sa_size)
606 {
607         MonoDomain *domain = mono_domain_get ();
608         MonoObject *sockaddr_obj;
609         MonoClass *sockaddr_class;
610         MonoClassField *field;
611         MonoArray *data;
612         MonoAddressFamily family;
613
614         /* Build a System.Net.SocketAddress object instance */
615         sockaddr_class=mono_class_from_name(system_assembly, "System.Net", "SocketAddress");
616         sockaddr_obj=mono_object_new(domain, sockaddr_class);
617         
618         /* Locate the SocketAddress data buffer in the object */
619         field=mono_class_get_field_from_name(sockaddr_class, "data");
620
621         /* Make sure there is space for the family and size bytes */
622         data=mono_array_new(domain, mono_defaults.byte_class, sa_size+2);
623
624         /* The data buffer is laid out as follows:
625          * byte 0 is the address family
626          * byte 1 is the buffer length
627          * bytes 2 and 3 are the port info
628          * the rest is the address info
629          */
630                 
631         family=convert_to_mono_family(saddr->sa_family);
632         if(family==AddressFamily_Unknown) {
633                 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
634                 return(NULL);
635         }
636
637         mono_array_set(data, guint8, 0, family & 0x0FF);
638         mono_array_set(data, guint8, 1, ((family << 8) & 0x0FFFF));
639         
640         if(saddr->sa_family==AF_INET) {
641                 struct sockaddr_in *sa_in=(struct sockaddr_in *)saddr;
642                 guint16 port=ntohs(sa_in->sin_port);
643                 guint32 address=ntohl(sa_in->sin_addr.s_addr);
644                 
645                 if(sa_size<8) {
646                         mono_raise_exception((MonoException *)mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
647                 }
648                 
649                 mono_array_set(data, guint8, 2, (port>>8) & 0xff);
650                 mono_array_set(data, guint8, 3, (port) & 0xff);
651                 mono_array_set(data, guint8, 4, (address>>24) & 0xff);
652                 mono_array_set(data, guint8, 5, (address>>16) & 0xff);
653                 mono_array_set(data, guint8, 6, (address>>8) & 0xff);
654                 mono_array_set(data, guint8, 7, (address) & 0xff);
655                 
656                 *(MonoArray **)(((char *)sockaddr_obj) + field->offset)=data;
657
658                 return(sockaddr_obj);
659 #ifdef HAVE_SYS_UN_H
660         } else if (saddr->sa_family == AF_UNIX) {
661                 int i;
662
663                 for (i = 0; i < sa_size; i++)
664                         mono_array_set (data, guint8, i + 2, saddr->sa_data [i]);
665                 
666                 *(MonoArray **)(((char *)sockaddr_obj) + field->offset) = data;
667
668                 return sockaddr_obj;
669 #endif
670         } else {
671                 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
672                 return(NULL);
673         }
674 }
675
676 extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock)
677 {
678         struct sockaddr sa;
679         int salen;
680         int ret;
681         
682         MONO_ARCH_SAVE_REGS;
683
684         salen=sizeof(struct sockaddr);
685         ret=getsockname(sock, &sa, &salen);
686         
687         if(ret==SOCKET_ERROR) {
688                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
689         }
690         
691 #ifdef DEBUG
692         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));
693 #endif
694
695         return(create_object_from_sockaddr(&sa, salen));
696 }
697
698 extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock)
699 {
700         struct sockaddr sa;
701         int salen;
702         int ret;
703         
704         MONO_ARCH_SAVE_REGS;
705
706         salen=sizeof(struct sockaddr);
707         ret=getpeername(sock, &sa, &salen);
708         
709         if(ret==SOCKET_ERROR) {
710                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
711         }
712         
713 #ifdef DEBUG
714         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));
715 #endif
716
717         return(create_object_from_sockaddr(&sa, salen));
718 }
719
720 static struct sockaddr *create_sockaddr_from_object(MonoObject *saddr_obj,
721                                                     int *sa_size)
722 {
723         MonoClassField *field;
724         MonoArray *data;
725         gint32 family;
726         int len;
727
728         /* Dig the SocketAddress data buffer out of the object */
729         field=mono_class_get_field_from_name(saddr_obj->vtable->klass, "data");
730         data=*(MonoArray **)(((char *)saddr_obj) + field->offset);
731
732         /* The data buffer is laid out as follows:
733          * byte 0 is the address family low byte
734          * byte 1 is the address family high byte
735          * INET:
736          *      bytes 2 and 3 are the port info
737          *      the rest is the address info
738          * UNIX:
739          *      the rest is the file name
740          */
741         len = mono_array_length (data);
742         if (len < 2) {
743                 mono_raise_exception (mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
744         }
745         
746         family = convert_family (mono_array_get (data, guint16, 0));
747         if(family==AF_INET) {
748                 struct sockaddr_in *sa=g_new0(struct sockaddr_in, 1);
749                 guint16 port=(mono_array_get(data, guint8, 2) << 8) +
750                         mono_array_get(data, guint8, 3);
751                 guint32 address=(mono_array_get(data, guint8, 4) << 24) +
752                         (mono_array_get(data, guint8, 5) << 16 ) +
753                         (mono_array_get(data, guint8, 6) << 8) +
754                         mono_array_get(data, guint8, 7);
755                 
756                 sa->sin_family=family;
757                 sa->sin_addr.s_addr=htonl(address);
758                 sa->sin_port=htons(port);
759
760                 *sa_size=sizeof(struct sockaddr_in);
761                 return((struct sockaddr *)sa);
762 #ifdef HAVE_SYS_UN_H
763         } else if (family == AF_UNIX) {
764                 struct sockaddr_un *sun = g_new0 (struct sockaddr_un, 1);
765                 int i;
766
767                 if (len - 2 > MONO_SIZEOF_SUNPATH)
768                         mono_raise_exception (mono_get_exception_index_out_of_range ());
769
770                 sun->sun_family = family;
771                 for (i = 0; i < len - 2; i++)
772                         sun->sun_path [i] = mono_array_get (data, guint8, i + 2);
773                 sun->sun_path [len - 2] = '\0';
774                 *sa_size = sizeof (struct sockaddr_un);
775
776                 return (struct sockaddr *)sun;
777 #endif
778         } else {
779                 mono_raise_exception(get_socket_exception(WSAEAFNOSUPPORT));
780                 return(0);
781         }
782 }
783
784 extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoObject *sockaddr)
785 {
786         struct sockaddr *sa;
787         int sa_size;
788         int ret;
789         
790         MONO_ARCH_SAVE_REGS;
791
792         sa=create_sockaddr_from_object(sockaddr, &sa_size);
793
794 #ifdef DEBUG
795         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));
796 #endif
797         ret=bind(sock, sa, sa_size);
798         g_free(sa);
799         
800         if(ret==SOCKET_ERROR) {
801                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
802         }
803 }
804
805 extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr)
806 {
807         struct sockaddr *sa;
808         int sa_size;
809         int ret;
810         
811         MONO_ARCH_SAVE_REGS;
812
813         sa=create_sockaddr_from_object(sockaddr, &sa_size);
814         
815 #ifdef DEBUG
816         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));
817 #endif
818
819         ret=connect(sock, sa, sa_size);
820         g_free(sa);
821         
822         if(ret==SOCKET_ERROR) {
823                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
824         }
825 }
826
827 gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
828 {
829         int ret;
830         guchar *buf;
831         gint32 alen;
832         int recvflags=0;
833         
834         MONO_ARCH_SAVE_REGS;
835
836         alen=mono_array_length(buffer);
837         if(offset+count>alen) {
838                 return(0);
839         }
840         
841         buf=mono_array_addr(buffer, guchar, offset);
842         
843         ret=recv(sock, buf, count, recvflags);
844         if(ret==SOCKET_ERROR) {
845                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
846         }
847         
848         return(ret);
849 }
850
851 gint32 ves_icall_System_Net_Sockets_Socket_RecvFrom_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject **sockaddr)
852 {
853         int ret;
854         guchar *buf;
855         gint32 alen;
856         int recvflags=0;
857         struct sockaddr *sa;
858         int sa_size;
859         
860         MONO_ARCH_SAVE_REGS;
861
862         alen=mono_array_length(buffer);
863         if(offset+count>alen) {
864                 return(0);
865         }
866
867         sa=create_sockaddr_from_object(*sockaddr, &sa_size);
868         
869         buf=mono_array_addr(buffer, guchar, offset);
870         
871         ret=recvfrom(sock, buf, count, recvflags, sa, &sa_size);
872         
873         if(ret==SOCKET_ERROR) {
874                 g_free(sa);
875                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
876         }
877
878         *sockaddr=create_object_from_sockaddr(sa, sa_size);
879         g_free(sa);
880         
881         return(ret);
882 }
883
884 gint32 ves_icall_System_Net_Sockets_Socket_Send_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags)
885 {
886         int ret;
887         guchar *buf;
888         gint32 alen;
889         int sendflags=0;
890         
891         MONO_ARCH_SAVE_REGS;
892
893         alen=mono_array_length(buffer);
894         if(offset+count>alen) {
895                 return(0);
896         }
897
898 #ifdef DEBUG
899         g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
900 #endif
901         
902         buf=mono_array_addr(buffer, guchar, offset);
903
904 #ifdef DEBUG
905         g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
906 #endif
907
908         ret=send(sock, buf, count, sendflags);
909         if(ret==SOCKET_ERROR) {
910                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
911         }
912         
913         return(ret);
914 }
915
916 gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, MonoObject *sockaddr)
917 {
918         int ret;
919         guchar *buf;
920         gint32 alen;
921         int sendflags=0;
922         struct sockaddr *sa;
923         int sa_size;
924         
925         MONO_ARCH_SAVE_REGS;
926
927         alen=mono_array_length(buffer);
928         if(offset+count>alen) {
929                 return(0);
930         }
931
932         sa=create_sockaddr_from_object(sockaddr, &sa_size);
933         
934 #ifdef DEBUG
935         g_message(G_GNUC_PRETTY_FUNCTION ": alen: %d", alen);
936 #endif
937         
938         buf=mono_array_addr(buffer, guchar, offset);
939
940 #ifdef DEBUG
941         g_message(G_GNUC_PRETTY_FUNCTION ": Sending %d bytes", count);
942 #endif
943
944         ret=sendto(sock, buf, count, sendflags, sa, sa_size);
945         g_free(sa);
946         
947         if(ret==SOCKET_ERROR) {
948                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
949         }
950         
951         return(ret);
952 }
953
954 static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
955 {
956         SOCKET sock;
957         MonoClassField *field;
958         
959         field=mono_class_get_field_from_name(sockobj->vtable->klass, "socket");
960         sock=*(SOCKET *)(((char *)sockobj)+field->offset);
961
962         return(sock);
963 }
964
965 void ves_icall_System_Net_Sockets_Socket_Select_internal(MonoArray **read_socks, MonoArray **write_socks, MonoArray **err_socks, gint32 timeout)
966 {
967         fd_set readfds, writefds, errfds;
968         struct timeval tv;
969         div_t divvy;
970         int ret;
971         int readarrsize, writearrsize, errarrsize;
972         MonoDomain *domain=mono_domain_get();
973         MonoClass *sock_arr_class;
974         MonoArray *socks;
975         int count;
976         int i;
977         
978         MONO_ARCH_SAVE_REGS;
979
980         readarrsize=mono_array_length(*read_socks);
981         if(readarrsize>FD_SETSIZE) {
982                 mono_raise_exception(get_socket_exception(WSAEFAULT));
983                 return;
984         }
985         
986         FD_ZERO(&readfds);
987         for(i=0; i<readarrsize; i++) {
988                 FD_SET(Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i)), &readfds);
989         }
990         
991         writearrsize=mono_array_length(*write_socks);
992         if(writearrsize>FD_SETSIZE) {
993                 mono_raise_exception(get_socket_exception(WSAEFAULT));
994                 return;
995         }
996         
997         FD_ZERO(&writefds);
998         for(i=0; i<writearrsize; i++) {
999                 FD_SET(Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i)), &writefds);
1000         }
1001         
1002         errarrsize=mono_array_length(*err_socks);
1003         if(errarrsize>FD_SETSIZE) {
1004                 mono_raise_exception(get_socket_exception(WSAEFAULT));
1005                 return;
1006         }
1007         
1008         FD_ZERO(&errfds);
1009         for(i=0; i<errarrsize; i++) {
1010                 FD_SET(Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i)), &errfds);
1011         }
1012
1013         /* Negative timeout meaning block until ready is only
1014          * specified in Poll, not Select
1015          */
1016         if(timeout>=0) {
1017                 divvy=div(timeout, 1000000);
1018                 tv.tv_sec=divvy.quot;
1019                 tv.tv_usec=divvy.rem*1000000;
1020         
1021                 ret=select(0, &readfds, &writefds, &errfds, &tv);
1022         } else {
1023                 ret=select(0, &readfds, &writefds, &errfds, NULL);
1024         }
1025         
1026         if(ret==SOCKET_ERROR) {
1027                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1028                 return;
1029         }
1030
1031         sock_arr_class=((MonoObject *)*read_socks)->vtable->klass;
1032         
1033         count=0;
1034         for(i=0; i<readarrsize; i++) {
1035                 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*read_socks, MonoObject *, i)), &readfds)) {
1036                         count++;
1037                 }
1038         }
1039         socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1040         count=0;
1041         for(i=0; i<readarrsize; i++) {
1042                 MonoObject *sock=mono_array_get(*read_socks, MonoObject *, i);
1043                 
1044                 if(FD_ISSET(Socket_to_SOCKET(sock), &readfds)) {
1045                         mono_array_set(socks, MonoObject *, count, sock);
1046                         count++;
1047                 }
1048         }
1049         *read_socks=socks;
1050
1051         count=0;
1052         for(i=0; i<writearrsize; i++) {
1053                 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*write_socks, MonoObject *, i)), &writefds)) {
1054                         count++;
1055                 }
1056         }
1057         socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1058         count=0;
1059         for(i=0; i<writearrsize; i++) {
1060                 MonoObject *sock=mono_array_get(*write_socks, MonoObject *, i);
1061                 
1062                 if(FD_ISSET(Socket_to_SOCKET(sock), &writefds)) {
1063                         mono_array_set(socks, MonoObject *, count, sock);
1064                         count++;
1065                 }
1066         }
1067         *write_socks=socks;
1068
1069         count=0;
1070         for(i=0; i<errarrsize; i++) {
1071                 if(FD_ISSET(Socket_to_SOCKET(mono_array_get(*err_socks, MonoObject *, i)), &errfds)) {
1072                         count++;
1073                 }
1074         }
1075         socks=mono_array_new_full(domain, sock_arr_class, &count, NULL);
1076         count=0;
1077         for(i=0; i<errarrsize; i++) {
1078                 MonoObject *sock=mono_array_get(*err_socks, MonoObject *, i);
1079                 
1080                 if(FD_ISSET(Socket_to_SOCKET(sock), &errfds)) {
1081                         mono_array_set(socks, MonoObject *, count, sock);
1082                         count++;
1083                 }
1084         }
1085         *err_socks=socks;
1086 }
1087
1088 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val)
1089 {
1090         int system_level;
1091         int system_name;
1092         int ret;
1093         int val;
1094         int valsize=sizeof(val);
1095         struct linger linger;
1096         int lingersize=sizeof(linger);
1097         MonoDomain *domain=mono_domain_get();
1098         MonoObject *obj;
1099         MonoClass *obj_class;
1100         MonoClassField *field;
1101         
1102         MONO_ARCH_SAVE_REGS;
1103
1104         ret=convert_sockopt_level_and_name(level, name, &system_level,
1105                                            &system_name);
1106         if(ret==-1) {
1107                 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1108                 return;
1109         }
1110         
1111         /* No need to deal with MulticastOption names here, because
1112          * you cant getsockopt AddMembership or DropMembership (the
1113          * int getsockopt will error, causing an exception)
1114          */
1115         switch(name) {
1116         case SocketOptionName_Linger:
1117         case SocketOptionName_DontLinger:
1118                 ret=getsockopt(sock, system_level, system_name, &linger,
1119                                &lingersize);
1120                 break;
1121                 
1122         default:
1123                 ret=getsockopt(sock, system_level, system_name, &val,
1124                                &valsize);
1125         }
1126         
1127         if(ret==SOCKET_ERROR) {
1128                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1129                 return;
1130         }
1131         
1132         switch(name) {
1133         case SocketOptionName_Linger:
1134                 /* build a System.Net.Sockets.LingerOption */
1135                 obj_class=mono_class_from_name(system_assembly,
1136                                                "System.Net.Sockets",
1137                                                "LingerOption");
1138                 obj=mono_object_new(domain, obj_class);
1139                 
1140                 /* Locate and set the fields "bool enabled" and "int
1141                  * seconds"
1142                  */
1143                 field=mono_class_get_field_from_name(obj_class, "enabled");
1144                 *(guint8 *)(((char *)obj)+field->offset)=linger.l_onoff;
1145
1146                 field=mono_class_get_field_from_name(obj_class, "seconds");
1147                 *(guint32 *)(((char *)obj)+field->offset)=linger.l_linger;
1148                 
1149                 break;
1150                 
1151         case SocketOptionName_DontLinger:
1152                 /* construct a bool int in val - true if linger is off */
1153                 val=!linger.l_onoff;
1154                 
1155                 /* fall through */
1156                 
1157         default:
1158                 /* construct an Int32 object to hold val */
1159                 obj=mono_object_new(domain, mono_defaults.int32_class);
1160                 
1161                 /* Locate and set the "value" field */
1162                 field=mono_class_get_field_from_name(mono_defaults.int32_class,
1163                                                      "value");
1164                 *(gint32 *)(((char *)obj)+field->offset)=val;
1165         }
1166
1167         *obj_val=obj;
1168 }
1169
1170 void ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal(SOCKET sock, gint32 level, gint32 name, MonoArray **byte_val)
1171 {
1172         int system_level;
1173         int system_name;
1174         int ret;
1175         guchar *buf;
1176         int valsize;
1177         
1178         MONO_ARCH_SAVE_REGS;
1179
1180         ret=convert_sockopt_level_and_name(level, name, &system_level,
1181                                            &system_name);
1182         if(ret==-1) {
1183                 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1184                 return;
1185         }
1186
1187         valsize=mono_array_length(*byte_val);
1188         buf=mono_array_addr(*byte_val, guchar, 0);
1189         
1190         ret=getsockopt(sock, system_level, system_name, buf, &valsize);
1191         if(ret==SOCKET_ERROR) {
1192                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1193         }
1194 }
1195
1196 static struct in_addr ipaddress_to_struct_in_addr(MonoObject *ipaddr)
1197 {
1198         struct in_addr inaddr;
1199         guint64 addr;
1200         MonoClassField *field;
1201         
1202         field=mono_class_get_field_from_name(ipaddr->vtable->klass, "address");
1203         addr=*(guint64 *)(((char *)ipaddr)+field->offset);
1204
1205         /* No idea why .net uses a 64bit type to hold a 32bit value */
1206         inaddr.s_addr=htonl((guint32)addr);
1207         
1208         return(inaddr);
1209 }
1210
1211 void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, gint32 level, gint32 name, MonoObject *obj_val, MonoArray *byte_val, gint32 int_val)
1212 {
1213         int system_level;
1214         int system_name;
1215         int ret;
1216
1217         MONO_ARCH_SAVE_REGS;
1218
1219         ret=convert_sockopt_level_and_name(level, name, &system_level,
1220                                            &system_name);
1221         if(ret==-1) {
1222                 mono_raise_exception(get_socket_exception(WSAENOPROTOOPT));
1223                 return;
1224         }
1225
1226         /* Only one of obj_val, byte_val or int_val has data */
1227         if(obj_val!=NULL) {
1228                 MonoClassField *field;
1229                 struct linger linger;
1230                 int valsize;
1231                 
1232                 switch(name) {
1233                 case SocketOptionName_DontLinger:
1234                         linger.l_onoff=0;
1235                         linger.l_linger=0;
1236                         valsize=sizeof(linger);
1237                         ret=setsockopt(sock, system_level, system_name,
1238                                        &linger, valsize);
1239                         break;
1240                         
1241                 case SocketOptionName_Linger:
1242                         /* Dig out "bool enabled" and "int seconds"
1243                          * fields
1244                          */
1245                         field=mono_class_get_field_from_name(obj_val->vtable->klass, "enabled");
1246                         linger.l_onoff=*(guint8 *)(((char *)obj_val)+field->offset);
1247                         field=mono_class_get_field_from_name(obj_val->vtable->klass, "seconds");
1248                         linger.l_linger=*(guint32 *)(((char *)obj_val)+field->offset);
1249                         
1250                         valsize=sizeof(linger);
1251                         ret=setsockopt(sock, system_level, system_name,
1252                                        &linger, valsize);
1253                         break;
1254                 case SocketOptionName_AddMembership:
1255                 case SocketOptionName_DropMembership:
1256                 {
1257 #ifdef HAVE_STRUCT_IP_MREQN
1258                         struct ip_mreqn mreq;
1259 #else
1260                         struct ip_mreq mreq;
1261 #endif /* HAVE_STRUCT_IP_MREQN */
1262                         
1263                         /* pain! MulticastOption holds two IPAddress
1264                          * members, so I have to dig the value out of
1265                          * those :-(
1266                          */
1267                         field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
1268                         mreq.imr_multiaddr = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
1269                                                                                         field->offset));
1270                         field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
1271 #ifdef HAVE_STRUCT_IP_MREQN
1272                         mreq.imr_address = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
1273                                                                                       field->offset));
1274 #else
1275                         mreq.imr_interface = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
1276                                                                                         field->offset));
1277 #endif /* HAVE_STRUCT_IP_MREQN */
1278                         
1279                         ret = setsockopt (sock, system_level, system_name,
1280                                           &mreq, sizeof (mreq));
1281                         break;
1282                 }
1283                 default:
1284                         /* Throw an exception */
1285                         mono_raise_exception(get_socket_exception(WSAEINVAL));
1286                 }
1287         } else if (byte_val!=NULL) {
1288                 int valsize=mono_array_length(byte_val);
1289                 guchar *buf=mono_array_addr(byte_val, guchar, 0);
1290         
1291                 ret=setsockopt(sock, system_level, system_name, buf, valsize);
1292                 if(ret==SOCKET_ERROR) {
1293                         mono_raise_exception(get_socket_exception(WSAGetLastError()));
1294                 }
1295         } else {
1296                 ret=setsockopt(sock, system_level, system_name, &int_val,
1297                                sizeof(int_val));
1298         }
1299
1300         if(ret==SOCKET_ERROR) {
1301                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1302         }
1303 }
1304
1305 void ves_icall_System_Net_Sockets_Socket_Shutdown_internal(SOCKET sock,
1306                                                            gint32 how)
1307 {
1308         int ret;
1309         
1310         MONO_ARCH_SAVE_REGS;
1311
1312         /* Currently, the values for how (recv=0, send=1, both=2) match
1313          * the BSD API
1314          */
1315         ret=shutdown(sock, how);
1316         if(ret==SOCKET_ERROR) {
1317                 mono_raise_exception(get_socket_exception(WSAGetLastError()));
1318         }
1319 }
1320
1321 static gboolean hostent_to_IPHostEntry(struct hostent *he, MonoString **h_name,
1322                                        MonoArray **h_aliases,
1323                                        MonoArray **h_addr_list)
1324 {
1325         MonoDomain *domain = mono_domain_get ();
1326         int i;
1327
1328         if(he->h_length!=4 || he->h_addrtype!=AF_INET) {
1329                 return(FALSE);
1330         }
1331
1332         *h_name=mono_string_new(domain, he->h_name);
1333
1334         i=0;
1335         while(he->h_aliases[i]!=NULL) {
1336                 i++;
1337         }
1338         
1339         *h_aliases=mono_array_new(domain, mono_defaults.string_class, i);
1340         i=0;
1341         while(he->h_aliases[i]!=NULL) {
1342                 MonoString *alias;
1343                 
1344                 alias=mono_string_new(domain, he->h_aliases[i]);
1345                 mono_array_set(*h_aliases, MonoString *, i, alias);
1346                 i++;
1347         }
1348
1349         i=0;
1350         while(he->h_addr_list[i]!=NULL) {
1351                 i++;
1352         }
1353         
1354         *h_addr_list=mono_array_new(domain, mono_defaults.string_class, i);
1355         i=0;
1356         while(he->h_addr_list[i]!=NULL) {
1357                 MonoString *addr_string;
1358                 char addr[16];
1359                 
1360                 g_snprintf(addr, 16, "%u.%u.%u.%u",
1361                          (unsigned char)he->h_addr_list[i][0],
1362                          (unsigned char)he->h_addr_list[i][1],
1363                          (unsigned char)he->h_addr_list[i][2],
1364                          (unsigned char)he->h_addr_list[i][3]);
1365                 
1366                 addr_string=mono_string_new(domain, addr);
1367                 mono_array_set(*h_addr_list, MonoString *, i, addr_string);
1368                 i++;
1369         }
1370
1371         return(TRUE);
1372 }
1373
1374 extern MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1375 {
1376         char *hostname;
1377         struct hostent *he;
1378         
1379         MONO_ARCH_SAVE_REGS;
1380
1381         hostname=mono_string_to_utf8(host);
1382         he=gethostbyname(hostname);
1383         g_free(hostname);
1384         
1385         if(he==NULL) {
1386                 return(FALSE);
1387         }
1388
1389         return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
1390 }
1391
1392 #ifndef HAVE_INET_PTON
1393 static int
1394 inet_pton (int family, const char *address, void *inaddrp)
1395 {
1396         if (family == AF_INET) {
1397 #ifdef HAVE_INET_ATON
1398                 struct in_addr inaddr;
1399                 
1400                 if (!inet_aton (address, &inaddr))
1401                         return 0;
1402                 
1403                 memcpy (inaddrp, &inaddr, sizeof (struct in_addr));
1404                 return 1;
1405 #else
1406                 /* assume the system has inet_addr(), if it doesn't
1407                    have that we're pretty much screwed... */
1408                 guint32 inaddr;
1409                 
1410                 if (!strcmp (address, "255.255.255.255")) {
1411                         /* special-case hack */
1412                         inaddr = 0xffffffff;
1413                 } else {
1414                         inaddr = inet_addr (address);
1415 #ifndef INADDR_NONE
1416 #define INADDR_NONE ((in_addr_t) -1)
1417 #endif
1418                         if (inaddr == INADDR_NONE)
1419                                 return 0;
1420                 }
1421                 
1422                 memcpy (inaddrp, &inaddr, sizeof (guint32));
1423                 return 1;
1424 #endif /* HAVE_INET_ATON */
1425         }
1426         
1427         return -1;
1428 }
1429 #endif /* !HAVE_INET_PTON */
1430
1431 extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
1432 {
1433         struct in_addr inaddr;
1434         struct hostent *he;
1435         char *address;
1436         
1437         MONO_ARCH_SAVE_REGS;
1438
1439         address = mono_string_to_utf8 (addr);
1440         if (inet_pton (AF_INET, address, &inaddr) <= 0) {
1441                 g_free (address);
1442                 return FALSE;
1443         }
1444         
1445         g_free (address);
1446         if ((he = gethostbyaddr ((char *) &inaddr, sizeof (inaddr), AF_INET)) == NULL)
1447                 return FALSE;
1448         
1449         return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
1450 }
1451
1452 extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name)
1453 {
1454         guchar hostname[256];
1455         int ret;
1456         
1457         MONO_ARCH_SAVE_REGS;
1458
1459         ret=gethostname (hostname, sizeof(hostname));
1460         if(ret==-1) {
1461                 return(FALSE);
1462         }
1463         
1464         *h_name=mono_string_new(mono_domain_get (), hostname);
1465
1466         return(TRUE);
1467 }
1468
1469
1470 void mono_network_init(void)
1471 {
1472         WSADATA wsadata;
1473         int err;
1474         
1475         err=WSAStartup(MAKEWORD(2,0), &wsadata);
1476         if(err!=0) {
1477                 g_error(G_GNUC_PRETTY_FUNCTION ": Couldn't initialise networking");
1478                 exit(-1);
1479         }
1480
1481 #ifdef DEBUG
1482         g_message(G_GNUC_PRETTY_FUNCTION ": Using socket library: %s", wsadata.szDescription);
1483         g_message(G_GNUC_PRETTY_FUNCTION ": Socket system status: %s", wsadata.szSystemStatus);
1484 #endif
1485 }
1486
1487 void mono_network_cleanup(void)
1488 {
1489         WSACleanup();
1490 }