From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2210) id 905BF3894C36; Tue, 27 Apr 2021 14:16:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 905BF3894C36 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Ken Brown To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: connect: implement resetting a connected DGRAM socket X-Act-Checkin: newlib-cygwin X-Git-Author: Ken Brown X-Git-Refname: refs/heads/master X-Git-Oldrev: 2be07f75548a9111ebf9b5cb4bb1040c3dc4f4f0 X-Git-Newrev: 3b0ba6535218631b1ab467cd29d36b1eae4a0af6 Message-Id: <20210427141607.905BF3894C36@sourceware.org> Date: Tue, 27 Apr 2021 14:16:07 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Apr 2021 14:16:07 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3b0ba6535218631b1ab467cd29d36b1eae4a0af6 commit 3b0ba6535218631b1ab467cd29d36b1eae4a0af6 Author: Ken Brown Date: Fri Apr 23 18:17:57 2021 -0400 Cygwin: connect: implement resetting a connected DGRAM socket Following POSIX and Linux, allow a connected DGRAM socket's connection to be reset (so that the socket becomes unconnected). This is done by calling connect and specifing an address whose family is AF_UNSPEC. Diff: --- winsup/cygwin/fhandler_socket_inet.cc | 21 +++++++++++++++++++-- winsup/cygwin/fhandler_socket_local.cc | 30 +++++++++++++++++++++++++----- winsup/cygwin/fhandler_socket_unix.cc | 7 +++++++ winsup/cygwin/release/3.2.1 | 5 +++++ 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc index f6bb8c503..30eab4099 100644 --- a/winsup/cygwin/fhandler_socket_inet.cc +++ b/winsup/cygwin/fhandler_socket_inet.cc @@ -781,8 +781,20 @@ int fhandler_socket_inet::connect (const struct sockaddr *name, int namelen) { struct sockaddr_storage sst; + bool reset = (name->sa_family == AF_UNSPEC + && get_socket_type () == SOCK_DGRAM); - if (get_inet_addr_inet (name, namelen, &sst, &namelen) == SOCKET_ERROR) + if (reset) + { + if (connect_state () == unconnected) + return 0; + /* To reset a connected DGRAM socket, call Winsock's connect + function with the address member of the sockaddr structure + filled with zeroes. */ + memset (&sst, 0, sizeof sst); + sst.ss_family = get_addr_family (); + } + else if (get_inet_addr_inet (name, namelen, &sst, &namelen) == SOCKET_ERROR) return SOCKET_ERROR; /* Initialize connect state to "connect_pending". In the SOCK_STREAM @@ -804,7 +816,12 @@ fhandler_socket_inet::connect (const struct sockaddr *name, int namelen) int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen); if (!res) - connect_state (connected); + { + if (reset) + connect_state (unconnected); + else + connect_state (connected); + } else if (!is_nonblocking () && res == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) diff --git a/winsup/cygwin/fhandler_socket_local.cc b/winsup/cygwin/fhandler_socket_local.cc index 1c8d48b58..bd4081622 100644 --- a/winsup/cygwin/fhandler_socket_local.cc +++ b/winsup/cygwin/fhandler_socket_local.cc @@ -894,19 +894,34 @@ fhandler_socket_local::connect (const struct sockaddr *name, int namelen) { struct sockaddr_storage sst; int type = 0; + bool reset = (name->sa_family == AF_UNSPEC + && get_socket_type () == SOCK_DGRAM); - if (get_inet_addr_local (name, namelen, &sst, &namelen, &type, connect_secret) - == SOCKET_ERROR) + if (reset) + { + if (connect_state () == unconnected) + return 0; + /* To reset a connected DGRAM socket, call Winsock's connect + function with the address member of the sockaddr structure + filled with zeroes. */ + memset (&sst, 0, sizeof sst); + sst.ss_family = get_addr_family (); + } + else if (get_inet_addr_local (name, namelen, &sst, &namelen, &type, + connect_secret) == SOCKET_ERROR) return SOCKET_ERROR; - if (get_socket_type () != type) + if (get_socket_type () != type && !reset) { WSASetLastError (WSAEPROTOTYPE); set_winsock_errno (); return SOCKET_ERROR; } - set_peer_sun_path (name->sa_data); + if (reset) + set_peer_sun_path (NULL); + else + set_peer_sun_path (name->sa_data); /* Don't move af_local_set_cred into af_local_connect which may be called via select, possibly running under another identity. Call early here, @@ -933,7 +948,12 @@ fhandler_socket_local::connect (const struct sockaddr *name, int namelen) int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen); if (!res) - connect_state (connected); + { + if (reset) + connect_state (unconnected); + else + connect_state (connected); + } else if (!is_nonblocking () && res == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 252bcd9a9..a2428e952 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -1696,6 +1696,13 @@ fhandler_socket_unix::connect (const struct sockaddr *name, int namelen) conn_unlock (); return -1; } + if (name->sa_family == AF_UNSPEC && get_socket_type () == SOCK_DGRAM) + { + connect_state (unconnected); + peer_sun_path (NULL); + conn_unlock (); + return 0; + } connect_state (connect_pending); conn_unlock (); /* Check validity of name */ diff --git a/winsup/cygwin/release/3.2.1 b/winsup/cygwin/release/3.2.1 index 7662c7114..6ebe68fa6 100644 --- a/winsup/cygwin/release/3.2.1 +++ b/winsup/cygwin/release/3.2.1 @@ -28,3 +28,8 @@ Bug Fixes - Fix a bug in recognizing a successful completion of connect(2) on a datagram socket. + +- Fix connect(2) when called with an address structure whose family is + AF_UNSPEC. As specified by POSIX and Linux, this is allowed on + datagram sockets, and its effect is to reset the socket's peer + address.