]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEV: tcploop: add a new "bind" command to bind to ip/port.
authorWilly Tarreau <w@1wt.eu>
Tue, 7 Jun 2022 10:03:48 +0000 (12:03 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 8 Jun 2022 12:42:15 +0000 (14:42 +0200)
The Listen command automatically relies on it (without passing its
argument), and both Listen and Connect now support working with the
existing socket, so that it's possible to Bind an ip:port on an
existing socket or to create a new one for the purpose of listening
or connecting. It now becomes possible to do:

   tcploop 0 L1234 C8888

to connect from port 1234 to port 8888.

dev/tcploop/tcploop.c

index 1aebb881ef04fc54cc71180433dc3bef66ba7a56..8433872f8f66dc42cb9a0d1eaa3463e4a0c95d06 100644 (file)
@@ -99,6 +99,8 @@ __attribute__((noreturn)) void usage(int code, const char *arg0)
            "actions :\n"
            "  A[<count>]   : Accepts <count> incoming sockets and closes count-1\n"
            "                 Note: fd=accept(fd)\n"
+           "  B[[ip]:port] : Bind a new socket to ip:port or default one if unspecified.\n"
+           "                 Note: fd=socket,bind(fd)\n"
            "  C[[ip]:port] : Connects to ip:port or default ones if unspecified.\n"
            "                 Note: fd=socket,connect(fd)\n"
            "  D            : Disconnect (connect to AF_UNSPEC)\n"
@@ -345,10 +347,21 @@ int tcp_socket()
        return sock;
 }
 
-/* Try to listen to address <sa>. Return the fd or -1 in case of error */
-int tcp_listen(int sock, const struct sockaddr_storage *sa, const char *arg)
+/* Try to bind to local address <sa>. Return the fd or -1 in case of error.
+ * Supports being passed NULL for arg if none has to be passed.
+ */
+int tcp_bind(int sock, const struct sockaddr_storage *sa, const char *arg)
 {
-       int backlog;
+       struct sockaddr_storage conn_addr;
+
+       if (arg && arg[1]) {
+               struct err_msg err;
+
+               if (addr_to_ss(arg + 1, &conn_addr, &err) < 0)
+                       die(1, "%s\n", err.msg);
+               sa = &conn_addr;
+       }
+
 
        if (sock < 0) {
                sock = tcp_socket();
@@ -356,16 +369,6 @@ int tcp_listen(int sock, const struct sockaddr_storage *sa, const char *arg)
                        return sock;
        }
 
-       if (arg[1])
-               backlog = atoi(arg + 1);
-       else
-               backlog = 1000;
-
-       if (backlog < 0 || backlog > 65535) {
-               fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
-               goto fail;
-       }
-
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
                perror("setsockopt(SO_REUSEADDR)");
                goto fail;
@@ -383,6 +386,33 @@ int tcp_listen(int sock, const struct sockaddr_storage *sa, const char *arg)
                goto fail;
        }
 
+       return sock;
+ fail:
+       close(sock);
+       return -1;
+}
+
+/* Try to listen to address <sa>. Return the fd or -1 in case of error */
+int tcp_listen(int sock, const struct sockaddr_storage *sa, const char *arg)
+{
+       int backlog;
+
+       if (sock < 0) {
+               sock = tcp_bind(sock, sa, NULL);
+               if (sock < 0)
+                       return sock;
+       }
+
+       if (arg[1])
+               backlog = atoi(arg + 1);
+       else
+               backlog = 1000;
+
+       if (backlog < 0 || backlog > 65535) {
+               fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
+               goto fail;
+       }
+
        if (listen(sock, backlog) == -1) {
                perror("listen");
                goto fail;
@@ -798,17 +828,21 @@ int main(int argc, char **argv)
        for (arg = loop_arg; arg < argc; arg++) {
                switch (argv[arg][0]) {
                case 'L':
-                       /* silently ignore existing connections */
-                       if (sock == -1)
-                               sock = tcp_listen(sock, &default_addr, argv[arg]);
+                       sock = tcp_listen(sock, &default_addr, argv[arg]);
                        if (sock < 0)
                                die(1, "Fatal: tcp_listen() failed.\n");
                        break;
 
-               case 'C':
+               case 'B':
                        /* silently ignore existing connections */
-                       if (sock == -1)
-                               sock = tcp_connect(sock, &default_addr, argv[arg]);
+                       sock = tcp_bind(sock, &default_addr, argv[arg]);
+                       if (sock < 0)
+                               die(1, "Fatal: tcp_connect() failed.\n");
+                       dolog("connect\n");
+                       break;
+
+               case 'C':
+                       sock = tcp_connect(sock, &default_addr, argv[arg]);
                        if (sock < 0)
                                die(1, "Fatal: tcp_connect() failed.\n");
                        dolog("connect\n");