summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2013-03-07 15:39:35 +0000
committerCorinna Vinschen <corinna@vinschen.de>2013-03-07 15:39:35 +0000
commit8981489becf128c41e2befa6c03e2385e5e396d9 (patch)
tree1fcf1178cc6256509afb77f873f2d6d834a30f21
parentb5545a7b7e98f79c4c3b4b6e735c77ed2b78b9d2 (diff)
downloadcygnal-8981489becf128c41e2befa6c03e2385e5e396d9.tar.gz
cygnal-8981489becf128c41e2befa6c03e2385e5e396d9.tar.bz2
cygnal-8981489becf128c41e2befa6c03e2385e5e396d9.zip
* 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.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/fhandler_socket.cc45
-rw-r--r--winsup/cygwin/include/sys/un.h6
3 files changed, 48 insertions, 12 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 11299dd2b..d509568e1 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
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>
+
* fhandler_socket.cc (fhandler_socket::bind): Fix check for AF_LOCAL
filename length to allow non-NUL terminated strings within namelen
bytes. Copy over sun_path to local array sun_path to have a
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index d52f75901..1ccc7f81d 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -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
NUL-terminated, because there are projects out there which set
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);
goto out;
@@ -1253,7 +1253,7 @@ fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
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);
+ strncat (sun.sun_path, get_sun_path (), UNIX_PATH_MAX - 1);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
*namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0);
res = 0;
@@ -1327,7 +1327,7 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
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);
+ strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_MAX - 1);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1));
*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;
ULONG &wsacnt = wsamsg->dwBufferCount;
static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
+ int orig_namelen = wsamsg->namelen;
DWORD wait_flags = wsamsg->dwFlags;
bool waitall = !!(wait_flags & MSG_WAITALL);
@@ -1483,17 +1484,43 @@ fhandler_socket::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
/* According to SUSv3, errno isn't set in that case and no error
condition is returned. */
if (WSAGetLastError () == WSAEMSGSIZE)
- return ret + wret;
-
- if (!ret)
+ ret += wret;
+ else if (!ret)
{
/* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
in this case. */
if (WSAGetLastError () == WSAESHUTDOWN)
- return 0;
+ ret = 0;
+ else
+ {
+ set_winsock_errno ();
+ return SOCKET_ERROR;
+ }
+ }
+ }
- set_winsock_errno ();
- 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;
+ }
}
}
diff --git a/winsup/cygwin/include/sys/un.h b/winsup/cygwin/include/sys/un.h
index 3d72ba277..a2f3dacb1 100644
--- a/winsup/cygwin/include/sys/un.h
+++ b/winsup/cygwin/include/sys/un.h
@@ -1,6 +1,6 @@
/* 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.
@@ -15,11 +15,11 @@ details. */
#include <cygwin/socket.h>
/* POSIX requires only at least 100 bytes */
-#define UNIX_PATH_LEN 108
+#define UNIX_PATH_MAX 108
struct sockaddr_un {
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. */