From 4f86301f09e10e2c88d539392723c4d21385bcab Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 21 Sep 2011 00:20:59 +0200 Subject: [PATCH] Ensure EBADF returns for socket functions on mingw. * lib/accept.c (rpl_accept): Fail with error EBADF if the file descriptor is invalid. * lib/bind.c (rpl_bind): Likewise. * lib/connect.c (rpl_connect): Likewise. * lib/getpeername.c (rpl_getpeername): Likewise. * lib/getsockname.c (rpl_getsockname): Likewise. * lib/getsockopt.c (rpl_getsockopt): Likewise. * lib/listen.c (rpl_listen): Likewise. * lib/recv.c (rpl_recv): Likewise. * lib/recvfrom.c (rpl_recvfrom): Likewise. * lib/send.c (rpl_send): Likewise. * lib/sendto.c (rpl_sendto): Likewise. * lib/setsockopt.c (rpl_setsockopt): Likewise. * lib/shutdown.c (rpl_shutdown): Likewise. --- ChangeLog | 18 ++++++++++++++++++ lib/accept.c | 18 ++++++++++++++---- lib/bind.c | 17 +++++++++++++---- lib/connect.c | 29 +++++++++++++++++++---------- lib/getpeername.c | 17 +++++++++++++---- lib/getsockname.c | 17 +++++++++++++---- lib/getsockopt.c | 51 +++++++++++++++++++++++++++++++-------------------- lib/listen.c | 17 +++++++++++++---- lib/recv.c | 17 +++++++++++++---- lib/recvfrom.c | 32 +++++++++++++++++++++----------- lib/send.c | 17 +++++++++++++---- lib/sendto.c | 17 +++++++++++++---- lib/setsockopt.c | 31 ++++++++++++++++++++----------- lib/shutdown.c | 17 +++++++++++++---- 14 files changed, 227 insertions(+), 88 deletions(-) diff --git a/ChangeLog b/ChangeLog index a653b15ba..542c6fad4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2011-09-20 Bruno Haible + Ensure EBADF returns for socket functions on mingw. + * lib/accept.c (rpl_accept): Fail with error EBADF if the file + descriptor is invalid. + * lib/bind.c (rpl_bind): Likewise. + * lib/connect.c (rpl_connect): Likewise. + * lib/getpeername.c (rpl_getpeername): Likewise. + * lib/getsockname.c (rpl_getsockname): Likewise. + * lib/getsockopt.c (rpl_getsockopt): Likewise. + * lib/listen.c (rpl_listen): Likewise. + * lib/recv.c (rpl_recv): Likewise. + * lib/recvfrom.c (rpl_recvfrom): Likewise. + * lib/send.c (rpl_send): Likewise. + * lib/sendto.c (rpl_sendto): Likewise. + * lib/setsockopt.c (rpl_setsockopt): Likewise. + * lib/shutdown.c (rpl_shutdown): Likewise. + +2011-09-20 Bruno Haible + select tests: EBADF tests. * tests/test-select.h (do_select_bad_fd, do_select_bad_fd_nowait, test_bad_fd): New functions. diff --git a/lib/accept.c b/lib/accept.c index 5591fa50a..01faf5420 100644 --- a/lib/accept.c +++ b/lib/accept.c @@ -31,12 +31,22 @@ int rpl_accept (int fd, struct sockaddr *addr, socklen_t *addrlen) { - SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen); - if (fh == INVALID_SOCKET) + SOCKET sock = FD_TO_SOCKET (fd); + + if (sock == INVALID_SOCKET) { - set_winsock_errno (); + errno = EBADF; return -1; } else - return SOCKET_TO_FD (fh); + { + SOCKET fh = accept (sock, addr, addrlen); + if (fh == INVALID_SOCKET) + { + set_winsock_errno (); + return -1; + } + else + return SOCKET_TO_FD (fh); + } } diff --git a/lib/bind.c b/lib/bind.c index e6d959dce..baaea59b6 100644 --- a/lib/bind.c +++ b/lib/bind.c @@ -32,9 +32,18 @@ int rpl_bind (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); - int r = bind (sock, sockaddr, len); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = bind (sock, sockaddr, len); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/connect.c b/lib/connect.c index ea03e77bc..afd13b9f8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -32,16 +32,25 @@ int rpl_connect (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); - int r = connect (sock, sockaddr, len); - if (r < 0) - { - /* EINPROGRESS is not returned by WinSock 2.0; for backwards - compatibility, connect(2) uses EWOULDBLOCK. */ - if (WSAGetLastError () == WSAEWOULDBLOCK) - WSASetLastError (WSAEINPROGRESS); - set_winsock_errno (); + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = connect (sock, sockaddr, len); + if (r < 0) + { + /* EINPROGRESS is not returned by WinSock 2.0; for backwards + compatibility, connect(2) uses EWOULDBLOCK. */ + if (WSAGetLastError () == WSAEWOULDBLOCK) + WSASetLastError (WSAEINPROGRESS); + + set_winsock_errno (); + } + + return r; } - - return r; } diff --git a/lib/getpeername.c b/lib/getpeername.c index 9e540a1fd..abe5a40b6 100644 --- a/lib/getpeername.c +++ b/lib/getpeername.c @@ -32,9 +32,18 @@ int rpl_getpeername (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = getpeername (sock, addr, addrlen); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = getpeername (sock, addr, addrlen); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/getsockname.c b/lib/getsockname.c index 1eabd9496..1c494bb98 100644 --- a/lib/getsockname.c +++ b/lib/getsockname.c @@ -32,9 +32,18 @@ int rpl_getsockname (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = getsockname (sock, addr, addrlen); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = getsockname (sock, addr, addrlen); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/getsockopt.c b/lib/getsockopt.c index d82ea5ff2..22176649d 100644 --- a/lib/getsockopt.c +++ b/lib/getsockopt.c @@ -37,32 +37,43 @@ int rpl_getsockopt (int fd, int level, int optname, void *optval, socklen_t *optlen) { - int r; SOCKET sock = FD_TO_SOCKET (fd); - if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + if (sock == INVALID_SOCKET) { - int milliseconds; - int milliseconds_len = sizeof (int); - struct timeval tv; - size_t n; - r = getsockopt (sock, level, optname, (char *) &milliseconds, - &milliseconds_len); - tv.tv_sec = milliseconds / 1000; - tv.tv_usec = (milliseconds - 1000 * tv.tv_sec) * 1000; - n = sizeof (struct timeval); - if (n > *optlen) - n = *optlen; - memcpy (optval, &tv, n); - *optlen = n; + errno = EBADF; + return -1; } else { - r = getsockopt (sock, level, optname, optval, optlen); - } + int r; + + if (level == SOL_SOCKET + && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + { + int milliseconds; + int milliseconds_len = sizeof (int); + struct timeval tv; + size_t n; - if (r < 0) - set_winsock_errno (); + r = getsockopt (sock, level, optname, (char *) &milliseconds, + &milliseconds_len); + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = (milliseconds - 1000 * tv.tv_sec) * 1000; + n = sizeof (struct timeval); + if (n > *optlen) + n = *optlen; + memcpy (optval, &tv, n); + *optlen = n; + } + else + { + r = getsockopt (sock, level, optname, optval, optlen); + } - return r; + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/listen.c b/lib/listen.c index 938aa7546..b7d070e64 100644 --- a/lib/listen.c +++ b/lib/listen.c @@ -32,9 +32,18 @@ int rpl_listen (int fd, int backlog) { SOCKET sock = FD_TO_SOCKET (fd); - int r = listen (sock, backlog); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = listen (sock, backlog); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/recv.c b/lib/recv.c index d99b7a40a..4755f6370 100644 --- a/lib/recv.c +++ b/lib/recv.c @@ -32,9 +32,18 @@ ssize_t rpl_recv (int fd, void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); - int r = recv (sock, buf, len, flags); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = recv (sock, buf, len, flags); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/recvfrom.c b/lib/recvfrom.c index 5edd1d8b1..5ce2b1274 100644 --- a/lib/recvfrom.c +++ b/lib/recvfrom.c @@ -32,17 +32,27 @@ ssize_t rpl_recvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { - int frombufsize = (from != NULL ? *fromlen : 0); SOCKET sock = FD_TO_SOCKET (fd); - int r = recvfrom (sock, buf, len, flags, from, fromlen); - if (r < 0) - set_winsock_errno (); - - /* Winsock recvfrom() only returns a valid 'from' when the socket is - connectionless. POSIX gives a valid 'from' for all types of sockets. */ - else if (from != NULL && *fromlen == frombufsize) - rpl_getpeername (fd, from, fromlen); - - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int frombufsize = (from != NULL ? *fromlen : 0); + int r = recvfrom (sock, buf, len, flags, from, fromlen); + + if (r < 0) + set_winsock_errno (); + + /* Winsock recvfrom() only returns a valid 'from' when the socket is + connectionless. POSIX gives a valid 'from' for all types of + sockets. */ + else if (from != NULL && *fromlen == frombufsize) + rpl_getpeername (fd, from, fromlen); + + return r; + } } diff --git a/lib/send.c b/lib/send.c index d8a876ec3..cd2148290 100644 --- a/lib/send.c +++ b/lib/send.c @@ -32,9 +32,18 @@ ssize_t rpl_send (int fd, const void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); - int r = send (sock, buf, len, flags); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = send (sock, buf, len, flags); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/sendto.c b/lib/sendto.c index e301626df..95efab888 100644 --- a/lib/sendto.c +++ b/lib/sendto.c @@ -33,9 +33,18 @@ rpl_sendto (int fd, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = sendto (sock, buf, len, flags, to, tolen); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = sendto (sock, buf, len, flags, to, tolen); + if (r < 0) + set_winsock_errno (); + + return r; + } } diff --git a/lib/setsockopt.c b/lib/setsockopt.c index a31a10ee9..6a7ca5e32 100644 --- a/lib/setsockopt.c +++ b/lib/setsockopt.c @@ -34,23 +34,32 @@ int rpl_setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen) { - int r; SOCKET sock = FD_TO_SOCKET (fd); + int r; - if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + if (sock == INVALID_SOCKET) { - const struct timeval *tv = optval; - int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000; - optval = &milliseconds; - r = setsockopt (sock, level, optname, optval, sizeof (int)); + errno = EBADF; + return -1; } else { - r = setsockopt (sock, level, optname, optval, optlen); - } + if (level == SOL_SOCKET + && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + { + const struct timeval *tv = optval; + int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000; + optval = &milliseconds; + r = setsockopt (sock, level, optname, optval, sizeof (int)); + } + else + { + r = setsockopt (sock, level, optname, optval, optlen); + } - if (r < 0) - set_winsock_errno (); + if (r < 0) + set_winsock_errno (); - return r; + return r; + } } diff --git a/lib/shutdown.c b/lib/shutdown.c index 26c49323a..1c302a24f 100644 --- a/lib/shutdown.c +++ b/lib/shutdown.c @@ -32,9 +32,18 @@ int rpl_shutdown (int fd, int how) { SOCKET sock = FD_TO_SOCKET (fd); - int r = shutdown (sock, how); - if (r < 0) - set_winsock_errno (); - return r; + if (sock == INVALID_SOCKET) + { + errno = EBADF; + return -1; + } + else + { + int r = shutdown (sock, how); + if (r < 0) + set_winsock_errno (); + + return r; + } } -- 2.11.0