diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c68f7f8f5..9c1d25fdc 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,8 @@ +2014-05-05 Corinna Vinschen + + * net.cc (cygwin_getsockopt): Rearrange code slightly and handle + TCP_NODELAY just like SO_KEEPALIVE and SO_DONTROUTE. + 2014-05-03 Christopher Faylor * spawn.cc (av::setup): Eat trailing whitespace on #! script. diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 5ccfc96fd..ab36a30b4 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -923,32 +923,27 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, (int *) optlen); if (res == SOCKET_ERROR) set_winsock_errno (); - else if (level == SOL_SOCKET) + else if (level == SOL_SOCKET && optname == SO_ERROR) { - switch (optname) + int *e = (int *) optval; + debug_printf ("WinSock SO_ERROR = %d", *e); + *e = find_winsock_errno (*e); + } + else if (*optlen == 1) + { + /* 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. For some reason + only three BSD-compatible socket options seem to be affected. */ + if ((level == SOL_SOCKET + && (optname == SO_KEEPALIVE || optname == SO_DONTROUTE)) + || (level == IPPROTO_TCP && optname == TCP_NODELAY)) { - 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; + BOOLEAN *in = (BOOLEAN *) optval; + int *out = (int *) optval; + *out = *in; + *optlen = 4; } } } diff --git a/winsup/cygwin/release/1.7.30 b/winsup/cygwin/release/1.7.30 index 6d7156c0c..a0ad86394 100644 --- a/winsup/cygwin/release/1.7.30 +++ b/winsup/cygwin/release/1.7.30 @@ -34,3 +34,8 @@ Bug Fixes when calling select on a dup'ed socket after an asynchronous connection attempt. Fixes: http://cygwin.com/ml/cygwin/2014-04/msg00510.html + +- Workaround the problem that getsockopt(IPPROTO_TCP,TCP_NODELAY) returns + the option value as a 1 byte value, while BSD and Linux expect a 4 byte + value. + Fixes: http://cygwin.com/ml/cygwin/2014-04/msg00624.html