I'm ok with the diff, can I get another ok before commiting ?

On Tue, Apr 24, 2012 at 10:53:34PM -0400, Lawrence Teo wrote:
> On Wed, Apr 18, 2012 at 11:58:26PM -0400, Lawrence Teo wrote:
> > This diff adds a -s flag to ftp(1) to let the user specify the
> > source IP address of the connection.  This is useful when using
> > ftp(1) over VPN tunnels or when an alternate source IP is required
> > to fetch a file from a FTP/HTTP/HTTPS server due to access control
> > policies.
> 
> I have revised this diff based on feedback from haesbaert@.  The primary
> change is to use AI_NUMERICHOST in the hints addrinfo struct that's
> passed to getaddrinfo().
> 
> The resulting ftp(1) binary still passes all 48 tests from my test
> script at http://lteo.net/stuff/ftp-test
> 
> Comments and more testing are welcome!
> 
> Thanks,
> Lawrence
> 
> 
> Index: fetch.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
> retrieving revision 1.104
> diff -u -p -r1.104 fetch.c
> --- fetch.c   23 Apr 2012 21:22:02 -0000      1.104
> +++ fetch.c   25 Apr 2012 02:12:13 -0000
> @@ -179,7 +179,7 @@ url_get(const char *origline, const char
>       char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL;
>       char *epath, *redirurl, *loctail;
>       int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1;
> -     struct addrinfo hints, *res0, *res;
> +     struct addrinfo hints, *res0, *res, *ares = NULL;
>       const char * volatile savefile;
>       char * volatile proxyurl = NULL;
>       char *cookie = NULL;
> @@ -198,6 +198,7 @@ url_get(const char *origline, const char
>  #endif /* !SMALL */
>       SSL *ssl = NULL;
>       int status;
> +     int save_errno;
>  
>       direction = "received";
>  
> @@ -490,6 +491,17 @@ noslash:
>               goto cleanup_url_get;
>       }
>  
> +#ifndef SMALL
> +     if (srcaddr) {
> +             hints.ai_flags |= AI_NUMERICHOST;
> +             error = getaddrinfo(srcaddr, NULL, &hints, &ares);
> +             if (error) {
> +                     warnx("%s: %s", gai_strerror(error), srcaddr);
> +                     goto cleanup_url_get;
> +             }
> +     }
> +#endif /* !SMALL */
> +
>       s = -1;
>       for (res = res0; res; res = res->ai_next) {
>               if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
> @@ -504,10 +516,28 @@ noslash:
>                       continue;
>               }
>  
> +#ifndef SMALL
> +             if (srcaddr) {
> +                     if (ares->ai_family != res->ai_family) {
> +                             close(s);
> +                             s = -1;
> +                             errno = EINVAL;
> +                             cause = "bind";
> +                             continue;
> +                     }
> +                     if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
> +                             save_errno = errno;
> +                             close(s);
> +                             errno = save_errno;
> +                             s = -1;
> +                             cause = "bind";
> +                             continue;
> +                     }
> +             }
> +#endif /* !SMALL */
> +
>  again:
>               if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
> -                     int save_errno;
> -
>                       if (errno == EINTR)
>                               goto again;
>                       save_errno = errno;
> @@ -532,6 +562,10 @@ again:
>               break;
>       }
>       freeaddrinfo(res0);
> +#ifndef SMALL
> +     if (srcaddr)
> +             freeaddrinfo(ares);
> +#endif /* !SMALL */
>       if (s < 0) {
>               warn("%s", cause);
>               goto cleanup_url_get;
> Index: ftp.1
> ===================================================================
> RCS file: /cvs/src/usr.bin/ftp/ftp.1,v
> retrieving revision 1.81
> diff -u -p -r1.81 ftp.1
> --- ftp.1     26 Jul 2010 21:31:34 -0000      1.81
> +++ ftp.1     25 Apr 2012 02:12:13 -0000
> @@ -42,10 +42,12 @@
>  .Op Fl k Ar seconds
>  .Op Fl P Ar port
>  .Op Fl r Ar seconds
> +.Op Fl s Ar srcaddr
>  .Op Ar host Op Ar port
>  .Nm ftp
>  .Op Fl C
>  .Op Fl o Ar output
> +.Op Fl s Ar srcaddr
>  .Sm off
>  .No ftp:// Oo Ar user : password No @
>  .Oc Ar host Oo : Ar port
> @@ -57,6 +59,7 @@
>  .Op Fl C
>  .Op Fl c Ar cookie
>  .Op Fl o Ar output
> +.Op Fl s Ar srcaddr
>  .Sm off
>  .No http:// Ar host Oo : Ar port
>  .Oc No / Ar file
> @@ -66,6 +69,7 @@
>  .Op Fl C
>  .Op Fl c Ar cookie
>  .Op Fl o Ar output
> +.Op Fl s Ar srcaddr
>  .Sm off
>  .No https:// Ar host Oo : Ar port
>  .Oc No / Ar file
> @@ -74,6 +78,7 @@
>  .Nm ftp
>  .Op Fl C
>  .Op Fl o Ar output
> +.Op Fl s Ar srcaddr
>  .Sm off
>  .No file: Ar file
>  .Sm on
> @@ -81,6 +86,7 @@
>  .Nm ftp
>  .Op Fl C
>  .Op Fl o Ar output
> +.Op Fl s Ar srcaddr
>  .Sm off
>  .Ar host : No / Ar file Oo /
>  .Oc
> @@ -220,6 +226,12 @@ if the server does not support passive c
>  .It Fl r Ar seconds
>  Retry to connect if failed, pausing for number of
>  .Ar seconds .
> +.It Fl s Ar srcaddr
> +Use
> +.Ar srcaddr
> +on the local machine as the source address
> +of the connection.
> +Only useful on systems with more than one address.
>  .It Fl t
>  Enables packet tracing.
>  .It Fl V
> Index: ftp.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/ftp/ftp.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 ftp.c
> --- ftp.c     3 Sep 2010 03:49:37 -0000       1.81
> +++ ftp.c     25 Apr 2012 02:12:14 -0000
> @@ -114,7 +114,7 @@ hookup(char *host, char *port)
>  {
>       int s, tos, error;
>       static char hostnamebuf[MAXHOSTNAMELEN];
> -     struct addrinfo hints, *res, *res0;
> +     struct addrinfo hints, *res, *res0, *ares;
>       char hbuf[NI_MAXHOST];
>       char *cause = "unknown";
>       socklen_t namelen;
> @@ -163,6 +163,25 @@ hookup(char *host, char *port)
>       else
>               strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
>       hostname = hostnamebuf;
> +
> +#ifndef SMALL
> +     if (srcaddr) {
> +             struct addrinfo ahints;
> +
> +             memset(&ahints, 0, sizeof(ahints));
> +             ahints.ai_family = family;
> +             ahints.ai_socktype = SOCK_STREAM;
> +             ahints.ai_flags |= AI_NUMERICHOST;
> +             ahints.ai_protocol = 0;
> +
> +             error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
> +             if (error) {
> +                     warnx("%s: %s", gai_strerror(error), srcaddr);
> +                     code = -1;
> +                     return (0);
> +             }
> +     }
> +#endif /* !SMALL */
>       
>       s = -1;
>       for (res = res0; res; res = res->ai_next) {
> @@ -183,6 +202,25 @@ hookup(char *host, char *port)
>                       cause = "socket";
>                       continue;
>               }
> +#ifndef SMALL
> +             if (srcaddr) {
> +                     if (ares->ai_family != res->ai_family) {
> +                             close(s);
> +                             s = -1;
> +                             errno = EINVAL;
> +                             cause = "bind";
> +                             continue;
> +                     }
> +                     if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
> +                             cause = "bind";
> +                             error = errno;
> +                             close(s);
> +                             errno = error;
> +                             s = -1;
> +                             continue;
> +                     }
> +             }
> +#endif /* !SMALL */
>               while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
>                               && errno == EINTR) {
>                       ;
> @@ -218,6 +256,12 @@ hookup(char *host, char *port)
>       namelen = res->ai_addrlen;
>       freeaddrinfo(res0);
>       res0 = res = NULL;
> +#ifndef SMALL
> +     if (srcaddr) {
> +             freeaddrinfo(ares);
> +             ares = NULL;
> +     }
> +#endif /* !SMALL */
>       if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) {
>               warn("getsockname");
>               code = -1;
> @@ -1240,12 +1284,31 @@ initconn(void)
>       u_int af, hal, pal;
>       char *pasvcmd = NULL;
>       socklen_t namelen;
> +     struct addrinfo *ares;
>  
>       if (myctladdr.su_family == AF_INET6
>        && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
>         || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
>               warnx("use of scoped address can be troublesome");
>       }
> +#ifndef SMALL
> +     if (srcaddr) {
> +             struct addrinfo ahints;
> +
> +             memset(&ahints, 0, sizeof(ahints));
> +             ahints.ai_family = family;
> +             ahints.ai_socktype = SOCK_STREAM;
> +             ahints.ai_flags |= AI_NUMERICHOST;
> +             ahints.ai_protocol = 0;
> +
> +             error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
> +             if (error) {
> +                     warnx("%s: %s", gai_strerror(error), srcaddr);
> +                     code = -1;
> +                     return (0);
> +             }
> +     }
> +#endif /* !SMALL */
>  reinit:
>       if (passivemode) {
>               data_addr = myctladdr;
> @@ -1255,6 +1318,13 @@ reinit:
>                       return (1);
>               }
>  #ifndef SMALL
> +             if (srcaddr) {
> +                     if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) {
> +                             warn("bind");
> +                             close(data);
> +                             return (1);
> +                     }
> +             }
>               if ((options & SO_DEBUG) &&
>                   setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
>                              sizeof(on)) < 0)
> Index: ftp_var.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/ftp/ftp_var.h,v
> retrieving revision 1.31
> diff -u -p -r1.31 ftp_var.h
> --- ftp_var.h 2 Jul 2010 22:01:10 -0000       1.31
> +++ ftp_var.h 25 Apr 2012 02:12:14 -0000
> @@ -165,6 +165,7 @@ size_t      cursor_argc;          /* location of cu
>  size_t         cursor_argo;          /* offset of cursor in 
> margv[cursor_argc] */
>  char  *cookiefile;           /* cookie jar to use */
>  int    resume;               /* continue transfer */
> +char  *srcaddr;              /* source address to bind to */
>  #endif /* !SMALL */
>  
>  off_t        bytes;                  /* current # of bytes read */
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/ftp/main.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 main.c
> --- main.c    29 Jun 2010 23:12:33 -0000      1.81
> +++ main.c    25 Apr 2012 02:12:14 -0000
> @@ -114,6 +114,7 @@ main(volatile int argc, char *argv[])
>       hist = NULL;
>       cookiefile = NULL;
>       resume = 0;
> +     srcaddr = NULL;
>       marg_sl = sl_init();
>  #endif /* !SMALL */
>       mark = HASHBYTES;
> @@ -174,7 +175,7 @@ main(volatile int argc, char *argv[])
>       cookiefile = getenv("http_cookies");
>  #endif /* !SMALL */
>  
> -     while ((ch = getopt(argc, argv, "46AaCc:dEegik:mno:pP:r:tvV")) != -1) {
> +     while ((ch = getopt(argc, argv, "46AaCc:dEegik:mno:pP:r:s:tvV")) != -1) 
> {
>               switch (ch) {
>               case '4':
>                       family = PF_INET;
> @@ -275,6 +276,12 @@ main(volatile int argc, char *argv[])
>                       }
>                       break;
>  
> +             case 's':
> +#ifndef SMALL
> +                     srcaddr = optarg;
> +#endif /* !SMALL */
> +                     break;
> +
>               case 't':
>                       trace = 1;
>                       break;
> @@ -756,15 +763,21 @@ usage(void)
>           "       %s [-C] "
>  #endif /* !SMALL */
>           "[-o output] "
> +#ifndef SMALL
> +         "[-s srcaddr] "
> +#endif /* !SMALL */
>           "ftp://[user:password@]host[:port]/file[/] ...\n"
>           "       %s "
>  #ifndef SMALL
>           "[-C] [-c cookie] "
>  #endif /* !SMALL */
>           "[-o output] "
> +#ifndef SMALL
> +         "[-s srcaddr] "
> +#endif /* !SMALL */
>           "http://host[:port]/file ...\n"
>  #ifndef SMALL
> -         "       %s [-C] [-c cookie] [-o output] "
> +         "       %s [-C] [-c cookie] [-o output] [-s srcaddr] "
>           "https://host[:port]/file ...\n"
>  #endif /* !SMALL */
>           "       %s "
> @@ -772,12 +785,19 @@ usage(void)
>           "[-C] "
>  #endif /* !SMALL */
>           "[-o output] "
> +#ifndef SMALL
> +         "[-s srcaddr] "
> +#endif /* !SMALL */
>           "file:file ...\n"
>           "       %s "
>  #ifndef SMALL
>           "[-C] "
>  #endif /* !SMALL */
> -         "[-o output] host:/file[/] ...\n",
> +         "[-o output] "
> +#ifndef SMALL
> +         "[-s srcaddr] "
> +#endif /* !SMALL */
> +         "host:/file[/] ...\n",
>  #ifndef SMALL
>           __progname, __progname, __progname, __progname, __progname,
>           __progname);

Reply via email to