* include/sys/un.h (UNIX_PATH_MAX): Rename from UNIX_PATH_LEN to

follow Linux.
	* fhandler_socket.cc: Change UNIX_PATH_LEN to UNIX_PATH_MAX throughout.
	(fhandler_socket::recv_internal): Don't return prematurely in case of
	successful return.  For AF_LOCAL sockets, overwrite returned AF_INET
	name with AF_LOCAL name.
This commit is contained in:
Corinna Vinschen 2013-03-07 15:39:35 +00:00
parent b5545a7b7e
commit 8981489bec
3 changed files with 48 additions and 12 deletions

View File

@ -1,3 +1,12 @@
2013-03-07 Corinna Vinschen <corinna@vinschen.de>
* include/sys/un.h (UNIX_PATH_MAX): Rename from UNIX_PATH_LEN to
follow Linux.
* fhandler_socket.cc: Change UNIX_PATH_LEN to UNIX_PATH_MAX throughout.
(fhandler_socket::recv_internal): Don't return prematurely in case of
successful return. For AF_LOCAL sockets, overwrite returned AF_INET
name with AF_LOCAL name.
2013-03-07 Corinna Vinschen <corinna@vinschen.de> 2013-03-07 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::bind): Fix check for AF_LOCAL * fhandler_socket.cc (fhandler_socket::bind): Fix check for AF_LOCAL

View File

@ -905,7 +905,7 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
/* Check that name is within bounds. Don't check if the string is /* Check that name is within bounds. Don't check if the string is
NUL-terminated, because there are projects out there which set NUL-terminated, because there are projects out there which set
namelen to a value which doesn't cover the trailing NUL. */ namelen to a value which doesn't cover the trailing NUL. */
if (len <= 1 || (len = strnlen (un_addr->sun_path, len)) > UNIX_PATH_LEN) if (len <= 1 || (len = strnlen (un_addr->sun_path, len)) > UNIX_PATH_MAX)
{ {
set_errno (len <= 1 ? (len == 1 ? ENOENT : EINVAL) : ENAMETOOLONG); set_errno (len <= 1 ? (len == 1 ? ENOENT : EINVAL) : ENAMETOOLONG);
goto out; goto out;
@ -1253,7 +1253,7 @@ fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
sun.sun_family = AF_LOCAL; sun.sun_family = AF_LOCAL;
sun.sun_path[0] = '\0'; sun.sun_path[0] = '\0';
if (get_sun_path ()) if (get_sun_path ())
strncat (sun.sun_path, get_sun_path (), UNIX_PATH_LEN - 1); strncat (sun.sun_path, get_sun_path (), UNIX_PATH_MAX - 1);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1)); memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
*namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0); *namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0);
res = 0; res = 0;
@ -1327,7 +1327,7 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
sun.sun_family = AF_LOCAL; sun.sun_family = AF_LOCAL;
sun.sun_path[0] = '\0'; sun.sun_path[0] = '\0';
if (get_peer_sun_path ()) if (get_peer_sun_path ())
strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_LEN - 1); strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_MAX - 1);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1)); memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
*namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0); *namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0);
} }
@ -1387,6 +1387,7 @@ fhandler_socket::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
LPWSABUF &wsabuf = wsamsg->lpBuffers; LPWSABUF &wsabuf = wsamsg->lpBuffers;
ULONG &wsacnt = wsamsg->dwBufferCount; ULONG &wsacnt = wsamsg->dwBufferCount;
static NO_COPY LPFN_WSARECVMSG WSARecvMsg; static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
int orig_namelen = wsamsg->namelen;
DWORD wait_flags = wsamsg->dwFlags; DWORD wait_flags = wsamsg->dwFlags;
bool waitall = !!(wait_flags & MSG_WAITALL); bool waitall = !!(wait_flags & MSG_WAITALL);
@ -1483,19 +1484,45 @@ fhandler_socket::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
/* According to SUSv3, errno isn't set in that case and no error /* According to SUSv3, errno isn't set in that case and no error
condition is returned. */ condition is returned. */
if (WSAGetLastError () == WSAEMSGSIZE) if (WSAGetLastError () == WSAEMSGSIZE)
return ret + wret; ret += wret;
else if (!ret)
if (!ret)
{ {
/* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
in this case. */ in this case. */
if (WSAGetLastError () == WSAESHUTDOWN) if (WSAGetLastError () == WSAESHUTDOWN)
return 0; ret = 0;
else
{
set_winsock_errno (); set_winsock_errno ();
return SOCKET_ERROR; return SOCKET_ERROR;
} }
} }
}
if (get_addr_family () == AF_LOCAL && wsamsg->name != NULL
&& orig_namelen >= (int) sizeof (sa_family_t))
{
/* WSARecvFrom copied the sockaddr_in block to wsamsg->name.
We have to overwrite it with a sockaddr_un block. */
sockaddr_un *un = (sockaddr_un *) wsamsg->name;
un->sun_family = AF_LOCAL;
int len = orig_namelen - offsetof (struct sockaddr_un, sun_path);
if (len > 0)
{
if (!get_peer_sun_path ())
wsamsg->namelen = sizeof (sa_family_t);
else
{
memset (un->sun_path, 0, len);
strncpy (un->sun_path, get_peer_sun_path (), len);
if (un->sun_path[len - 1] == '\0')
len = strlen (un->sun_path) + 1;
if (len > UNIX_PATH_MAX)
len = UNIX_PATH_MAX;
wsamsg->namelen = offsetof (struct sockaddr_un, sun_path) + len;
}
}
}
return ret; return ret;
} }

View File

@ -1,6 +1,6 @@
/* sys/un.h /* sys/un.h
Copyright 1999, 2000, 2001, 2005, 2009 Red Hat, Inc. Copyright 1999, 2000, 2001, 2005, 2009, 2013 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -15,11 +15,11 @@ details. */
#include <cygwin/socket.h> #include <cygwin/socket.h>
/* POSIX requires only at least 100 bytes */ /* POSIX requires only at least 100 bytes */
#define UNIX_PATH_LEN 108 #define UNIX_PATH_MAX 108
struct sockaddr_un { struct sockaddr_un {
sa_family_t sun_family; /* address family AF_LOCAL/AF_UNIX */ sa_family_t sun_family; /* address family AF_LOCAL/AF_UNIX */
char sun_path[UNIX_PATH_LEN]; /* 108 bytes of socket address */ char sun_path[UNIX_PATH_MAX]; /* 108 bytes of socket address */
}; };
/* Evaluates the actual length of `sockaddr_un' structure. */ /* Evaluates the actual length of `sockaddr_un' structure. */