[Sockets] Support Remote/LocalEndPoint for AF_UNIX
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 24 Nov 2010 05:47:51 +0000 (00:47 -0500)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Wed, 24 Nov 2010 05:49:01 +0000 (00:49 -0500)
We were not handling correctly the AF_UNIX family when getting the
socket name or the peer name.

Fixes bug #655637.

mcs/class/Mono.Posix/Mono.Unix/UnixEndPoint.cs
mcs/class/System/System.Net.Sockets/Socket.cs
mcs/class/System/System.Net.Sockets/Socket_2_1.cs
mono/metadata/icall-def.h
mono/metadata/socket-io.c
mono/metadata/socket-io.h

index 06a1ce758f938e61c3eb54b9990168be68423baa..d86dd7cf7dc3a036caf8c27002d160d7518adbfb 100644 (file)
@@ -75,6 +75,13 @@ namespace Mono.Unix
                                throw new ArgumentException ("socketAddress is not a unix socket address.");
                         */
 
+                       if (socketAddress.Size == 2) {
+                               // Empty filename.
+                               // Probably from RemoteEndPoint which on linux does not return the file name.
+                               UnixEndPoint uep = new UnixEndPoint ("a");
+                               uep.filename = "";
+                               return uep;
+                       }
                        byte [] bytes = new byte [socketAddress.Size - 2 - 1];
                        for (int i = 0; i < bytes.Length; i++) {
                                bytes [i] = socketAddress [i + 2];
index b1b21aedbe64d58a647b15a51eeb03c3129c5bcf..5e5ddc5d454d5a1f0fb3da60cae4e97fb6492303 100644 (file)
@@ -411,7 +411,7 @@ namespace System.Net.Sockets
 #if !TARGET_JVM
                // Returns the local endpoint details in addr and port
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
+               private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, int family, out int error);
 #endif
 
                // Wish:  support non-IP endpoints.
@@ -431,7 +431,7 @@ namespace System.Net.Sockets
                                SocketAddress sa;
                                int error;
                                
