commit-inetutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Inetutils branch, master, updated. inetutils-1_8-86-gf4ff1bc


From: Mats Erik Andersson
Subject: [SCM] GNU Inetutils branch, master, updated. inetutils-1_8-86-gf4ff1bc
Date: Sat, 16 Apr 2011 22:23:39 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Inetutils ".

The branch, master has been updated
       via  f4ff1bc8ebb92855507f854589fd50de0b1930a7 (commit)
      from  4d82d1d7ae718a2407f14780d3edf0ab3cfc6754 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=f4ff1bc8ebb92855507f854589fd50de0b1930a7


commit f4ff1bc8ebb92855507f854589fd50de0b1930a7
Author: Mats Erik Andersson <address@hidden>
Date:   Fri Apr 8 15:36:51 2011 +0200

    ftp: Prepare for later IPv6 support.
    
    The code basis is adapted to a minimal dependency on the
    adress family AF_INET.  At the same time the exchange
    responses for EPRT, EPSV, LPRT, and LPSV are implemented.

diff --git a/ChangeLog b/ChangeLog
index cc1ee67..67e6427 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2011-04-08  Mats Erik Andersson <address@hidden>
+
+       * ftp/cmds.c (setepsv4): New function.
+       (setpeer): Use the variable PORT in host byte order.
+       (status): New status message, based on DOEPSV4.
+       * ftp/cmdtab.c (epsv4help): New string variable.
+       (cmdtab): New command `epsv4` inserted.
+       * ftp/extern.h (setepsv4): New declaration.
+       * ftp/ftp_var.h (doepsv4): New variable.
+       * ftp/main.c (main): Initiate DOEPSV4 to `off`.
+       * ftp/ftp.c: Explicitly condition IP_TOS on address family AF_INET.
+       Replace `struct sockaddr_in` by `struct sockaddr_storage`. Always
+       use CTLADDRLEN when referencing address lengths.
+       (ctladdrlen, ia, portstr): New variables.
+       (FTP_CONNECT_TIMEOUT): New macro.
+       (hookup): Replace resolver `gethostbyname` by `getaddrinfo`.
+       A timed alarm interrupts any slow connection attempt.
+       (getreply): New server return codes for `LPSV` and `EPSV`.
+       (initconn): New protocol methods `EPSV` and `LPSV`.
+       (initconn) [noport]: Trivial switch statement on `AF_INET`.
+       New protocol methods `EPRT` and `LPRT`.
+
 2011-03-27  Mike Frysinger  <address@hidden>
 
        * configure.ac: Use AC_CANONICAL_HOST instead of AC_CANONICAL_SYSTEM.
diff --git a/ftp/cmds.c b/ftp/cmds.c
index 716d8c0..39b6294 100644
--- a/ftp/cmds.c
+++ b/ftp/cmds.c
@@ -227,10 +227,9 @@ setpeer (int argc, char **argv)
          code = -1;
          return;
        }
-      port = htons (port);
     }
   else
-    port = sp->s_port;
+    port = ntohs (sp->s_port);
 
   host = hookup (host, port);
   if (host)
@@ -1092,6 +1091,7 @@ status (int argc, char **argv)
     }
   printf ("Hash mark printing: %s; Use of PORT cmds: %s\n",
          onoff (hash), onoff (sendport));
+  printf ("Use of EPRT/EPSV for IPv4: %s\n", onoff (doepsv4));
   if (macnum > 0)
     {
       printf ("Macros:\n");
@@ -1158,6 +1158,18 @@ setverbose (int argc, char **argv)
 }
 
 /*
+ * Toggle use of EPRT/EPRT for IPv4.
+ */
+void
+setepsv4 (int argc, char **argv)
+{
+
+  doepsv4 = !doepsv4;
+  printf ("Use of EPRT/EPSV for IPv4: %s.\n", onoff (doepsv4));
+  code = doepsv4;
+}
+
+/*
  * Toggle PORT cmd use before each data connection.
  */
 void
diff --git a/ftp/cmdtab.c b/ftp/cmdtab.c
index d26896f..8910cf0 100644
--- a/ftp/cmdtab.c
+++ b/ftp/cmdtab.c
@@ -74,6 +74,7 @@ char debughelp[] = "toggle/set debugging mode";
 char dirhelp[] = "list contents of remote directory";
 char disconhelp[] = "terminate ftp session";
 char domachelp[] = "execute macro";
