Merge in the LIBSMB_PROG idea from samba, so that you can do
authorMartin Pool <mbp@samba.org>
Fri, 31 Aug 2001 07:06:13 +0000 (07:06 +0000)
committerMartin Pool <mbp@samba.org>
Fri, 31 Aug 2001 07:06:13 +0000 (07:06 +0000)
  RSYNC_CONNECT_PROG='./rsync --daemon' ./rsync -vvvvvv  localhost::

to test as a daemon without actually having to listen on a port.

clientserver.c
rsync.h
socket.c

index 70c12e2..7dd72e9 100644 (file)
@@ -78,7 +78,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
        if (!user) user = getenv("USER");
        if (!user) user = getenv("LOGNAME");
 
-       fd = open_socket_out(host, rsync_port, &socket_address);
+       fd = open_socket_out_wrapped (host, rsync_port, &socket_address);
        if (fd == -1) {
                exit_cleanup(RERR_SOCKETIO);
        }
diff --git a/rsync.h b/rsync.h
index b26073e..6a663fe 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -533,3 +533,6 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
 #endif
 
 #define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
+
+
+extern int verbose;
index d630fdb..5e03760 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1,6 +1,6 @@
 /* -*- c-file-style: "linux" -*-
    
-   Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
+   Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
    
    This program is free software; you can redistribute it and/or modify
@@ -90,10 +90,13 @@ static int establish_proxy_connection(int fd, char *host, int port)
 }
 
 
+
 /* open a socket to a tcp remote host with the specified port 
    based on code from Warren
    proxy support by Stephen Rothwell */
-int open_socket_out(char *host, int port, struct in_addr *address)
+static int open_socket_out (char *host,
+                           int port,
+                           struct in_addr *address)
 {
        int type = SOCK_STREAM;
        struct sockaddr_in sock_out;
@@ -152,7 +155,8 @@ int open_socket_out(char *host, int port, struct in_addr *address)
        }
 
        if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
-               rprintf(FERROR,"failed to connect to %s - %s\n", h, strerror(errno));
+               rprintf (FERROR, RSYNC_NAME ": failed to connect to host %s: %s\n",
+                        h, strerror(errno));
                close(res);
                return -1;
        }
@@ -166,6 +170,30 @@ int open_socket_out(char *host, int port, struct in_addr *address)
 }
 
 
+/**
+ * Open an outgoing socket, but allow for it to be intercepted by
+ * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
+ * socketpair rather than really opening a socket.
+ *
+ * We use this primarily in testing to detect TCP flow bugs, but not
+ * cause security problems by really opening remote connections.
+ *
+ * This is based on the Samba LIBSMB_PROG feature.
+ **/
+int open_socket_out_wrapped (char *host,
+                            int port,
+                            struct in_addr *address)
+{
+       char *prog;
+
+       if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL) 
+               return sock_exec (prog);
+       else 
+               return open_socket_out (host, port, address);
+}
+
+
+
 /****************************************************************************
 open a socket of the specified type, port and address for incoming data
 ****************************************************************************/
@@ -185,7 +213,7 @@ static int open_socket_in(int type, int port, struct in_addr *address)
        }
        res = socket(AF_INET, type, 0);
        if (res == -1) { 
-               rprintf(FERROR,"socket failed: %s\n",
+               rprintf(FERROR, RSYNC_NAME ": socket failed: %s\n",
                        strerror(errno)); 
                return -1; 
        }
@@ -573,3 +601,107 @@ struct in_addr *ip_address(const char *str)
 
        return &ret;
 }
+
+
+
+/*******************************************************************
+this is like socketpair but uses tcp. It is used by the Samba
+regression test code
+The function guarantees that nobody else can attach to the socket,
+or if they do that this function fails and the socket gets closed
+returns 0 on success, -1 on failure
+the resulting file descriptors are symmetrical
+ ******************************************************************/
+static int socketpair_tcp(int fd[2])
+{
+       int listener;
+       struct sockaddr_in sock;
+       struct sockaddr_in sock2;
+       socklen_t socklen = sizeof(sock);
+       int connect_done = 0;
+       
+       fd[0] = fd[1] = listener = -1;
+
+       memset(&sock, 0, sizeof(sock));
+       
+       if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
+
+        memset(&sock2, 0, sizeof(sock2));
+#ifdef HAVE_SOCK_SIN_LEN
+        sock2.sin_len = sizeof(sock2);
+#endif
+        sock2.sin_family = PF_INET;
+
+        bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
+
+       if (listen(listener, 1) != 0) goto failed;
+
+       if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
+
+       if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
+
+       set_nonblocking(fd[1]);
+
+       sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+       if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
+               if (errno != EINPROGRESS) goto failed;
+       } else {
+               connect_done = 1;
+       }
+
+       if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
+
+       close(listener);
+       if (connect_done == 0) {
+               if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
+                   && errno != EISCONN) goto failed;
+       }
+
+       set_blocking (fd[1]);
+
+       /* all OK! */
+       return 0;
+
+ failed:
+       if (fd[0] != -1) close(fd[0]);
+       if (fd[1] != -1) close(fd[1]);
+       if (listener != -1) close(listener);
+       return -1;
+}
+
+
+/*******************************************************************
+run a program on a local tcp socket, this is used to launch smbd
+when regression testing
+the return value is a socket which is attached to a subprocess
+running "prog". stdin and stdout are attached. stderr is left
+attached to the original stderr
+ ******************************************************************/
+int sock_exec(const char *prog)
+{
+       int fd[2];
+       if (socketpair_tcp(fd) != 0) {
+               rprintf (FERROR, RSYNC_NAME
+                        ": socketpair_tcp failed (%s)\n",
+                        strerror(errno));
+               return -1;
+       }
+       if (fork() == 0) {
+               close(fd[0]);
+               close(0);
+               close(1);
+               dup(fd[1]);
+               dup(fd[1]);
+               if (verbose > 3)
+                       fprintf (stderr,
+                                RSYNC_NAME ": execute socket program \"%s\"\n",
+                                prog);
+               exit (system (prog));
+       }
+       close (fd[1]);
+       return fd[0];
+}
+
+
+