summarylogtreecommitdiffstats
path: root/0013-server-error-on-connect-to-zero.patch
blob: ee68329f98d3db57c8680a747712fe692470a66c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
diff --git a/server/sock.c b/server/sock.c
index 84c0d4a4931..b33d06aa706 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -2647,6 +2647,21 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
         if (unix_addr.addr.sa_family == AF_INET && !memcmp( &unix_addr.in.sin_addr, magic_loopback_addr, 4 ))
             unix_addr.in.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
 
+        /* NOTE: winsock treats 0.0.0.0 address as special case error. */
+        /* TODO: this should also work for AF_INET6, AF_IPX, AF_... */
+        if (unix_addr.addr.sa_family == AF_INET && unix_addr.in.sin_addr.s_addr == 0 && unix_addr.in.sin_port == 0)
+        {
+            /* TODO: Microsoft docs mention that socket can not be connect-ed after this.
+             * Maybe shutdown and transition to special state for this? */
+            sock->errors[AFD_POLL_BIT_CONNECT_ERR] = EADDRNOTAVAIL;
+            set_error( sock_get_ntstatus( EADDRNOTAVAIL ) );
+            post_socket_event( sock, AFD_POLL_BIT_CONNECT_ERR );
+
+            /* NOTE: Some applications rely on this behaviour as a mechanism to abort select from another thread. */
+            async_wake_up( &sock->poll_q, STATUS_SUCCESS );
+            return;
+        }
+
         memcpy( &peer_addr, &unix_addr, sizeof(unix_addr) );
         ret = connect( unix_fd, &unix_addr.addr, unix_len );
         if (ret < 0 && errno == ECONNABORTED)