int always_checksum = 0;
int list_only = 0;
+struct in_addr socket_address = {INADDR_ANY};
+
void usage(int F)
{
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
+ rprintf(F," --address bind to the specified address\n");
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST,
- OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY};
+ OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS};
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:zP";
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{"log-format", 1, 0, OPT_LOG_FORMAT},
+ {"address", 1, 0, OPT_ADDRESS},
{0,0,0,0}};
log_format = optarg;
break;
+ case OPT_ADDRESS:
+ {
+ struct in_addr *ia;
+ if ((ia = ip_address(optarg))) {
+ socket_address = *ia;
+ }
+ }
+ break;
+
default:
slprintf(err_buf,sizeof(err_buf),"unrecognised option\n");
return 0;
--include-from=FILE don't exclude patterns listed in FILE
--version print version number
--daemon run as a rsync daemon
+ --address bind to the specified address
--config=FILE specify alternate rsyncd.conf file
--port=PORT specify alternate rsyncd port number
--stats give some file transfer stats
respond to requests accordingly. See the rsyncd.conf(5) man page for more
details.
+dit(bf(--address)) By default rsync will bind to the wildcard address
+when run as a daemon with the --daemon option. The --address option
+allows you to specify a specific IP address (or hostname) to bind
+to. This makes virtual hosting possible in conjunction with the
+--config option.
+
dit(bf(--config=FILE)) This specifies an alternate config file than
the default /etc/rsyncd.conf. This is only relevant when --daemon is
specified.
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
-static int open_socket_in(int type, int port)
+static int open_socket_in(int type, int port, struct in_addr *address)
{
struct hostent *hp;
struct sockaddr_in sock;
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
sock.sin_port = htons(port);
sock.sin_family = hp->h_addrtype;
- sock.sin_addr.s_addr = INADDR_ANY;
+ if (address) {
+ sock.sin_addr = *address;
+ } else {
+ sock.sin_addr.s_addr = INADDR_ANY;
+ }
res = socket(hp->h_addrtype, type, 0);
if (res == -1) {
rprintf(FERROR,"socket failed\n");
void start_accept_loop(int port, int (*fn)(int ))
{
int s;
+ extern struct in_addr socket_address;
/* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, port);
+ s = open_socket_in(SOCK_STREAM, port, &socket_address);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);
return name_buf;
}
+
+/*******************************************************************
+convert a string to an IP address. The string can be a name or
+dotted decimal number
+ ******************************************************************/
+struct in_addr *ip_address(const char *str)
+{
+ static struct in_addr ret;
+ struct hostent *hp;
+
+ /* try as an IP address */
+ if (inet_aton(str, &ret) != 0) {
+ return &ret;
+ }
+
+ /* otherwise assume it's a network name of some sort and use
+ gethostbyname */
+ if ((hp = gethostbyname(str)) == 0) {
+ rprintf(FERROR, "gethostbyname: Unknown host. %s\n",str);
+ return NULL;
+ }
+
+ if (hp->h_addr == NULL) {
+ rprintf(FERROR, "gethostbyname: host address is invalid for host %s\n",str);
+ return NULL;
+ }
+
+ if (hp->h_length > sizeof(ret)) {
+ rprintf(FERROR, "gethostbyname: host address is too large\n");
+ return NULL;
+ }
+
+ memcpy(&ret.s_addr, hp->h_addr, hp->h_length);
+
+ return(&ret);
+}