Re: openrsync --address option

2019-08-09 Thread Stuart Henderson
On 2019/08/09 14:31, Christian Weisgerber wrote:
> On 2019-08-08, Stuart Henderson  wrote:
> 
> > Works as expected for IPv4. For IPv6 it only works if you use a hostname 
> > that
> > only has a v6 address and not also a v4 address.
> 
> Not sure what scenario you mean exactly.  This works fine for me:
> 
> openrsync --address=2003:e5:cf15:c101:76dd:6f32:911c:ce5c -av \
> rsync://anoncvs.spacehopper.org/... ...

Ah, you have "family inet6 inet4" in resolv.conf. In that case
--address=$some_v4_address will fail instead.



Re: openrsync --address option

2019-08-09 Thread Christian Weisgerber
On 2019-08-08, Stuart Henderson  wrote:

> Works as expected for IPv4. For IPv6 it only works if you use a hostname that
> only has a v6 address and not also a v4 address.

Not sure what scenario you mean exactly.  This works fine for me:

openrsync --address=2003:e5:cf15:c101:76dd:6f32:911c:ce5c -av \
rsync://anoncvs.spacehopper.org/... ...

-- 
Christian "naddy" Weisgerber  na...@mips.inka.de



Re: openrsync --address option

2019-08-09 Thread Sebastian Benoit
Claudio Jeker(cje...@diehard.n-r-g.com) on 2019.08.09 00:16:42 +0200:
> On Thu, Aug 08, 2019 at 11:06:30PM +0100, Stuart Henderson wrote:
> > On 2019/08/08 15:42, Claudio Jeker wrote:
> > > I need to be able to control the bind address for openrsync connections.
> > > This implements this but it only works for connections to an rsync daemon.
> > > For rsync over ssh you need to use -e 'ssh -b address' instead.
> > 
> > Works as expected for IPv4. For IPv6 it only works if you use a hostname 
> > that
> > only has a v6 address and not also a v4 address. In this situation GPL rsync
> > prints a warning (unless you also use -6), but then moves onto a v6 
> > destination
> > address.
> > 
> > (Maybe openrsync works if you use an IPv6 literal address as the 
> > destination,
> > but I didn't see a way to do that).
> > 
> > OK for now, but as rpki-client may well end up used in places with fiddly
> > addressing requirements (which is why you're adding it in the first place ;)
> > it would be good to improve v6 as a later step.
> > 
> 
> I think this has also to do with the way the host (aka destination) lookup
> happens. My assumption is that you first try to connect to a IPv4 address
> and so there is no binding to the IPv6 address happening.
> To be honest, the GPL rsync way of doing things is also not entierly clear to
> me. It may be necessary to add -4 and -6 support or maybe force the address
> family to match bind_address and destination (or error out if they
> mismatch) would be enough.

We definatly will need to add -4/6 options.

> 
> I will commit this tomorrow morning so that improvements can happen in
> tree.

ok

> -- 
> :wq Claudio
> 
> > > Index: extern.h
> > > ===
> > > RCS file: /cvs/src/usr.bin/rsync/extern.h,v
> > > retrieving revision 1.31
> > > diff -u -p -r1.31 extern.h
> > > --- extern.h  2 Jun 2019 17:36:48 -   1.31
> > > +++ extern.h  8 Aug 2019 13:41:02 -
> > > @@ -120,6 +120,7 @@ structopts {
> > >   char*rsync_path;/* --rsync-path */
> > >   char*ssh_prog;  /* --rsh or -e */
> > >   char*port;  /* --port */
> > > + char*address;   /* --address */
> > >  };
> > >  
> > >  /*
> > > Index: main.c
> > > ===
> > > RCS file: /cvs/src/usr.bin/rsync/main.c,v
> > > retrieving revision 1.47
> > > diff -u -p -r1.47 main.c
> > > --- main.c3 Jun 2019 15:37:48 -   1.47
> > > +++ main.c8 Aug 2019 13:41:02 -
> > > @@ -307,6 +307,7 @@ main(int argc, char *argv[])
> > >   { "no-times",   no_argument,_times,   0 },
> > >   { "verbose",no_argument,,   1 },
> > >   { "no-verbose", no_argument,,   0 },
> > > + { "address",required_argument, NULL,4 },
> > >   { NULL, 0,  NULL,   0 }};
> > >  
> > >   /* Global pledge. */
> > > @@ -380,6 +381,9 @@ main(int argc, char *argv[])
> > >   case 3:
> > >   opts.port = optarg;
> > >   break;
> > > + case 4:
> > > + opts.address = optarg;
> > > + break;
> > >   case 'h':
> > >   default:
> > >   goto usage;
> > > @@ -505,9 +509,9 @@ main(int argc, char *argv[])
> > >   exit(rc);
> > >  usage:
> > >   fprintf(stderr, "usage: %s"
> > > - " [-aDglnoprtvx] [-e program] [--del] [--numeric-ids]\n"
> > > - "\t[--port=portnumber] [--rsync-path=program] [--version]\n"
> > > - "\tsource ... directory\n",
> > > + " [-aDglnoprtvx] [-e program] [--address=bind_address] [--del]\n"
> > > + "\t[--numeric-ids] [--port=portnumber] [--rsync-path=program]\n"
> > > + "\t[--version] source ... directory\n",
> > >   getprogname());
> > >   exit(1);
> > >  }
> > > Index: rsync.1
> > > ===
> > > RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
> > > retrieving revision 1.18
> > > diff -u -p -r1.18 rsync.1
> > > --- rsync.1   6 May 2019 15:44:34 -   1.18
> > > +++ rsync.1   8 Aug 2019 13:41:02 -
> > > @@ -24,6 +24,7 @@
> > >  .Nm openrsync
> > >  .Op Fl aDglnoprtvx
> > >  .Op Fl e Ar program
> > > +.Op Fl -address Ns = Ns Ar bind_address
> > >  .Op Fl -del
> > >  .Op Fl -numeric-ids
> > >  .Op Fl -port Ns = Ns Ar service
> > > @@ -50,6 +51,12 @@ The arguments are as follows:
> > >  .It Fl a , -archive
> > >  Shorthand for
> > >  .Fl Dgloprt .
> > > +.It Fl -address Ns = Ns Ar bind_address
> > > +Use
> > > +.Ar bind_address
> > > +on the local machine as the source address of the connection.
> > > +Only useful when connecting to an rsync daemon and on systems with more 
> > > than
> > > +one address.
> > >  .It Fl D
> > >  Also transfer device and special files.
> > 

Re: openrsync --address option

2019-08-08 Thread Claudio Jeker
On Thu, Aug 08, 2019 at 11:06:30PM +0100, Stuart Henderson wrote:
> On 2019/08/08 15:42, Claudio Jeker wrote:
> > I need to be able to control the bind address for openrsync connections.
> > This implements this but it only works for connections to an rsync daemon.
> > For rsync over ssh you need to use -e 'ssh -b address' instead.
> 
> Works as expected for IPv4. For IPv6 it only works if you use a hostname that
> only has a v6 address and not also a v4 address. In this situation GPL rsync
> prints a warning (unless you also use -6), but then moves onto a v6 
> destination
> address.
> 
> (Maybe openrsync works if you use an IPv6 literal address as the destination,
> but I didn't see a way to do that).
> 
> OK for now, but as rpki-client may well end up used in places with fiddly
> addressing requirements (which is why you're adding it in the first place ;)
> it would be good to improve v6 as a later step.
> 

I think this has also to do with the way the host (aka destination) lookup
happens. My assumption is that you first try to connect to a IPv4 address
and so there is no binding to the IPv6 address happening.
To be honest, the GPL rsync way of doing things is also not entierly clear to
me. It may be necessary to add -4 and -6 support or maybe force the address
family to match bind_address and destination (or error out if they
mismatch) would be enough.

I will commit this tomorrow morning so that improvements can happen in
tree.
-- 
:wq Claudio

> > Index: extern.h
> > ===
> > RCS file: /cvs/src/usr.bin/rsync/extern.h,v
> > retrieving revision 1.31
> > diff -u -p -r1.31 extern.h
> > --- extern.h2 Jun 2019 17:36:48 -   1.31
> > +++ extern.h8 Aug 2019 13:41:02 -
> > @@ -120,6 +120,7 @@ struct  opts {
> > char*rsync_path;/* --rsync-path */
> > char*ssh_prog;  /* --rsh or -e */
> > char*port;  /* --port */
> > +   char*address;   /* --address */
> >  };
> >  
> >  /*
> > Index: main.c
> > ===
> > RCS file: /cvs/src/usr.bin/rsync/main.c,v
> > retrieving revision 1.47
> > diff -u -p -r1.47 main.c
> > --- main.c  3 Jun 2019 15:37:48 -   1.47
> > +++ main.c  8 Aug 2019 13:41:02 -
> > @@ -307,6 +307,7 @@ main(int argc, char *argv[])
> > { "no-times",   no_argument,_times,   0 },
> > { "verbose",no_argument,,   1 },
> > { "no-verbose", no_argument,,   0 },
> > +   { "address",required_argument, NULL,4 },
> > { NULL, 0,  NULL,   0 }};
> >  
> > /* Global pledge. */
> > @@ -380,6 +381,9 @@ main(int argc, char *argv[])
> > case 3:
> > opts.port = optarg;
> > break;
> > +   case 4:
> > +   opts.address = optarg;
> > +   break;
> > case 'h':
> > default:
> > goto usage;
> > @@ -505,9 +509,9 @@ main(int argc, char *argv[])
> > exit(rc);
> >  usage:
> > fprintf(stderr, "usage: %s"
> > -   " [-aDglnoprtvx] [-e program] [--del] [--numeric-ids]\n"
> > -   "\t[--port=portnumber] [--rsync-path=program] [--version]\n"
> > -   "\tsource ... directory\n",
> > +   " [-aDglnoprtvx] [-e program] [--address=bind_address] [--del]\n"
> > +   "\t[--numeric-ids] [--port=portnumber] [--rsync-path=program]\n"
> > +   "\t[--version] source ... directory\n",
> > getprogname());
> > exit(1);
> >  }
> > Index: rsync.1
> > ===
> > RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
> > retrieving revision 1.18
> > diff -u -p -r1.18 rsync.1
> > --- rsync.1 6 May 2019 15:44:34 -   1.18
> > +++ rsync.1 8 Aug 2019 13:41:02 -
> > @@ -24,6 +24,7 @@
> >  .Nm openrsync
> >  .Op Fl aDglnoprtvx
> >  .Op Fl e Ar program
> > +.Op Fl -address Ns = Ns Ar bind_address
> >  .Op Fl -del
> >  .Op Fl -numeric-ids
> >  .Op Fl -port Ns = Ns Ar service
> > @@ -50,6 +51,12 @@ The arguments are as follows:
> >  .It Fl a , -archive
> >  Shorthand for
> >  .Fl Dgloprt .
> > +.It Fl -address Ns = Ns Ar bind_address
> > +Use
> > +.Ar bind_address
> > +on the local machine as the source address of the connection.
> > +Only useful when connecting to an rsync daemon and on systems with more 
> > than
> > +one address.
> >  .It Fl D
> >  Also transfer device and special files.
> >  Shorthand for
> > Index: socket.c
> > ===
> > RCS file: /cvs/src/usr.bin/rsync/socket.c,v
> > retrieving revision 1.25
> > diff -u -p -r1.25 socket.c
> > --- socket.c3 Jun 2019 15:37:48 -   1.25
> > +++ socket.c8 Aug 2019 13:41:02 -

Re: openrsync --address option

2019-08-08 Thread Stuart Henderson
On 2019/08/08 15:42, Claudio Jeker wrote:
> I need to be able to control the bind address for openrsync connections.
> This implements this but it only works for connections to an rsync daemon.
> For rsync over ssh you need to use -e 'ssh -b address' instead.

Works as expected for IPv4. For IPv6 it only works if you use a hostname that
only has a v6 address and not also a v4 address. In this situation GPL rsync
prints a warning (unless you also use -6), but then moves onto a v6 destination
address.

(Maybe openrsync works if you use an IPv6 literal address as the destination,
but I didn't see a way to do that).

OK for now, but as rpki-client may well end up used in places with fiddly
addressing requirements (which is why you're adding it in the first place ;)
it would be good to improve v6 as a later step.


> -- 
> :wq Claudio
> 
> Index: extern.h
> ===
> RCS file: /cvs/src/usr.bin/rsync/extern.h,v
> retrieving revision 1.31
> diff -u -p -r1.31 extern.h
> --- extern.h  2 Jun 2019 17:36:48 -   1.31
> +++ extern.h  8 Aug 2019 13:41:02 -
> @@ -120,6 +120,7 @@ structopts {
>   char*rsync_path;/* --rsync-path */
>   char*ssh_prog;  /* --rsh or -e */
>   char*port;  /* --port */
> + char*address;   /* --address */
>  };
>  
>  /*
> Index: main.c
> ===
> RCS file: /cvs/src/usr.bin/rsync/main.c,v
> retrieving revision 1.47
> diff -u -p -r1.47 main.c
> --- main.c3 Jun 2019 15:37:48 -   1.47
> +++ main.c8 Aug 2019 13:41:02 -
> @@ -307,6 +307,7 @@ main(int argc, char *argv[])
>   { "no-times",   no_argument,_times,   0 },
>   { "verbose",no_argument,,   1 },
>   { "no-verbose", no_argument,,   0 },
> + { "address",required_argument, NULL,4 },
>   { NULL, 0,  NULL,   0 }};
>  
>   /* Global pledge. */
> @@ -380,6 +381,9 @@ main(int argc, char *argv[])
>   case 3:
>   opts.port = optarg;
>   break;
> + case 4:
> + opts.address = optarg;
> + break;
>   case 'h':
>   default:
>   goto usage;
> @@ -505,9 +509,9 @@ main(int argc, char *argv[])
>   exit(rc);
>  usage:
>   fprintf(stderr, "usage: %s"
> - " [-aDglnoprtvx] [-e program] [--del] [--numeric-ids]\n"
> - "\t[--port=portnumber] [--rsync-path=program] [--version]\n"
> - "\tsource ... directory\n",
> + " [-aDglnoprtvx] [-e program] [--address=bind_address] [--del]\n"
> + "\t[--numeric-ids] [--port=portnumber] [--rsync-path=program]\n"
> + "\t[--version] source ... directory\n",
>   getprogname());
>   exit(1);
>  }
> Index: rsync.1
> ===
> RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
> retrieving revision 1.18
> diff -u -p -r1.18 rsync.1
> --- rsync.1   6 May 2019 15:44:34 -   1.18
> +++ rsync.1   8 Aug 2019 13:41:02 -
> @@ -24,6 +24,7 @@
>  .Nm openrsync
>  .Op Fl aDglnoprtvx
>  .Op Fl e Ar program
> +.Op Fl -address Ns = Ns Ar bind_address
>  .Op Fl -del
>  .Op Fl -numeric-ids
>  .Op Fl -port Ns = Ns Ar service
> @@ -50,6 +51,12 @@ The arguments are as follows:
>  .It Fl a , -archive
>  Shorthand for
>  .Fl Dgloprt .
> +.It Fl -address Ns = Ns Ar bind_address
> +Use
> +.Ar bind_address
> +on the local machine as the source address of the connection.
> +Only useful when connecting to an rsync daemon and on systems with more than
> +one address.
>  .It Fl D
>  Also transfer device and special files.
>  Shorthand for
> Index: socket.c
> ===
> RCS file: /cvs/src/usr.bin/rsync/socket.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 socket.c
> --- socket.c  3 Jun 2019 15:37:48 -   1.25
> +++ socket.c  8 Aug 2019 13:41:02 -
> @@ -46,11 +46,34 @@ structsource {
>  };
>  
>  /*
> + * Try to bind to a local IP address matching the addres family passed.
> + * Return -1 on failure to bind to any address, 0 on success.
> + */
> +static int
> +inet_bind(int s, sa_family_t af, const struct source *bsrc, size_t bsrcsz)
> +{
> + size_t i;
> +
> + if (bsrc == NULL)
> + return 0;
> + for (i = 0; i < bsrcsz; i++) {
> + if (bsrc[i].family != af)
> + continue;
> + if (bind(s, (const struct sockaddr *)[i].sa,
> + bsrc[i].salen) == -1)
> + continue;
> + return 0;
> + }
> + return -1;
> +}
> +
> +/*
>   * Connect to an IP address representing a host.
>   * Return <0 on 

openrsync --address option

2019-08-08 Thread Claudio Jeker
I need to be able to control the bind address for openrsync connections.
This implements this but it only works for connections to an rsync daemon.
For rsync over ssh you need to use -e 'ssh -b address' instead.

-- 
:wq Claudio

Index: extern.h
===
RCS file: /cvs/src/usr.bin/rsync/extern.h,v
retrieving revision 1.31
diff -u -p -r1.31 extern.h
--- extern.h2 Jun 2019 17:36:48 -   1.31
+++ extern.h8 Aug 2019 13:41:02 -
@@ -120,6 +120,7 @@ struct  opts {
char*rsync_path;/* --rsync-path */
char*ssh_prog;  /* --rsh or -e */
char*port;  /* --port */
+   char*address;   /* --address */
 };
 
 /*
Index: main.c
===
RCS file: /cvs/src/usr.bin/rsync/main.c,v
retrieving revision 1.47
diff -u -p -r1.47 main.c
--- main.c  3 Jun 2019 15:37:48 -   1.47
+++ main.c  8 Aug 2019 13:41:02 -
@@ -307,6 +307,7 @@ main(int argc, char *argv[])
{ "no-times",   no_argument,_times,   0 },
{ "verbose",no_argument,,   1 },
{ "no-verbose", no_argument,,   0 },
+   { "address",required_argument, NULL,4 },
{ NULL, 0,  NULL,   0 }};
 
/* Global pledge. */
@@ -380,6 +381,9 @@ main(int argc, char *argv[])
case 3:
opts.port = optarg;
break;
+   case 4:
+   opts.address = optarg;
+   break;
case 'h':
default:
goto usage;
@@ -505,9 +509,9 @@ main(int argc, char *argv[])
exit(rc);
 usage:
fprintf(stderr, "usage: %s"
-   " [-aDglnoprtvx] [-e program] [--del] [--numeric-ids]\n"
-   "\t[--port=portnumber] [--rsync-path=program] [--version]\n"
-   "\tsource ... directory\n",
+   " [-aDglnoprtvx] [-e program] [--address=bind_address] [--del]\n"
+   "\t[--numeric-ids] [--port=portnumber] [--rsync-path=program]\n"
+   "\t[--version] source ... directory\n",
getprogname());
exit(1);
 }
Index: rsync.1
===
RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
retrieving revision 1.18
diff -u -p -r1.18 rsync.1
--- rsync.1 6 May 2019 15:44:34 -   1.18
+++ rsync.1 8 Aug 2019 13:41:02 -
@@ -24,6 +24,7 @@
 .Nm openrsync
 .Op Fl aDglnoprtvx
 .Op Fl e Ar program
+.Op Fl -address Ns = Ns Ar bind_address
 .Op Fl -del
 .Op Fl -numeric-ids
 .Op Fl -port Ns = Ns Ar service
@@ -50,6 +51,12 @@ The arguments are as follows:
 .It Fl a , -archive
 Shorthand for
 .Fl Dgloprt .
+.It Fl -address Ns = Ns Ar bind_address
+Use
+.Ar bind_address
+on the local machine as the source address of the connection.
+Only useful when connecting to an rsync daemon and on systems with more than
+one address.
 .It Fl D
 Also transfer device and special files.
 Shorthand for
Index: socket.c
===
RCS file: /cvs/src/usr.bin/rsync/socket.c,v
retrieving revision 1.25
diff -u -p -r1.25 socket.c
--- socket.c3 Jun 2019 15:37:48 -   1.25
+++ socket.c8 Aug 2019 13:41:02 -
@@ -46,11 +46,34 @@ struct  source {
 };
 
 /*
+ * Try to bind to a local IP address matching the addres family passed.
+ * Return -1 on failure to bind to any address, 0 on success.
+ */
+static int
+inet_bind(int s, sa_family_t af, const struct source *bsrc, size_t bsrcsz)
+{
+   size_t i;
+
+   if (bsrc == NULL)
+   return 0;
+   for (i = 0; i < bsrcsz; i++) {
+   if (bsrc[i].family != af)
+   continue;
+   if (bind(s, (const struct sockaddr *)[i].sa,
+   bsrc[i].salen) == -1)
+   continue;
+   return 0;
+   }
+   return -1;
+}
+
+/*
  * Connect to an IP address representing a host.
  * Return <0 on failure, 0 on try another address, >0 on success.
  */
 static int
-inet_connect(int *sd, const struct source *src, const char *host)
+inet_connect(int *sd, const struct source *src, const char *host,
+const struct source *bsrc, size_t bsrcsz)
 {
int  c, flags;
 
@@ -64,6 +87,11 @@ inet_connect(int *sd, const struct sourc
return -1;
}
 
+   if (inet_bind(*sd, src->family, bsrc, bsrcsz) == -1) {
+   ERR("bind");
+   return -1;
+   }
+
/*
 * Initiate blocking connection.
 * We use the blocking connect() instead of passing NONBLOCK to
@@ -102,11 +130,12 @@ inet_connect(int *sd, const struct sourc
  * in this case).
  */
 static struct source *