GUnixSocketAddress: handle abstract sockets with non-0-padded names

There are apparently two incompatible ways of naming abstract sockets:
pad the sockaddr with 0s and use the entire thing as the name, or else
don't, and just pass a shorter length value to the relevant functions.
We previously only supported the former method. Add support for the
latter.

Also correctly handle "anonymous" unix sockaddrs (eg, the client side
of a connection, or a socketpair() socket), and add unix domain socket
support to the socket-client and socket-server test programs to make
sure this all works.

https://bugzilla.gnome.org/show_bug.cgi?id=615960
This commit is contained in:
Dan Winship
2010-04-20 17:23:49 -04:00
parent 5e892de8af
commit 19d8cc3375
11 changed files with 439 additions and 110 deletions

View File

@@ -217,9 +217,13 @@ g_socket_address_new_from_native (gpointer native,
if (family == AF_INET)
{
struct sockaddr_in *addr = (struct sockaddr_in *) native;
GInetAddress *iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
GInetAddress *iaddr;
GSocketAddress *sockaddr;
if (len < sizeof (*addr))
return NULL;
iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin_addr), AF_INET);
sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin_port));
g_object_unref (iaddr);
return sockaddr;
@@ -228,9 +232,13 @@ g_socket_address_new_from_native (gpointer native,
if (family == AF_INET6)
{
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
GInetAddress *iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
GInetAddress *iaddr;
GSocketAddress *sockaddr;
if (len < sizeof (*addr))
return NULL;
iaddr = g_inet_address_new_from_bytes ((guint8 *) &(addr->sin6_addr), AF_INET6);
sockaddr = g_inet_socket_address_new (iaddr, g_ntohs (addr->sin6_port));
g_object_unref (iaddr);
return sockaddr;
@@ -240,11 +248,30 @@ g_socket_address_new_from_native (gpointer native,
if (family == AF_UNIX)
{
struct sockaddr_un *addr = (struct sockaddr_un *) native;
gint path_len = len - G_STRUCT_OFFSET (struct sockaddr_un, sun_path);
if (addr->sun_path[0] == 0)
return g_unix_socket_address_new_abstract (addr->sun_path+1,
sizeof (addr->sun_path) - 1);
return g_unix_socket_address_new (addr->sun_path);
if (path_len == 0)
{
return g_unix_socket_address_new_with_type ("", 0,
G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
}
else if (addr->sun_path[0] == 0)
{
if (len < sizeof (*addr))
{
return g_unix_socket_address_new_with_type (addr->sun_path + 1,
path_len - 1,
G_UNIX_SOCKET_ADDRESS_ABSTRACT);
}
else
{
return g_unix_socket_address_new_with_type (addr->sun_path + 1,
path_len - 1,
G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
}
}
else
return g_unix_socket_address_new (addr->sun_path);
}
#endif