+char epsv4help[] ="toggle the use of EPRT/EPSV for IPv4";
 char formhelp[] = "set file transfer format";
 char globhelp[] = "toggle metacharacter expansion of local file names";
 char hashhelp[] = "toggle printing `#' for each buffer transferred";
@@ -145,6 +146,7 @@ static struct cmd cmdtab[] = {
   {"debug", debughelp, 0, 0, 0, setdebug},
   {"dir", dirhelp, 1, 1, 1, ls},
   {"disconnect", disconhelp, 0, 1, 1, disconnect},
+  {"epsv4", epsv4help, 0, 0, 0, setepsv4},
   {"form", formhelp, 0, 1, 1, setform},
   {"get", receivehelp, 1, 1, 1, get},
   {"glob", globhelp, 0, 0, 0, setglob},
diff --git a/ftp/extern.h b/ftp/extern.h
index 632d54c..1c4719f 100644
--- a/ftp/extern.h
+++ b/ftp/extern.h
@@ -127,6 +127,7 @@ void setbinary (int, char **);
 void setcase (int, char **);
 void setcr (int, char **);
 void setdebug (int, char **);
+void setepsv4 (int, char **);
 void setform (int, char **);
 void setftmode (int, char **);
 void setglob (int, char **);
diff --git a/ftp/ftp.c b/ftp/ftp.c
index 4aa067a..f144570 100644
--- a/ftp/ftp.c
+++ b/ftp/ftp.c
@@ -96,98 +96,108 @@ extern int pclose (FILE *);
 
 extern int h_errno;
 
-struct sockaddr_in hisctladdr;
-struct sockaddr_in data_addr;
 int data = -1;
 int abrtflag = 0;
 jmp_buf ptabort;
 int ptabflg;
 int ptflag = 0;
-struct sockaddr_in myctladdr;
 off_t restart_point = 0;
 
+struct sockaddr_storage myctladdr;
+struct sockaddr_storage hisctladdr;
+struct sockaddr_storage data_addr;
+socklen_t ctladdrlen;  /* Applies to all addresses.  */
+
+/* For temporary resolving: hookup() and initconn()/noport.  */
+static char ia[INET6_ADDRSTRLEN];
+static char portstr[10];
 
 FILE *cin, *cout;
 
+#if ! defined (FTP_CONNECT_TIMEOUT) || FTP_CONNECT_TIMEOUT < 1
+# define FTP_CONNECT_TIMEOUT 5
+#endif
+
 char *
 hookup (char *host, int port)
 {
-  struct hostent *hp = 0;
+  struct addrinfo hints, *ai = NULL, *res = NULL;
+  struct timeval timeout;
+  int status, again = 0;
   int s, tos;
   socklen_t len;
   static char hostnamebuf[80];
 
-  memset ((char *) &hisctladdr, 0, sizeof (hisctladdr));
-  hisctladdr.sin_addr.s_addr = inet_addr (host);
-  if (hisctladdr.sin_addr.s_addr != -1)
-    {
-      hisctladdr.sin_family = AF_INET;
-      strncpy (hostnamebuf, host, sizeof (hostnamebuf));
-    }
-  else
-    {
-      hp = gethostbyname (host);
-      if (hp == NULL)
-       {
-#ifdef HAVE_HSTRERROR
-         error (0, 0, "%s: %s", host, hstrerror (h_errno));
-#else
-         char *pfx = malloc (strlen (program_name) + 2 + strlen (host) + 1);
-         sprintf (pfx, "%s: %s", program_name, host);
-         herror (pfx);
-#endif
-         code = -1;
-         return ((char *) 0);
-       }
-      hisctladdr.sin_family = hp->h_addrtype;
-      memmove ((caddr_t) & hisctladdr.sin_addr,
-#ifdef HAVE_STRUCT_HOSTENT_H_ADDR_LIST
-              hp->h_addr_list[0],
-#else
-              hp->h_addr,
-#endif
-              hp->h_length);
-      strncpy (hostnamebuf, hp->h_name, sizeof (hostnamebuf));
-    }
-  hostname = hostnamebuf;
-  s = socket (hisctladdr.sin_family, SOCK_STREAM, 0);
-  if (s < 0)
+  snprintf (portstr, sizeof (portstr) - 1, "%8u", port);
+  memset (&hisctladdr, 0, sizeof (hisctladdr));
+  memset (&hints, 0, sizeof (hints));
+
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_CANONNAME;
+
+  status = getaddrinfo (host, portstr, &hints, &res);
+  if (status)
     {
-      error (0, errno, "socket");
+      error (0, 0, "%s: %s", host, gai_strerror (status));
       code = -1;
-      return (0);
+      return ((char *) 0);
     }
-  hisctladdr.sin_port = port;
-  while (connect (s, (struct sockaddr *) &hisctladdr, sizeof (hisctladdr)) <
-        0)
+  strncpy (hostnamebuf, res->ai_canonname, sizeof (hostnamebuf));
+  hostname = hostnamebuf;
+
+  for (ai = res; ai != NULL; ai = ai->ai_next, ++again)
     {
-#ifdef HAVE_STRUCT_HOSTENT_H_ADDR_LIST
-      if (hp && hp->h_addr_list[1])
+      if (again)
+        {
+         getnameinfo (ai->ai_addr, ai->ai_addrlen, ia, sizeof (ia),
+                       NULL, 0, NI_NUMERICHOST);
+         error (0, 0, "Trying %s ...", ia);
+       }
+
+      s = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+      if (s < 0)
+       continue;
+
+      timeout.tv_sec = FTP_CONNECT_TIMEOUT;
+      timeout.tv_usec = 0;
+      if (setsockopt (s, SOL_SOCKET, SO_SNDTIMEO, &timeout,
+                       sizeof (timeout)) < 0 && debug)
+       error (0, errno, "setsockopt (SO_SNDTIMEO)");
+
+      if (connect (s, ai->ai_addr, ai->ai_addrlen) < 0)
        {
-         int oerrno = errno;
-         char *ia;
+         int oerrno = (errno != EINPROGRESS) ? errno : ETIMEDOUT;
 
-         ia = inet_ntoa (hisctladdr.sin_addr);
+         getnameinfo (ai->ai_addr, ai->ai_addrlen, ia, sizeof (ia),
+                       NULL, 0, NI_NUMERICHOST);
          error (0, oerrno, "connect to address %s", ia);
-         hp->h_addr_list++;
-         memmove ((caddr_t) & hisctladdr.sin_addr,
-                  hp->h_addr_list[0], hp->h_length);
-         fprintf (stdout, "Trying %s...\n", inet_ntoa (hisctladdr.sin_addr));
          close (s);
-         s = socket (hisctladdr.sin_family, SOCK_STREAM, 0);
-         if (s < 0)
-           {
-             error (0, errno, "socket");
-             code = -1;
-             return (0);
-           }
+         s = -1;
          continue;
        }
-#endif
-      error (0, errno, "connect");
+
+      /* A standing connection is found: register the address.  */
+      timeout.tv_sec = 0;
+      timeout.tv_usec = 0;
+      (void) setsockopt (s, SOL_SOCKET, SO_SNDTIMEO, &timeout,
+                         sizeof (timeout));
+
+      ctladdrlen = ai->ai_addrlen;
+      memmove ((caddr_t) &hisctladdr, ai->ai_addr, ai->ai_addrlen);
+      break;
+    } /* for (ai = ai->ai_next) */
+
+  if (res)
+    freeaddrinfo (res);
+
+  if (ai == NULL)
+    {
+      error (0, 0, "no respons from host");
       code = -1;
       goto bad;
     }
+
   len = sizeof (myctladdr);
   if (getsockname (s, (struct sockaddr *) &myctladdr, &len) < 0)
     {
@@ -195,11 +205,14 @@ hookup (char *host, int port)
       code = -1;
       goto bad;
     }
+
 #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_LOWDELAY
   tos = IPTOS_LOWDELAY;
-  if (setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
+  if (myctladdr.ss_family == AF_INET &&
+       setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
     error (0, errno, "setsockopt TOS (ignored)");
 #endif
+
   cin = fdopen (s, "r");
   /* dup(s) is for sake of stdio implementations who do not
      allow two fdopen's on the same file-descriptor */
@@ -225,6 +238,7 @@ hookup (char *host, int port)
       code = -1;
       goto bad;
     }
+
 #ifdef SO_OOBINLINE
   {
     int on = 1;
@@ -240,7 +254,7 @@ hookup (char *host, int port)
   return (hostname);
 bad:
   close (s);
-  return NULL;
+  return ((char *) 0);
 }
 
 int
@@ -445,7 +459,7 @@ getreply (int expecteof)
            }
          if (dig < 4 && isdigit (c))
            code = code * 10 + (c - '0');
-         if (!pflag && code == 227)
+         if (!pflag && (code == 227 || code == 228 || code == 229)) /* PASV || 
LPSV || EPSV */
            pflag = 1;
          if (dig > 4 && pflag == 1 && isdigit (c))
            pflag = 2;
@@ -1108,15 +1122,18 @@ abort:
 int
 initconn (void)
 {
-  char *p, *a;
+  char *p = NULL, *a = NULL;
   int result, tmpno = 0;
+  int good_epsv = 0, good_lpsv = 0, j;
   socklen_t len;
   int on = 1;
-  int a0, a1, a2, a3, p0, p1;
+  uint32_t a0, a1, a2, a3, p0, p1, port;
+  uint32_t af, hal, h[4], pal; /* RFC 1639: LPSV resonse.  */
+  struct sockaddr_in *data_addr_sa4 = (struct sockaddr_in *) &data_addr;
 
   if (passivemode)
     {
-      data = socket (AF_INET, SOCK_STREAM, 0);
+      data = socket (myctladdr.ss_family, SOCK_STREAM, 0);
       if (data < 0)
        {
          perror ("ftp: socket");
@@ -1126,47 +1143,130 @@ initconn (void)
          setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on,
                      sizeof (on)) < 0)
        perror ("ftp: setsockopt (ignored)");
-      if (command ("PASV") != COMPLETE)
-       {
-         printf ("Passive mode refused.\n");
-         goto bad;
-       }
 
-      /*
-       * What we've got at this point is a string of comma
-       * separated one-byte unsigned integer values.
-       * The first four are the an IP address. The fifth is
-       * the MSB of the port number, the sixth is the LSB.
-       * From that we'll prepare a sockaddr_in.
+      /* Be contemporary:
+       *   first try EPSV,
+       *   then fall back to PASV/LPSV.
        */
+      switch (myctladdr.ss_family)
+        {
+         case AF_INET:
+           if (doepsv4 && command ("EPSV") == COMPLETE)
+             {
+               good_epsv = 1;
+               break;
+             }
+           if (doepsv4)
+             {
+               /* When arriving here, EPSV failed. Prevent new attempts.  */
+               doepsv4 = 0;
+             }
+           if (command ("PASV") == COMPLETE)
+               break;
+           if (command ("LPSV") == COMPLETE)
+             {
+               good_lpsv = 1;
+               break;
+             }
+           printf ("Passive mode refused.\n");
+           goto bad;
+           break;
+       }
 
-      if (sscanf (pasv, "%d,%d,%d,%d,%d,%d",
-                 &a0, &a1, &a2, &a3, &p0, &p1) != 6)
+      if (good_epsv)
        {
-         printf ("Passive mode address scan failure. Shouldn't happen!\n");
-         goto bad;
+         /* EPSV: IPv4
+          *
+          * Expected response (perl): pasv =~ '%u|'
+          * This communicates a port number.
+          */
+         if (sscanf (pasv, "%u|", &port) != 1)
+           {
+             printf ("Extended passive mode scan failure. "
+                       "Should not happen!\n");
+             (void) command ("ABOR");  /* Cancel any open connection.  */
+             goto bad;
+           }
+         data_addr = hisctladdr;
+         switch (data_addr.ss_family)
+           {
+             case AF_INET:
+               data_addr_sa4->sin_port = htons (port);
+               break;
+           }
+       } /* EPSV */
+      else if (good_lpsv)
+       {
+         /* LPSV: IPv4
+          *
+          * At this point we have got a string of comma
+          * separated, one-byte unsigned integer values.
+          * Length and interpretation depends on address
+          * family.
+          */
+
+         if (myctladdr.ss_family == AF_INET)
+           {
+             if ((sscanf (pasv, "%u," /* af */
+                               "%u,%u,%u,%u,%u," /* hal, h[4] */
+                               "%u,%u,%u", /* pal, p0, p1 */
+                               &af, &hal, &h[0], &h[1], &h[2], &h[3], &pal, 
&p0, &p1) != 9)
+                 || (/* Strong checking */ af != 4 || hal != 4 || pal != 2) )
+               {
+                 printf ("Passive mode address scan failure. "
+                         "Shouldn't happen!\n");
+                 (void) command ("ABOR");      /* Cancel any open connection.  
*/
+                 goto bad;
+               }
+             for (j = 0; j < 4; ++j)
+               h[j] &= 0xff; /* Mask only the significant bits.  */
+
+             data_addr.ss_family = AF_INET;
+             data_addr_sa4->sin_port =
+                 htons (((p0 & 0xff) << 8) | (p1 & 0xff));
+
+               {
+                 uint32_t *pu32 = (uint32_t *) &data_addr_sa4->sin_addr.s_addr;
+                 pu32[0] = htonl ( (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | 
h[3]);
+               }
+           }
        }
+      else /* !EPSV && !LPSV */
+       { /* PASV */
+         if (myctladdr.ss_family == AF_INET)
+           { /* PASV */
+             if (sscanf (pasv, "%u,%u,%u,%u,%u,%u",
+                         &a0, &a1, &a2, &a3, &p0, &p1) != 6)
+               {
+                 printf ("Passive mode address scan failure. "
+                         "Shouldn't happen!\n");
+                 (void) command ("ABOR");      /* Cancel any open connection.  
*/
+                 goto bad;
+               }
+             data_addr.ss_family = AF_INET;
+             data_addr_sa4->sin_addr.s_addr =
+                 htonl ( (a0 << 24) | ((a1 & 0xff) << 16)
+                        | ((a2 & 0xff) << 8) | (a3 & 0xff) );
+             data_addr_sa4->sin_port =
+                 htons (((p0 & 0xff) << 8) | (p1 & 0xff));
+           } /* PASV */
+         else
+           {
+             /* Catch all impossible cases.  */
+             printf ("Passive mode address scan failure. Shouldn't happen!\n");
+             goto bad;
+           }
+       } /* PASV */
 
-      memset (&data_addr, 0, sizeof (data_addr));
-      data_addr.sin_family = AF_INET;
-      a = (char *) &data_addr.sin_addr.s_addr;
-      a[0] = a0 & 0xff;
-      a[1] = a1 & 0xff;
-      a[2] = a2 & 0xff;
-      a[3] = a3 & 0xff;
-      p = (char *) &data_addr.sin_port;
-      p[0] = p0 & 0xff;
-      p[1] = p1 & 0xff;
-
-      if (connect (data, (struct sockaddr *) &data_addr,
-                  sizeof (data_addr)) < 0)
+      if (connect (data, (struct sockaddr *) &data_addr, ctladdrlen) < 0)
        {
          perror ("ftp: connect");
          goto bad;
        }
-#if defined IP_TOS && defined IPTOS_THROUGPUT
+#if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
       on = IPTOS_THROUGHPUT;
-      if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on,
+      if (data_addr.ss_family == AF_INET &&
+          setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on,
                      sizeof (int)) < 0)
        perror ("ftp: setsockopt TOS (ignored)");
 #endif
@@ -1176,10 +1276,17 @@ initconn (void)
 noport:
   data_addr = myctladdr;
   if (sendport)
-    data_addr.sin_port = 0;    /* let system pick one */
+    /* Let the system pick a port.  */
+    switch (myctladdr.ss_family)
+      {
+       case AF_INET:
+         data_addr_sa4->sin_port = 0;
+         break;
+      }
+
   if (data != -1)
     close (data);
-  data = socket (AF_INET, SOCK_STREAM, 0);
+  data = socket (myctladdr.ss_family, SOCK_STREAM, 0);
   if (data < 0)
     {
       error (0, errno, "socket");
@@ -1194,7 +1301,7 @@ noport:
        error (0, errno, "setsockopt (reuse address)");
        goto bad;
       }
-  if (bind (data, (struct sockaddr *) &data_addr, sizeof (data_addr)) < 0)
+  if (bind (data, (struct sockaddr *) &data_addr, ctladdrlen) < 0)
     {
       error (0, errno, "bind");
       goto bad;
@@ -1212,13 +1319,52 @@ noport:
     error (0, errno, "listen");
   if (sendport)
     {
-      a = (char *) &data_addr.sin_addr;
-      p = (char *) &data_addr.sin_port;
 #define UC(b)  (((int)b)&0xff)
-      result =
-       command ("PORT %d,%d,%d,%d,%d,%d",
-                UC (a[0]), UC (a[1]), UC (a[2]), UC (a[3]),
-                UC (p[0]), UC (p[1]));
+      /* Preferences:
+       *   IPv4: EPRT, PORT, LPRT
+       */
+      result = ERROR;  /* For success detection.  */
+      if (data_addr.ss_family != AF_INET || doepsv4)
+       {
+         /* Use EPRT mode.  */
+         getnameinfo ((struct sockaddr *) &data_addr, ctladdrlen,
+                       ia, sizeof (ia), portstr, sizeof (portstr),
+                       NI_NUMERICHOST | NI_NUMERICSERV);
+         result = command ("EPRT |%d|%s|%s|",
+                           (data_addr.ss_family == AF_INET) ? 1 : 2,
+                           ia, portstr);
+       }
+
+      if (data_addr.ss_family == AF_INET && doepsv4 && result != COMPLETE)
+       /* Do not try EPRT with IPv4 again.  It fails for this host.  */
+       doepsv4 = 0;
+
+      if (data_addr.ss_family == AF_INET && result != COMPLETE)
+       {
+         /* PORT for IPv4; possibly EPRT has failed.  */
+         a = (char *) &data_addr_sa4->sin_addr;
+         p = (char *) &data_addr_sa4->sin_port;
+         result = command ("PORT %d,%d,%d,%d,%d,%d",
+                           UC (a[0]), UC (a[1]), UC (a[2]), UC (a[3]),
+                           UC (p[0]), UC (p[1]));
+       }
+
+      if (result != COMPLETE)
+       {
+         /* Fall back to LPRT.  */
+         uint8_t *h, *p;
+
+         switch (data_addr.ss_family)
+           {
+             case AF_INET:
+               h = (uint8_t *) &data_addr_sa4->sin_addr;
+               p = (uint8_t *) &data_addr_sa4->sin_port;
+               result = command ("LPRT 4,4,%u,%u,%u,%u,2,%u,%u",
+                                 h[0], h[1], h[2], h[3], p[0], p[1]);
+               break;
+           }
+       }
+
       if (result == ERROR && sendport == -1)
        {
          sendport = 0;
@@ -1231,7 +1377,8 @@ noport:
     sendport = 1;
 #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
   on = IPTOS_THROUGHPUT;
-  if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0)
+  if (data_addr.ss_family == AF_INET &&
+       setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0)
     error (0, errno, "setsockopt TOS (ignored)");
 #endif
   return (0);
@@ -1245,7 +1392,7 @@ bad:
 FILE *
 dataconn (char *lmode)
 {
-  struct sockaddr_in from;
+  struct sockaddr_storage from;
   int s, tos;
   socklen_t fromlen = sizeof (from);
 
@@ -1263,7 +1410,8 @@ dataconn (char *lmode)
   data = s;
 #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
   tos = IPTOS_THROUGHPUT;
-  if (setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
+  if (from.ss_family == AF_INET &&
+       setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
     error (0, errno, "setsockopt TOS (ignored)");
 #endif
   return (fdopen (data, lmode));
@@ -1325,8 +1473,8 @@ pswitch (int flag)
   {
     int connect;
     char *name;
-    struct sockaddr_in mctl;
-    struct sockaddr_in hctl;
+    struct sockaddr_storage mctl;
+    struct sockaddr_storage hctl;
     FILE *in;
     FILE *out;
     int tpe;
diff --git a/ftp/ftp_var.h b/ftp/ftp_var.h
index 0ca73e5..52212ee 100644
--- a/ftp/ftp_var.h
+++ b/ftp/ftp_var.h
@@ -87,6 +87,7 @@ FTP_EXTERN int code;          /* return/reply code for ftp 
command */
 FTP_EXTERN int crflag;         /* if 1, strip car. rets. on ascii gets */
 FTP_EXTERN char pasv[64];      /* passive port for proxy data connection */
 FTP_EXTERN int passivemode;    /* passive mode enabled */
+FTP_EXTERN int doepsv4;                /* EPSV/EPRT for IPv4 enabled */
 FTP_EXTERN char *altarg;       /* argv[1] with no shell-like preprocessing  */
 FTP_EXTERN char ntin[17];      /* input translation table */
 FTP_EXTERN char ntout[17];     /* output translation table */
diff --git a/ftp/main.c b/ftp/main.c
index ae83c26..147f66f 100644
--- a/ftp/main.c
+++ b/ftp/main.c
@@ -178,6 +178,7 @@ main (int argc, char *argv[])
   interactive = 1;
   autologin = 1;
   passivemode = 0;             /* passive mode not active */
+  doepsv4 = 0;                 /* use EPRT/EPSV for IPv4 */
 
   /* Parse command line */
   iu_argp_init ("ftp", default_program_authors);

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog     |   22 ++++
 ftp/cmds.c    |   16 ++-
 ftp/cmdtab.c  |    2 +
 ftp/extern.h  |    1 +
 ftp/ftp.c     |  372 ++++++++++++++++++++++++++++++++++++++++-----------------
 ftp/ftp_var.h |    1 +
 ftp/main.c    |    1 +
 7 files changed, 301 insertions(+), 114 deletions(-)


hooks/post-receive
-- 
GNU Inetutils 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]