From 7ba0a42f557f68deea9c1b612afc4c74dd55a521 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 2 Jul 2010 14:36:43 +0000 Subject: [PATCH] * net.cc (cygwin_getsockopt): Make sure SO_PEERCRED is only handled in level SOL_SOCKET. Workaround a return value regression in Vista and later. Add comment to explain. --- winsup/cygwin/ChangeLog | 6 ++++++ winsup/cygwin/net.cc | 30 +++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f7d5202fa..cc7e9b3ee 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,9 @@ +2010-07-02 Corinna Vinschen + + * net.cc (cygwin_getsockopt): Make sure SO_PEERCRED is only handled + in level SOL_SOCKET. Workaround a return value regression in Vista + and later. Add comment to explain. + 2010-06-29 Corinna Vinschen * spawn.cc (spawn_guts): Reinstantiate a FIXME comment. diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 8a1d390dc..c0151e5b6 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -787,7 +787,7 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, myfault efault; if (efault.faulted (EFAULT) || !fh) res = -1; - else if (optname == SO_PEERCRED) + else if (optname == SO_PEERCRED && level == SOL_SOCKET) { struct ucred *cred = (struct ucred *) optval; res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid); @@ -800,6 +800,34 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, res = getsockopt (fh->get_socket (), level, optname, (char *) optval, (int *) optlen); + if (level == SOL_SOCKET) + { + switch (optname) + { + case SO_ERROR: + { + int *e = (int *) optval; + debug_printf ("WinSock SO_ERROR = %d", *e); + *e = find_winsock_errno (*e); + } + break; + case SO_KEEPALIVE: + case SO_DONTROUTE: + /* Regression in Vista and later: instead of a 4 byte BOOL + value, a 1 byte BOOLEAN value is returned, in contrast + to older systems and the documentation. Since an int + type is expected by the calling application, we convert + the result here. */ + if (*optlen == 1) + { + BOOLEAN *in = (BOOLEAN *) optval; + int *out = (int *) optval; + *out = *in; + *optlen = 4; + } + break; + } + } if (optname == SO_ERROR) { int *e = (int *) optval;