* fhandler.h (class fhandler_socket): Add peer_sun_path member.

(fhandler_socket::set_peer_sun_path): New method.
	(fhandler_socket::get_peer_sun_path): New method.
	* fhandler_socket.cc (fhandler_socket::fhandler_socket): Initialize
	peer_sun_path to NULL.
	(fhandler_socket::~fhandler_socket): Free peer_sun_path if necessary.
	(fhandler_socket::dup): Duplicate peer_sun_path.
	(fhandler_socket::accept): Ditto.  Return fake unbound peer content
	and len in case of AF_LOCAL sockets.
	(fhandler_socket::getsockname): Always use local sockaddr_storage to
	store socket address and copy over to incoming address.  Handle every
	namelen correctly per POSIX.
	(fhandler_socket::getpeername): Ditto.  Add code path to return
	correct value for AF_LOCAL sockets.
	(fhandler_socket::set_peer_sun_path): New method.
	* net.cc (socketpair): Set peer_sun_path to empty string, just like
	sun_path.
This commit is contained in:
Corinna Vinschen 2009-08-13 10:26:42 +00:00
parent af0a038ecb
commit d3d4aa96aa
4 changed files with 94 additions and 24 deletions

View File

@ -1,3 +1,23 @@
2009-08-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Add peer_sun_path member.
(fhandler_socket::set_peer_sun_path): New method.
(fhandler_socket::get_peer_sun_path): New method.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Initialize
peer_sun_path to NULL.
(fhandler_socket::~fhandler_socket): Free peer_sun_path if necessary.
(fhandler_socket::dup): Duplicate peer_sun_path.
(fhandler_socket::accept): Ditto. Return fake unbound peer content
and len in case of AF_LOCAL sockets.
(fhandler_socket::getsockname): Always use local sockaddr_storage to
store socket address and copy over to incoming address. Handle every
namelen correctly per POSIX.
(fhandler_socket::getpeername): Ditto. Add code path to return
correct value for AF_LOCAL sockets.
(fhandler_socket::set_peer_sun_path): New method.
* net.cc (socketpair): Set peer_sun_path to empty string, just like
sun_path.
2009-08-13 Corinna Vinschen <corinna@vinschen.de>
Dave Korn <dave.korn.cygwin@googlemail.com>

View File

@ -462,6 +462,7 @@ class fhandler_socket: public fhandler_base
private:
char *sun_path;
char *peer_sun_path;
struct status_flags
{
unsigned async_io : 1; /* async I/O */
@ -533,6 +534,8 @@ class fhandler_socket: public fhandler_base
int get_socket_type () {return type;}
void set_sun_path (const char *path);
char *get_sun_path () {return sun_path;}
void set_peer_sun_path (const char *path);
char *get_peer_sun_path () {return peer_sun_path;}
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));

View File

