*/
#include <config.h>
+
#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <mono/metadata/object.h>
#include <mono/io-layer/io-layer.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/appdomain.h>
+#include <sys/time.h>
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h> /* defines FIONBIO and FIONREAD */
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h> /* defines SIOCATMARK */
+#endif
+
+
#undef DEBUG
static gint32 convert_family(MonoAddressFamily mono_family)
break;
default:
+ break;
}
return(proto);
int *system_level,
int *system_name)
{
- switch(mono_level) {
+ switch (mono_level) {
case SocketOptionLevel_Socket:
- *system_level=SOL_SOCKET;
-
+ *system_level = SOL_SOCKET;
+
switch(mono_name) {
case SocketOptionName_DontLinger:
/* This is SO_LINGER, because the setsockopt
* internal call maps DontLinger to SO_LINGER
* with l_onoff=0
*/
- *system_name=SO_LINGER;
+ *system_name = SO_LINGER;
break;
case SocketOptionName_Debug:
- *system_name=SO_DEBUG;
+ *system_name = SO_DEBUG;
break;
+#ifdef SO_ACCEPTCONN
case SocketOptionName_AcceptConnection:
- *system_name=SO_ACCEPTCONN;
+ *system_name = SO_ACCEPTCONN;
break;
+#endif
case SocketOptionName_ReuseAddress:
- *system_name=SO_REUSEADDR;
+ *system_name = SO_REUSEADDR;
break;
case SocketOptionName_KeepAlive:
- *system_name=SO_KEEPALIVE;
+ *system_name = SO_KEEPALIVE;
break;
case SocketOptionName_DontRoute:
- *system_name=SO_DONTROUTE;
+ *system_name = SO_DONTROUTE;
break;
case SocketOptionName_Broadcast:
- *system_name=SO_BROADCAST;
+ *system_name = SO_BROADCAST;
break;
case SocketOptionName_Linger:
- *system_name=SO_LINGER;
+ *system_name = SO_LINGER;
break;
case SocketOptionName_OutOfBandInline:
- *system_name=SO_OOBINLINE;
+ *system_name = SO_OOBINLINE;
break;
case SocketOptionName_SendBuffer:
- *system_name=SO_SNDBUF;
+ *system_name = SO_SNDBUF;
break;
case SocketOptionName_ReceiveBuffer:
- *system_name=SO_RCVBUF;
+ *system_name = SO_RCVBUF;
break;
case SocketOptionName_SendLowWater:
- *system_name=SO_SNDLOWAT;
+ *system_name = SO_SNDLOWAT;
break;
case SocketOptionName_ReceiveLowWater:
- *system_name=SO_RCVLOWAT;
+ *system_name = SO_RCVLOWAT;
break;
case SocketOptionName_SendTimeout:
- *system_name=SO_SNDTIMEO;
+ *system_name = SO_SNDTIMEO;
break;
case SocketOptionName_ReceiveTimeout:
- *system_name=SO_RCVTIMEO;
+ *system_name = SO_RCVTIMEO;
break;
case SocketOptionName_Error:
- *system_name=SO_ERROR;
+ *system_name = SO_ERROR;
break;
case SocketOptionName_Type:
- *system_name=SO_TYPE;
+ *system_name = SO_TYPE;
break;
case SocketOptionName_ExclusiveAddressUse:
case SocketOptionName_UseLoopback:
break;
case SocketOptionLevel_IP:
- *system_level=SOL_IP;
-
+#ifdef HAVE_SOL_IP
+ *system_level = SOL_IP;
+#else
+ if (1) {
+ static int cached = 0;
+ static int proto;
+
+ if (!cached) {
+ struct protoent *pent;
+
+ pent = getprotobyname ("IP");
+ proto = pent ? pent->p_proto : 0 /* 0 a good default value?? */;
+ cached = 1;
+ }
+
+ *system_level = proto;
+ }
+#endif /* HAVE_SOL_IP */
+
switch(mono_name) {
case SocketOptionName_IPOptions:
- *system_name=IP_OPTIONS;
+ *system_name = IP_OPTIONS;
break;
+#ifdef IP_HDRINCL
case SocketOptionName_HeaderIncluded:
- *system_name=IP_HDRINCL;
+ *system_name = IP_HDRINCL;
break;
+#endif
+#ifdef IP_TOS
case SocketOptionName_TypeOfService:
- *system_name=IP_TOS;
+ *system_name = IP_TOS;
break;
+#endif
+#ifdef IP_TTL
case SocketOptionName_IpTimeToLive:
- *system_name=IP_TTL;
+ *system_name = IP_TTL;
break;
+#endif
case SocketOptionName_MulticastInterface:
- *system_name=IP_MULTICAST_IF;
+ *system_name = IP_MULTICAST_IF;
break;
case SocketOptionName_MulticastTimeToLive:
- *system_name=IP_MULTICAST_TTL;
+ *system_name = IP_MULTICAST_TTL;
break;
case SocketOptionName_MulticastLoopback:
- *system_name=IP_MULTICAST_LOOP;
+ *system_name = IP_MULTICAST_LOOP;
break;
case SocketOptionName_AddMembership:
- *system_name=IP_ADD_MEMBERSHIP;
+ *system_name = IP_ADD_MEMBERSHIP;
break;
case SocketOptionName_DropMembership:
- *system_name=IP_DROP_MEMBERSHIP;
+ *system_name = IP_DROP_MEMBERSHIP;
break;
+#ifdef HAVE_IP_PKTINFO
case SocketOptionName_PacketInformation:
- *system_name=IP_PKTINFO;
+ *system_name = IP_PKTINFO;
break;
+#endif /* HAVE_IP_PKTINFO */
case SocketOptionName_DontFragment:
case SocketOptionName_AddSourceMembership:
case SocketOptionName_DropSourceMembership:
break;
case SocketOptionLevel_Tcp:
- *system_level=SOL_TCP;
-
+#ifdef HAVE_SOL_TCP
+ *system_level = SOL_TCP;
+#else
+ if (1) {
+ static int cached = 0;
+ static int proto;
+
+ if (!cached) {
+ struct protoent *pent;
+
+ pent = getprotobyname ("TCP");
+ proto = pent ? pent->p_proto : 6 /* is 6 a good default value?? */;
+ cached = 1;
+ }
+
+ *system_level = proto;
+ }
+#endif /* HAVE_SOL_TCP */
+
switch(mono_name) {
case SocketOptionName_NoDelay:
- *system_name=TCP_NODELAY;
+ *system_name = TCP_NODELAY;
break;
#if 0
/* The documentation is talking complete
}
#define STASH_SYS_ASS(this) \
- if(system_assembly==NULL) { \
+ if(system_assembly == NULL) { \
system_assembly=this->vtable->klass->image; \
}
return(ex);
}
-SOCKET ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto)
+gpointer ves_icall_System_Net_Sockets_Socket_Socket_internal(MonoObject *this, gint32 family, gint32 type, gint32 proto)
{
SOCKET sock;
gint32 sock_family;
return(NULL);
}
- return(sock);
+ return(GUINT_TO_POINTER (sock));
}
+/* FIXME: the SOCKET parameter (here and in other functions in this
+ * file) is really an IntPtr which needs to be converted to a guint32.
+ */
void ves_icall_System_Net_Sockets_Socket_Close_internal(SOCKET sock)
{
closesocket(sock);
gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal(void)
{
+#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", WSAGetLastError());
+#endif
+
return(WSAGetLastError());
}
}
}
-SOCKET ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock)
+gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock)
{
SOCKET newsock;
return(NULL);
}
- return(newsock);
+ return(GUINT_TO_POINTER (newsock));
}
void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock,
buf=mono_array_addr(buffer, guchar, offset);
ret=recvfrom(sock, buf, count, recvflags, sa, &sa_size);
- g_free(sa);
if(ret==SOCKET_ERROR) {
+ g_free(sa);
mono_raise_exception(get_socket_exception(WSAGetLastError()));
}
*sockaddr=create_object_from_sockaddr(sa, sa_size);
+ g_free(sa);
return(ret);
}
return(ret);
}
-static SOCKET Socket_to_SOCKET(MonoObject *socket)
+static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
{
SOCKET sock;
MonoClassField *field;
- field=mono_class_get_field_from_name(socket->vtable->klass, "socket");
- sock=*(SOCKET *)(((char *)socket)+field->offset);
+ field=mono_class_get_field_from_name(sockobj->vtable->klass, "socket");
+ sock=*(SOCKET *)(((char *)sockobj)+field->offset);
return(sock);
}
/* Only one of obj_val, byte_val or int_val has data */
if(obj_val!=NULL) {
+ MonoClassField *field;
struct linger linger;
- struct ip_mreqn mreq;
int valsize;
- MonoClassField *field;
switch(name) {
case SocketOptionName_DontLinger:
ret=setsockopt(sock, system_level, system_name,
&linger, valsize);
break;
-
case SocketOptionName_AddMembership:
case SocketOptionName_DropMembership:
+ {
+#ifdef HAVE_STRUCT_IP_MREQN
+ struct ip_mreqn mreq;
+#else
+ struct ip_mreq mreq;
+#endif /* HAVE_STRUCT_IP_MREQN */
+
/* pain! MulticastOption holds two IPAddress
* members, so I have to dig the value out of
* those :-(
*/
- field=mono_class_get_field_from_name(obj_val->vtable->klass, "group");
- mreq.imr_multiaddr=ipaddress_to_struct_in_addr(*(gpointer *)(((char *)obj_val)+field->offset));
- field=mono_class_get_field_from_name(obj_val->vtable->klass, "local");
- mreq.imr_address=ipaddress_to_struct_in_addr(*(gpointer *)(((char *)obj_val)+field->offset))
-;
- valsize=sizeof(mreq);
- ret=setsockopt(sock, system_level, system_name,
- &mreq, valsize);
+ field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
+ mreq.imr_multiaddr = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+ field->offset));
+ field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
+#ifdef HAVE_STRUCT_IP_MREQN
+ mreq.imr_address = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+ field->offset));
+#else
+ mreq.imr_interface = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+ field->offset));
+#endif /* HAVE_STRUCT_IP_MREQN */
+
+ ret = setsockopt (sock, system_level, system_name,
+ &mreq, sizeof (mreq));
break;
-
+ }
default:
/* Throw an exception */
mono_raise_exception(get_socket_exception(WSAEINVAL));
MonoString *addr_string;
char addr[16];
- snprintf(addr, 16, "%u.%u.%u.%u",
+ g_snprintf(addr, 16, "%u.%u.%u.%u",
(unsigned char)he->h_addr_list[i][0],
(unsigned char)he->h_addr_list[i][1],
(unsigned char)he->h_addr_list[i][2],
return(TRUE);
}
-extern gboolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
+extern MonoBoolean ves_icall_System_Net_Dns_GetHostByName_internal(MonoString *host, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
{
char *hostname;
struct hostent *he;
hostname=mono_string_to_utf8(host);
he=gethostbyname(hostname);
- free(hostname);
+ g_free(hostname);
if(he==NULL) {
return(FALSE);
return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
}
-extern gboolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
+#ifndef HAVE_INET_PTON
+static int
+inet_pton (int family, const char *address, void *inaddrp)
{
- char *address;
- guint32 inaddr;
+ if (family == AF_INET) {
+#ifdef HAVE_INET_ATON
+ struct in_addr inaddr;
+
+ if (!inet_aton (address, &inaddr))
+ return 0;
+
+ memcpy (inaddrp, &inaddr, sizeof (struct in_addr));
+ return 1;
+#else
+ /* assume the system has inet_addr(), if it doesn't
+ have that we're pretty much screwed... */
+ guint32 inaddr;
+
+ if (!strcmp (address, "255.255.255.255")) {
+ /* special-case hack */
+ inaddr = 0xffffffff;
+ } else {
+ inaddr = inet_addr (address);
+#ifndef INADDR_NONE
+#define INADDR_NONE ((in_addr_t) -1)
+#endif
+ if (inaddr == INADDR_NONE)
+ return 0;
+ }
+
+ memcpy (inaddrp, &inaddr, sizeof (guint32));
+ return 1;
+#endif /* HAVE_INET_ATON */
+ }
+
+ return -1;
+}
+#endif /* !HAVE_INET_PTON */
+
+extern MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal(MonoString *addr, MonoString **h_name, MonoArray **h_aliases, MonoArray **h_addr_list)
+{
+ struct in_addr inaddr;
struct hostent *he;
+ char *address;
- address=mono_string_to_utf8(addr);
- inaddr=inet_addr(address);
- free(address);
- if(inaddr==INADDR_NONE) {
- return(FALSE);
+ address = mono_string_to_utf8 (addr);
+ if (inet_pton (AF_INET, address, &inaddr) <= 0) {
+ g_free (address);
+ return FALSE;
}
- he=gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET);
- if(he==NULL) {
+ g_free (address);
+ if ((he = gethostbyaddr ((char *) &inaddr, sizeof (inaddr), AF_INET)) == NULL)
+ return FALSE;
+
+ return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
+}
+
+extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name)
+{
+ guchar hostname[256];
+ int ret;
+
+ ret=gethostname (hostname, sizeof(hostname));
+ if(ret==-1) {
return(FALSE);
}
+
+ *h_name=mono_string_new(mono_domain_get (), hostname);
- return(hostent_to_IPHostEntry(he, h_name, h_aliases, h_addr_list));
+ return(TRUE);
}
+
void mono_network_init(void)
{
WSADATA wsadata;