Subject: Re: bin/24940: rcp doesn't like ipv6-only hosts
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,>
From: Dave Tyson <Dave.Tyson@liverpool.ac.uk>
List: netbsd-bugs
Date: 09/28/2006 16:35:02
The following reply was made to PR bin/24940; it has been noted by GNATS.

From: Dave Tyson <Dave.Tyson@liverpool.ac.uk>
To: Manuel Bouyer <bouyer@antioche.eu.org>
Cc: gnats-bugs@NetBSD.org
Subject: Re: bin/24940: rcp doesn't like ipv6-only hosts
Date: Thu, 28 Sep 2006 16:24:31 +0100

 We have the same problems as you and it has bugged me sufficiently to 
 have a stab at fixing it.
 
 The following patch to /usr/src/lib/libc/net/rcmd.c will help in that rcp will
 now correctly obey the -4 and -6 options documented in the man page. This 
 means at least you can force a transfer with IPV4 if the IPV6 address is 
 unresponsive on a dual stack host. I think a fix to automatically make rcp 
 use IPV4 if the IPV6 connection fails is going to be very messy because of 
 the way a sub-process is spawned to do the copying. Arguably the fix should 
 be in rcmd.c as this is where the problem is solved for rsh, however, because 
 of the sub-process the only thing which knows if the connection has failed is 
 the rcp command itself. Changing this to check the available address families 
 and invoking the connection with IPV6 and falling back to IPV4 is an option, 
 but I view it as a kludge as the real problem is the sub-process. Other 
 *BSD's seem to have done away with this to avoid this issue. Maybe an import 
 of the OpenBSD/FreeBSD code is the most satisfactory solution. In the 
 meantime the fix below should apply cleanly to 3, 4 and current - If people 
 think its OK could it be pulled up into the 3 & 4 branches?
 
 --- rcmd.c.orig 2005-07-09 23:51:22.000000000 +0100
 +++ rcmd.c      2006-09-27 22:27:41.000000000 +0100
 @@ -78,7 +78,7 @@
  int    __ivaliduser_sa __P((FILE *, struct sockaddr *, socklen_t, const char 
 *,
             const char *));
  static int rshrcmd __P((char **, u_int32_t, const char *, const char *,
 -           const char *, int *, const char *));
 +           const char *, int *, const char *, const int));
  static int resrcmd __P((struct addrinfo *, char **, u_int32_t, const char *,
             const char *, const char *, int *));
  static int __icheckhost __P((struct sockaddr *, socklen_t, const char *));
 @@ -142,7 +142,7 @@
         sp = getservbyname("shell", "tcp");
         if (sp != NULL && sp->s_port == rport)
                 error = rshrcmd(ahost, (u_int32_t)rport,
 -                   locuser, remuser, cmd, fd2p, getenv("RCMD_CMD"));
 +                   locuser, remuser, cmd, fd2p, getenv("RCMD_CMD"), af);
         else
                 error = resrcmd(res, ahost, (u_int32_t)rport,
                     locuser, remuser, cmd, fd2p);
 @@ -379,12 +379,13 @@
   */
  /* ARGSUSED */
  static int
 -rshrcmd(ahost, rport, locuser, remuser, cmd, fd2p, rshcmd)
 +rshrcmd(ahost, rport, locuser, remuser, cmd, fd2p, rshcmd, af)
         char    **ahost;
         u_int32_t       rport;
         const   char *locuser, *remuser, *cmd;
         int     *fd2p;
         const   char *rshcmd;
 +       const   int af;
  {
         pid_t pid;
         int sp[2], ep[2];
 @@ -476,11 +477,18 @@
                         else
                                 rshcmd = pw->pw_shell;
                         p = strrchr(rshcmd, '/');
 -                       execlp(rshcmd, p ? p + 1 : rshcmd, "-c", cmd, NULL);
 +                       if (af == AF_UNSPEC)
 +                               execlp(rshcmd, p ? p + 1 : rshcmd, "-c", cmd, 
 NULL);
 +                       else
 +                               execlp(rshcmd, p ? p + 1 : rshcmd, af == 
 AF_INET ? "-4" : "-6", "-c",
 +                                       cmd, NULL);
                 } else {
                         p = strrchr(rshcmd, '/');
 -                       execlp(rshcmd, p ? p + 1 : rshcmd, *ahost, "-l",
 -                           remuser, cmd, NULL);
 +                       if (af == AF_UNSPEC)
 +                               execlp(rshcmd, p ? p + 1 : rshcmd, *ahost, 
 "-l", remuser, cmd, NULL);
 +                       else
 +                               execlp(rshcmd, p ? p + 1 : rshcmd, *ahost, af 
 == AF_INET ? "-4" : "-6",
 +                                       "-l", remuser, cmd, NULL);
                 }
                 warn("rshrcmd: exec %s", rshcmd);
                 _exit(1);
 
 
 -- 
 =====================================================================
 Computing Services Dept         Phone/Fax: 0151-794-3731/3759
 The University of Liverpool     Email: dtyson@liv.ac.uk
 Chadwick Tower, Peach Street    WWW:   http://www.liv.ac.uk/~dtyson
 Liverpool L69 7ZF               Open Source O/S: www.netbsd.org
 =====================================================================