many globals already.
Better error messages for network-related failures.
if (!user) user = getenv("USER");
if (!user) user = getenv("LOGNAME");
if (!user) user = getenv("USER");
if (!user) user = getenv("LOGNAME");
- fd = open_socket_out_wrapped (host, rsync_port, bind_address);
+ fd = open_socket_out_wrapped (host, rsync_port, bind_address,
+ global_opts.af_hint);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
#endif
int blocking_io=0;
#endif
int blocking_io=0;
-/** Network address family. **/
-int af = AF_INET;
+/** Global options set from command line. **/
+struct global_opts global_opts;
int read_batch=0; /* dw */
int write_batch=0; /* dw */
int read_batch=0; /* dw */
int write_batch=0; /* dw */
{"read-batch", 'f', POPT_ARG_STRING, &batch_ext, 'f'},
{"write-batch", 'F', POPT_ARG_NONE, &write_batch, 0},
#ifdef INET6
{"read-batch", 'f', POPT_ARG_STRING, &batch_ext, 'f'},
{"write-batch", 'F', POPT_ARG_NONE, &write_batch, 0},
#ifdef INET6
- {0, '4', POPT_ARG_VAL, &af, AF_INET },
- {0, '6', POPT_ARG_VAL, &af, AF_INET6 },
+ {0, '4', POPT_ARG_VAL, &global_opts.af, AF_INET },
+ {0, '6', POPT_ARG_VAL, &global_opts.af, AF_INET6 },
+
+extern struct global_opts {
+ /** Network address family. **/
+ int af_hint;
+} global_opts;
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*
- socket functions used in rsync
-
- */
+/**
+ * @file socket.c
+ *
+ * Socket functions used in rsync.
+ **/
#include "lib/addrinfo.h"
#endif
#include "lib/addrinfo.h"
#endif
+// extern int af; /* NO MORE BLOODY GLOBALS! */
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
-/** Open a socket to a tcp remote host with the specified port .
+/**
+ * Open a socket to a tcp remote host with the specified port .
- * Based on code from Warren. Proxy support by Stephen Rothwell
+ * Based on code from Warren. Proxy support by Stephen Rothwell.
+ * getaddrinfo() rewrite contributed by KAME.net.
+ * Now that we support IPv6 we need to look up the remote machine's
+ * address first, using @p af_hint to set a preference for the type
+ * of address. Then depending on whether it has v4 or v6 addresses we
+ * try to open a connection.
- * @param bind_address Local address to use. Normally NULL to get the stack default.
+ * The loop allows for machines with some addresses which may not be
+ * reachable, perhaps because we can't e.g. route ipv6 to that network
+ * but we can get ip4 packets through.
+ *
+ * @param bind_address Local address to use. Normally NULL to bind
+ * the wildcard address.
+ *
+ * @param af_hint Address family, e.g. AF_INET or AF_INET6.
-int open_socket_out(char *host, int port, const char *bind_address)
+int open_socket_out(char *host, int port, const char *bind_address,
+ int af_hint)
{
int type = SOCK_STREAM;
int error;
{
int type = SOCK_STREAM;
int error;
}
memset(&hints, 0, sizeof(hints));
}
memset(&hints, 0, sizeof(hints));
+ hints.ai_family = af_hint;
hints.ai_socktype = type;
error = getaddrinfo(h, portbuf, &hints, &res0);
if (error) {
hints.ai_socktype = type;
error = getaddrinfo(h, portbuf, &hints, &res0);
if (error) {
- rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s: %s\n", portbuf, gai_strerror(error));
+ rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
+ h, portbuf, gai_strerror(error));
bhints.ai_flags = AI_PASSIVE;
error = getaddrinfo(bind_address, NULL, &bhints, &bres);
if (error) {
bhints.ai_flags = AI_PASSIVE;
error = getaddrinfo(bind_address, NULL, &bhints, &bres);
if (error) {
- rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
+ rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s <noport>: %s\n",
bind_address, gai_strerror(error));
continue;
}
bind_address, gai_strerror(error));
continue;
}
**/
int open_socket_out_wrapped (char *host,
int port,
**/
int open_socket_out_wrapped (char *host,
int port,
- const char *bind_address)
+ const char *bind_address,
+ int af_hint)
{
char *prog;
if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
return sock_exec (prog);
else
{
char *prog;
if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
return sock_exec (prog);
else
- return open_socket_out (host, port, bind_address);
+ return open_socket_out (host, port, bind_address,
+ af_hint);
* @param bind_address Local address to bind, or NULL to allow it to
* default.
**/
* @param bind_address Local address to bind, or NULL to allow it to
* default.
**/
-static int open_socket_in(int type, int port, const char *bind_address)
+static int open_socket_in(int type, int port, const char *bind_address,
+ int af_hint)
int error;
memset(&hints, 0, sizeof(hints));
int error;
memset(&hints, 0, sizeof(hints));
+ hints.ai_family = af_hint;
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof(portbuf), "%d", port);
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof(portbuf), "%d", port);
extern char *bind_address;
/* open an incoming socket */
extern char *bind_address;
/* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, port, bind_address);
+ s = open_socket_in(SOCK_STREAM, port, bind_address,
+ global_opts.af_hint);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);
strcpy(name_buf,def);
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
strcpy(name_buf,def);
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
+ /* FIXME: Can we really not continue? */
+ rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
+ strerror(errno));
exit_cleanup(RERR_SOCKETIO);
}
exit_cleanup(RERR_SOCKETIO);
}
if (res == NULL) {
strcpy(name_buf, def);
if (res == NULL) {
strcpy(name_buf, def);
- rprintf(FERROR,
- "reverse name lookup mismatch - spoofed address?\n");
+ rprintf(FERROR, RSYNC_NAME ": "
+ "reverse name lookup mismatch on fd%d - spoofed address?\n",
+ fd);