]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CONTRIB: tcploop: implement a disconnect operation 'D'
authorWilly Tarreau <w@1wt.eu>
Wed, 14 Oct 2020 06:09:48 +0000 (08:09 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 14 Oct 2020 06:46:23 +0000 (08:46 +0200)
This performs a connect(AF_UNSPEC) over an existing connection. This is
mainly for compatibility testing. At this step it only seems to work on
linux for TCP sockets (both listening and established), while SO_LINGER
successfully resets established connections on freebsd and aix.

contrib/tcploop/tcploop.c

index f9f5f6307d2b3033e9ab72976a792b4064918aa3..55b79365890f25cbed8c55b011c9692fc8a44071 100644 (file)
@@ -105,6 +105,7 @@ __attribute__((noreturn)) void usage(int code, const char *arg0)
            "                 Note: fd=socket,bind(fd),listen(fd)\n"
            "  C            : Connects to ip:port\n"
            "                 Note: fd=socket,connect(fd)\n"
+           "  D            : Disconnect (connect to AF_UNSPEC)\n"
            "  A[<count>]   : Accepts <count> incoming sockets and closes count-1\n"
            "                 Note: fd=accept(fd)\n"
            "  J            : Jump back to oldest post-fork/post-accept action\n"
@@ -443,6 +444,14 @@ int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
        return -1;
 }
 
+/* Try to disconnect by connecting to AF_UNSPEC. Return >=0 on success, -1 in case of error */
+int tcp_disconnect(int sock)
+{
+       const struct sockaddr sa = { .sa_family = AF_UNSPEC };
+
+       return connect(sock, &sa, sizeof(sa));
+}
+
 /* receives N bytes from the socket and returns 0 (or -1 in case of a recv
  * error, or -2 in case of an argument error). When no arg is passed, receives
  * anything and stops. Otherwise reads the requested amount of data. 0 means
@@ -787,6 +796,13 @@ int main(int argc, char **argv)
                        dolog("connect\n");
                        break;
 
+               case 'D':
+                       /* silently ignore non-existing connections */
+                       if (sock >= 0 && tcp_disconnect(sock) < 0)
+                               die(1, "Fatal: tcp_connect() failed.\n");
+                       dolog("disconnect\n");
+                       break;
+
                case 'A':
                        if (sock < 0)
                                die(1, "Fatal: tcp_accept() on non-socket.\n");