-                               sa=LocalEndPoint_internal(socket, out error);
+                               sa=LocalEndPoint_internal(socket, (int) address_family, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
index ce0e49ba360723f888a92eef7b8f56cce7753b45..78bfb95cf0ce346bd3960caba2d4e57a1418b5e8 100644 (file)
@@ -1040,7 +1040,7 @@ namespace System.Net.Sockets {
 
                // Returns the remote endpoint details in addr and port
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
+               private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, int family, out int error);
 
                public EndPoint RemoteEndPoint {
                        get {
@@ -1062,7 +1062,7 @@ namespace System.Net.Sockets {
                                SocketAddress sa;
                                int error;
                                
-                               sa=RemoteEndPoint_internal(socket, out error);
+                               sa=RemoteEndPoint_internal(socket, (int) address_family, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
index 7ec162d3f87c1b56577d4c389e809234b18befc3..afde21e29797544ea646b4977d3152ab40eed1d3 100644 (file)
@@ -441,12 +441,12 @@ ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_So
 ICALL(SOCK_7, "GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal)
 ICALL(SOCK_8, "GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal)
 ICALL(SOCK_9, "Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal)
-ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal)
+ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal)
 ICALL(SOCK_11, "Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal)
 ICALL(SOCK_11a, "Receive_internal(intptr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Receive_array_internal)
 ICALL(SOCK_12, "Receive_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,int&)", ves_icall_System_Net_Sockets_Socket_Receive_internal)
 ICALL(SOCK_13, "RecvFrom_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,int&)", ves_icall_System_Net_Sockets_Socket_RecvFrom_internal)
-ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal)
+ICALL(SOCK_14, "RemoteEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal)
 ICALL(SOCK_15, "Select_internal(System.Net.Sockets.Socket[]&,int,int&)", ves_icall_System_Net_Sockets_Socket_Select_internal)
 ICALL(SOCK_15a, "SendFile(intptr,string,byte[],byte[],System.Net.Sockets.TransmitFileOptions)", ves_icall_System_Net_Sockets_Socket_SendFile)
 ICALL(SOCK_16, "SendTo_internal(intptr,byte[],int,int,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_SendTo_internal)
index 6e2f88d399e7a0fca0dcb2d3450f48485c5b55f2..1a62826a411c11f35d72d49a39fb8cfc49732d83 100644 (file)
@@ -1021,52 +1021,88 @@ static MonoObject *create_object_from_sockaddr(struct sockaddr *saddr,
        }
 }
 
-extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock, gint32 *error)
+static int
+get_sockaddr_size (int family)
+{
+       int size;
+
+       size = 0;
+       if (family == AF_INET) {
+               size = sizeof (struct sockaddr_in);
+#ifdef AF_INET6
+       } else if (family == AF_INET6) {
+               size = sizeof (struct sockaddr_in6);
+#endif
+#ifdef HAVE_SYS_UN_H
+       } else if (family == AF_UNIX) {
+               size = sizeof (struct sockaddr_un);
+#endif
+       }
+       return size;
+}
+
+extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock, gint32 af, gint32 *error)
 {
-       gchar sa[32];   /* sockaddr in not big enough for sockaddr_in6 */
+       gchar *sa;
        socklen_t salen;
        int ret;
+       MonoObject *result;
        
        MONO_ARCH_SAVE_REGS;
 
        *error = 0;
        
-       salen=sizeof(sa);
+       salen = get_sockaddr_size (convert_family (af));
+       if (salen == 0) {
+               *error = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+       sa = g_malloc0 (salen);
        ret = _wapi_getsockname (sock, (struct sockaddr *)sa, &salen);
        
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
+               g_free (sa);
                return(NULL);
        }
        
        LOGDEBUG (g_message("%s: bound to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port)));
 
-       return(create_object_from_sockaddr((struct sockaddr *)sa, salen,
-                                          error));
+       result = create_object_from_sockaddr((struct sockaddr *)sa, salen, error);
+       g_free (sa);
+       return result;
 }
 
-extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock, gint32 *error)
+extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock, gint32 af, gint32 *error)
 {
-       gchar sa[32];   /* sockaddr in not big enough for sockaddr_in6 */
+       gchar *sa;
        socklen_t salen;
        int ret;
+       MonoObject *result;
        
        MONO_ARCH_SAVE_REGS;
 
        *error = 0;
        
-       salen=sizeof(sa);
+       salen = get_sockaddr_size (convert_family (af));
+       if (salen == 0) {
+               *error = WSAEAFNOSUPPORT;
+               return NULL;
+       }
+       sa = g_malloc0 (salen);
+       /* Note: linux returns just 2 for AF_UNIX. Always. */
        ret = _wapi_getpeername (sock, (struct sockaddr *)sa, &salen);
-       
        if(ret==SOCKET_ERROR) {
                *error = WSAGetLastError ();
+               g_free (sa);
                return(NULL);
        }
        
        LOGDEBUG (g_message("%s: connected to %s port %d", __func__, inet_ntoa(((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port)));
 
-       return(create_object_from_sockaddr((struct sockaddr *)sa, salen,
-                                          error));
+       result = create_object_from_sockaddr((struct sockaddr *)sa, salen, error);
+       g_free (sa);
+       return result;
 }
 
 static struct sockaddr *create_sockaddr_from_object(MonoObject *saddr_obj,
index 1d815d1081a6a7821920818e32f97f20ad3ca369..0e0e16eebed568e3b08b10ce5362768d1889b9ad 100644 (file)
@@ -198,8 +198,8 @@ extern gint32 ves_icall_System_Net_Sockets_Socket_Available_internal(SOCKET sock
 extern void ves_icall_System_Net_Sockets_Socket_Blocking_internal(SOCKET sock, gboolean block, gint32 *error) MONO_INTERNAL;
 extern gpointer ves_icall_System_Net_Sockets_Socket_Accept_internal(SOCKET sock, gint32 *error, gboolean blocking) MONO_INTERNAL;
 extern void ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock, guint32 backlog, gint32 *error) MONO_INTERNAL;
-extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock, gint32 *error) MONO_INTERNAL;
-extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock, gint32 *error) MONO_INTERNAL;
+extern MonoObject *ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal(SOCKET sock, gint32 af, gint32 *error) MONO_INTERNAL;
+extern MonoObject *ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal(SOCKET sock, gint32 af, gint32 *error) MONO_INTERNAL;
 extern void ves_icall_System_Net_Sockets_Socket_Bind_internal(SOCKET sock, MonoObject *sockaddr, gint32 *error) MONO_INTERNAL;
 extern void ves_icall_System_Net_Sockets_Socket_Connect_internal(SOCKET sock, MonoObject *sockaddr, gint32 *error) MONO_INTERNAL;
 extern gint32 ves_icall_System_Net_Sockets_Socket_Receive_internal(SOCKET sock, MonoArray *buffer, gint32 offset, gint32 count, gint32 flags, gint32 *error) MONO_INTERNAL;