@ -152,6 +152,7 @@ fhandler_socket::fhandler_socket () :
wsock_mtx (NULL),
wsock_evt (NULL),
sun_path (NULL),
peer_sun_path (NULL),
status ()
{
need_fork_fixup (true);
@ -161,6 +162,8 @@ fhandler_socket::~fhandler_socket ()
{
if (sun_path)
cfree (sun_path);
if (peer_sun_path)
cfree (peer_sun_path);
}
char *
@ -664,6 +667,7 @@ fhandler_socket::dup (fhandler_base *child)
if (get_addr_family () == AF_LOCAL)
{
fhs->set_sun_path (get_sun_path ());
fhs->set_peer_sun_path (get_peer_sun_path ());
if (get_socket_type () == SOCK_STREAM)
{
fhs->sec_pid = sec_pid;
@ -1043,7 +1047,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
}
if (get_addr_family () == AF_LOCAL && (!res || in_progress))
set_sun_path (name->sa_data);
set_peer_sun_path (name->sa_data);
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
{
@ -1141,6 +1145,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
if (get_addr_family () == AF_LOCAL)
{
sock->set_sun_path (get_sun_path ());
sock->set_peer_sun_path (get_peer_sun_path ());
if (get_socket_type () == SOCK_STREAM)
{
/* Don't forget to copy credentials from accepting
@ -1163,8 +1168,20 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
res = res_fd;
if (peer)
{
*len = min (*len, llen);
memcpy (peer, &lpeer, *len);
if (get_addr_family () == AF_LOCAL)
{
/* FIXME: Right now we have no way to determine the
bound socket name of the peer's socket. For now
we just fake an unbound socket on the other side. */
static struct sockaddr_un un = { AF_LOCAL, "" };
*len = min (*len, 2);
memcpy (peer, &un, *len);
}
else
{
*len = min (*len, llen);
memcpy (peer, &lpeer, *len);
}
}
}
else
@ -1186,28 +1203,29 @@ fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
if (get_addr_family () == AF_LOCAL)
{
struct sockaddr_un *sun = (struct sockaddr_un *) name;
memset (sun, 0, *namelen);
sun->sun_family = AF_LOCAL;
if (!get_sun_path ())
sun->sun_path[0] = '\0';
else
/* According to SUSv2 "If the actual length of the address is
greater than the length of the supplied sockaddr structure, the
stored address will be truncated." We play it save here so
that the path always has a trailing 0 even if it's truncated. */
strncpy (sun->sun_path, get_sun_path (),
*namelen - sizeof *sun + sizeof sun->sun_path - 1);
*namelen = sizeof *sun - sizeof sun->sun_path
+ strlen (sun->sun_path) + 1;
struct sockaddr_un sun;
sun.sun_family = AF_LOCAL;
sun.sun_path[0] = '\0';
if (get_sun_path ())
strncat (sun.sun_path, get_sun_path (), UNIX_PATH_LEN - 1);
*namelen = min (*namelen, (int) SUN_LEN (&sun) + 1);
memcpy (name, &sun, *namelen);
res = 0;
}
else
{
res = ::getsockname (get_socket (), name, namelen);
if (res)
/* Always use a local big enough buffer and truncate later as necessary
per POSIX. WinSock unfortunaltey only returns WSAEFAULT if the buffer
is too small. */
struct sockaddr_storage sock;
int len = sizeof sock;
res = ::getsockname (get_socket (), (struct sockaddr *) &sock, &len);
if (!res)
{
*namelen = min (*namelen, len);
memcpy (name, &sock, *namelen);
}
else
{
if (WSAGetLastError () == WSAEINVAL)
{
@ -1219,11 +1237,11 @@ fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
{
case AF_INET:
res = 0;
*namelen = sizeof (struct sockaddr_in);
*namelen = min (*namelen, (int) sizeof (struct sockaddr_in));
break;
case AF_INET6:
res = 0;
*namelen = sizeof (struct sockaddr_in6);
*namelen = min (*namelen, (int) sizeof (struct sockaddr_in6));
break;
default:
WSASetLastError (WSAEOPNOTSUPP);
@ -1246,9 +1264,30 @@ fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
int
fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
{
int res = ::getpeername (get_socket (), name, namelen);
/* Always use a local big enough buffer and truncate later as necessary
per POSIX. WinSock unfortunately only returns WSAEFAULT if the buffer
is too small. */
struct sockaddr_storage sock;
int len = sizeof sock;
int res = ::getpeername (get_socket (), (struct sockaddr *) &sock, &len);
if (res)
set_winsock_errno ();
else if (get_addr_family () == AF_LOCAL)
{
struct sockaddr_un sun;
memset (&sun, 0, sizeof sun);
sun.sun_family = AF_LOCAL;
sun.sun_path[0] = '\0';
if (get_peer_sun_path ())
strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_LEN - 1);
*namelen = min (*namelen, (int) SUN_LEN (&sun) + 1);
memcpy (name, &sun, *namelen);
}
else
{
*namelen = min (*namelen, len);
memcpy (name, &sock, *namelen);
}
return res;
}
@ -1915,6 +1954,12 @@ fhandler_socket::set_sun_path (const char *path)
sun_path = path ? cstrdup (path) : NULL;
}
void
fhandler_socket::set_peer_sun_path (const char *path)
{
peer_sun_path = path ? cstrdup (path) : NULL;
}
int
fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
{

View File

@ -2867,6 +2867,7 @@ socketpair (int family, int type, int protocol, int *sb)
if (sb0 >= 0 && fdsock (sb0, dev, insock))
{
((fhandler_socket *) sb0)->set_sun_path ("");
((fhandler_socket *) sb0)->set_peer_sun_path ("");
((fhandler_socket *) sb0)->set_addr_family (family);
((fhandler_socket *) sb0)->set_socket_type (type);
((fhandler_socket *) sb0)->connect_state (connected);
@ -2878,6 +2879,7 @@ socketpair (int family, int type, int protocol, int *sb)
if (sb1 >= 0 && fdsock (sb1, dev, outsock))
{
((fhandler_socket *) sb1)->set_sun_path ("");
((fhandler_socket *) sb1)->set_peer_sun_path ("");
((fhandler_socket *) sb1)->set_addr_family (family);
((fhandler_socket *) sb1)->set_socket_type (type);
((fhandler_socket *) sb1)->connect_state (connected);