Ticket #121: mc-ipv6.patch

File mc-ipv6.patch, 11.9 KB (added by slavazanko, 15 years ago)

original patch from Fedora-10

  • mc-2006-09-12-21/vfs/ftpfs.c

    old new ftpfs_get_proxy_host_and_port (const cha 
    639639static int 
    640640ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super) 
    641641{ 
    642     struct   sockaddr_in server_address; 
    643     struct   hostent *hp; 
    644     int      my_socket; 
     642    struct addrinfo hints, *res, *restmp; 
     643    int      my_socket = 0; 
    645644    char     *host; 
    646     int      port = SUP.port; 
     645    char     *port; 
     646    int      tmp_port; 
    647647    int      free_host = 0; 
     648    int      e; 
    648649 
    649650    (void) me; 
    650651     
    ftpfs_open_socket (struct vfs_class *me, 
    657658        return -1; 
    658659    } 
    659660 
     661    port = malloc (sizeof (char) * 6); 
     662    if (port == NULL) { 
     663      ftpfs_errno = errno; 
     664      return -1; 
     665    } 
     666 
    660667    /* Hosts to connect to that start with a ! should use proxy */ 
     668    tmp_port = SUP.port; 
     669 
    661670    if (SUP.proxy){ 
    662         ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &port); 
     671        ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port); 
    663672        free_host = 1; 
    664673    } 
    665674 
    666     enable_interrupt_key(); /* clear the interrupt flag */ 
    667      
    668     /* Get host address */ 
    669     memset ((char *) &server_address, 0, sizeof (server_address)); 
    670     server_address.sin_family = AF_INET; 
    671     server_address.sin_addr.s_addr = inet_addr (host); 
    672     if (server_address.sin_addr.s_addr == INADDR_NONE) { 
    673         hp = gethostbyname (host); 
    674         if (hp == NULL){ 
    675             disable_interrupt_key(); 
    676             print_vfs_message (_("ftpfs: Invalid host address.")); 
    677             ftpfs_errno = EINVAL; 
    678             if (free_host) 
    679                 g_free (host); 
    680             return -1; 
    681         } 
    682         server_address.sin_family = hp->h_addrtype; 
    683  
    684         /* We copy only 4 bytes, we cannot trust hp->h_length, as it comes from the DNS */ 
    685         memcpy ((char *) &server_address.sin_addr, (char *) hp->h_addr, 4); 
     675    if (snprintf (port, 6, "%hu", (unsigned short)tmp_port) < 0) { 
     676      g_free (port); 
     677      if (free_host) 
     678        g_free (host); 
     679      ftpfs_errno = errno; 
     680      return -1; 
    686681    } 
    687682 
    688     server_address.sin_port = htons (port); 
     683    enable_interrupt_key(); /* clear the interrupt flag */ 
    689684 
    690     /* Connect */ 
    691     if ((my_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) { 
    692         disable_interrupt_key(); 
    693         ftpfs_errno = errno; 
    694         if (free_host) 
    695             g_free (host); 
    696         return -1; 
    697     } 
    698      
    699     print_vfs_message (_("ftpfs: making connection to %s"), host); 
    700     if (free_host) 
     685    memset (&hints, 0, sizeof (struct addrinfo)); 
     686    hints.ai_socktype = SOCK_STREAM; 
     687    hints.ai_flags = AI_ADDRCONFIG; 
     688 
     689    if ((e = getaddrinfo (host, port, &hints, &res)) != 0) { 
     690      disable_interrupt_key(); 
     691      print_vfs_message (_("ftpfs: %s"), gai_strerror (e)); 
     692      if (free_host) 
    701693        g_free (host); 
    702  
    703     if (connect (my_socket, (struct sockaddr *) &server_address, 
    704              sizeof (server_address)) < 0){ 
    705         ftpfs_errno = errno; 
    706         if (errno == EINTR && got_interrupt ()) 
     694      g_free (port); 
     695      ftpfs_errno = EINVAL; 
     696      return -1; 
     697    } 
     698    g_free (port); 
     699 
     700    for (restmp = res; res != NULL; res = res->ai_next) { 
     701      my_socket = socket (res->ai_family, res->ai_socktype, res->ai_protocol); 
     702      if (my_socket < 0) { 
     703        if (res->ai_next == NULL) { 
     704          disable_interrupt_key(); 
     705          print_vfs_message (_("ftpfs: %s"), unix_error_string (errno)); 
     706          if (free_host) 
     707            g_free (host); 
     708          freeaddrinfo (restmp); 
     709          ftpfs_errno = errno; 
     710          return -1; 
     711        } else 
     712          continue; 
     713      } else { 
     714        print_vfs_message (_("ftpfs: making connection to %s"), host); 
     715        if (free_host) 
     716          g_free (host); 
     717         
     718        if (connect (my_socket, res->ai_addr, res->ai_addrlen) < 0) { 
     719          ftpfs_errno = errno; 
     720          close (my_socket); 
     721          if (errno == EINTR && got_interrupt ()) { 
    707722            print_vfs_message (_("ftpfs: connection interrupted by user")); 
    708         else 
     723          } else if (res->ai_next == NULL) { 
    709724            print_vfs_message (_("ftpfs: connection to server failed: %s"), 
    710                                    unix_error_string(errno)); 
    711         disable_interrupt_key(); 
    712         close (my_socket); 
    713         return -1; 
     725                               unix_error_string (errno)); 
     726          } else 
     727            continue; 
     728          freeaddrinfo (restmp); 
     729          disable_interrupt_key (); 
     730          return -1; 
     731        } else 
     732          break; 
     733      } 
    714734    } 
    715     disable_interrupt_key(); 
     735 
     736    freeaddrinfo (restmp); 
     737    disable_interrupt_key (); 
    716738    return my_socket; 
    717739} 
    718740 
    ftpfs_get_current_directory (struct vfs_ 
    861883     
    862884/* Setup Passive ftp connection, we use it for source routed connections */ 
    863885static int 
    864 ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super, int my_socket, struct sockaddr_in *sa) 
     886ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super, int my_socket, struct sockaddr_storage *sa, socklen_t *salen) 
    865887{ 
     888  char *c; 
     889   
     890  if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "EPSV") == COMPLETE) { 
     891    int port; 
     892    /* (|||<port>|) */ 
     893    c = strchr (reply_str, '|'); 
     894    if (c == NULL) 
     895      return 0; 
     896    if(strlen(c) > 3) 
     897      c+=3; 
     898    else 
     899      return 0; 
     900 
     901    port = atoi (c); 
     902    if (port < 0 || port > 65535) 
     903      return 0; 
     904    port = htons (port); 
     905 
     906    switch (sa->ss_family) { 
     907    case AF_INET: 
     908      ((struct sockaddr_in *)sa)->sin_port = port; 
     909      break; 
     910    case AF_INET6: 
     911      ((struct sockaddr_in6 *)sa)->sin6_port = port; 
     912      break; 
     913    default: 
     914      print_vfs_message (_("ftpfs: invalid address family")); 
     915      ERRNOR (EINVAL, -1); 
     916    } 
     917  } else if (sa->ss_family == AF_INET) { 
    866918    int xa, xb, xc, xd, xe, xf; 
    867919    char n [6]; 
    868     char *c; 
    869920     
    870921    if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "PASV") != COMPLETE) 
    871         return 0; 
    872  
     922      return 0; 
     923     
    873924    /* Parse remote parameters */ 
    874925    for (c = reply_str + 4; (*c) && (!isdigit ((unsigned char) *c)); c++) 
    875         ; 
     926      ; 
    876927    if (!*c) 
    877         return 0; 
     928      return 0; 
    878929    if (!isdigit ((unsigned char) *c)) 
    879         return 0; 
     930      return 0; 
    880931    if (sscanf (c, "%d,%d,%d,%d,%d,%d", &xa, &xb, &xc, &xd, &xe, &xf) != 6) 
    881         return 0; 
     932      return 0; 
    882933    n [0] = (unsigned char) xa; 
    883934    n [1] = (unsigned char) xb; 
    884935    n [2] = (unsigned char) xc; 
    885936    n [3] = (unsigned char) xd; 
    886937    n [4] = (unsigned char) xe; 
    887938    n [5] = (unsigned char) xf; 
     939     
     940    memcpy (&(((struct sockaddr_in *)sa)->sin_addr.s_addr), (void *)n, 4); 
     941    memcpy (&(((struct sockaddr_in *)sa)->sin_port), (void *)&n[4], 2); 
     942  } else 
     943    return 0; 
    888944 
    889     memcpy (&(sa->sin_addr.s_addr), (void *)n, 4); 
    890     memcpy (&(sa->sin_port), (void *)&n[4], 2); 
    891     if (connect (my_socket, (struct sockaddr *) sa, sizeof (struct sockaddr_in)) < 0) 
    892         return 0; 
    893     return 1; 
     945  if (connect (my_socket, (struct sockaddr *) sa, *salen ) < 0) 
     946    return 0; 
     947 
     948  return 1; 
    894949} 
    895950 
    896951static int 
    897952ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super) 
    898953{ 
    899     struct sockaddr_in data_addr; 
    900     int data; 
    901     socklen_t len = sizeof(data_addr); 
    902     struct protoent *pe; 
     954  struct sockaddr_storage data_addr; 
     955  socklen_t data_addrlen; 
     956  int data_sock; 
    903957 
    904     pe = getprotobyname ("tcp"); 
    905     if (pe == NULL) 
    906         ERRNOR (EIO, -1); 
    907958again: 
    908     if (getsockname (SUP.sock, (struct sockaddr *) &data_addr, &len) == -1) 
    909         ERRNOR (EIO, -1); 
    910     data_addr.sin_port = 0; 
    911      
    912     data = socket (AF_INET, SOCK_STREAM, pe->p_proto); 
    913     if (data < 0) 
    914         ERRNOR (EIO, -1); 
     959  memset (&data_addr, 0, sizeof (struct sockaddr_storage)); 
     960  data_addrlen = sizeof (struct sockaddr_storage); 
    915961 
    916     if (SUP.use_passive_connection) { 
    917         if (ftpfs_setup_passive (me, super, data, &data_addr)) 
    918             return data; 
    919  
    920         SUP.use_passive_connection = 0; 
    921         print_vfs_message (_("ftpfs: could not setup passive mode")); 
     962  if (getpeername (SUP.sock, (struct sockaddr *) &data_addr, &data_addrlen) == -1) 
     963    return -1; 
     964   
     965  switch (data_addr.ss_family) { 
     966  case AF_INET: 
     967    ((struct sockaddr_in *)&data_addr)->sin_port = 0; 
     968    break; 
     969  case AF_INET6: 
     970    ((struct sockaddr_in6 *)&data_addr)->sin6_port = 0; 
     971    break; 
     972  default: 
     973    print_vfs_message (_("ftpfs: invalid address family")); 
     974    ERRNOR(EINVAL, -1); 
     975  } 
    922976 
    923         /* data or data_addr may be damaged by ftpfs_setup_passive */ 
    924         close (data); 
    925         goto again; 
     977  data_sock = socket (data_addr.ss_family, SOCK_STREAM, IPPROTO_TCP); 
     978  if (data_sock < 0) { 
     979    if (SUP.use_passive_connection) { 
     980      print_vfs_message (_("ftpfs: could not setup passive mode: %s"), unix_error_string (errno)); 
     981      SUP.use_passive_connection = 0; 
     982      goto again; 
    926983    } 
     984    print_vfs_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno)); 
     985    return -1; 
     986  } 
    927987 
     988  if (SUP.use_passive_connection) { 
     989    if (ftpfs_setup_passive (me, super, data_sock, &data_addr, &data_addrlen)) 
     990      return data_sock; 
     991 
     992    SUP.use_passive_connection = 0; 
     993    print_vfs_message (_("ftpfs: could not setup passive mode")); 
     994 
     995    close (data_sock); 
     996    goto again; 
     997  } 
     998   
    928999    /* If passive setup fails, fallback to active connections */ 
    9291000    /* Active FTP connection */ 
    930     if ((bind (data, (struct sockaddr *)&data_addr, len) == 0) && 
    931         (getsockname (data, (struct sockaddr *) &data_addr, &len) == 0) &&  
    932         (listen (data, 1) == 0)) 
     1001  if ((bind (data_sock, (struct sockaddr *)&data_addr, data_addrlen) == 0) && 
     1002      (getsockname (data_sock, (struct sockaddr *)&data_addr, &data_addrlen) == 0) &&  
     1003      (listen (data_sock, 1) == 0)) 
    9331004    { 
    934         unsigned char *a = (unsigned char *)&data_addr.sin_addr; 
    935         unsigned char *p = (unsigned char *)&data_addr.sin_port; 
     1005      unsigned short int port; 
     1006      char *addr; 
     1007      unsigned int af; 
     1008 
     1009      switch (data_addr.ss_family) { 
     1010      case AF_INET:  
     1011        af = FTP_INET; 
     1012        port = ((struct sockaddr_in *)&data_addr)->sin_port; 
     1013        break; 
     1014      case AF_INET6:  
     1015        af = FTP_INET6; 
     1016        port = ((struct sockaddr_in6 *)&data_addr)->sin6_port; 
     1017        break; 
     1018      default: 
     1019        print_vfs_message (_("ftpfs: invalid address family")); 
     1020        ERRNOR (EINVAL, -1); 
     1021      } 
     1022      port = ntohs (port); 
     1023      
     1024      addr = malloc (NI_MAXHOST); 
     1025      if (addr == NULL) 
     1026        ERRNOR (ENOMEM, -1); 
     1027 
     1028      if (getnameinfo ((struct sockaddr *)&data_addr, data_addrlen, addr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) { 
     1029        g_free (addr); 
     1030        ERRNOR (EIO, -1); 
     1031      } 
     1032 
     1033      if (ftpfs_command (me, super, WAIT_REPLY, "EPRT |%u|%s|%hu|", af, addr, port) == COMPLETE) { 
     1034        g_free (addr); 
     1035        return data_sock; 
     1036      } 
     1037      g_free (addr); 
     1038       
     1039      if (FTP_INET == af) { 
     1040        unsigned char *a = (unsigned char *)&((struct sockaddr_in *)&data_addr)->sin_addr; 
     1041        unsigned char *p = (unsigned char *)&port; 
    9361042         
    937         if (ftpfs_command (me, super, WAIT_REPLY, "PORT %d,%d,%d,%d,%d,%d", a[0], a[1],  
    938                      a[2], a[3], p[0], p[1]) == COMPLETE) 
    939             return data; 
     1043        if (ftpfs_command (me, super, WAIT_REPLY, "PORT %u,%u,%u,%u,%u,%u", a[0], a[1], a[2], a[3], 
     1044                           p[0], p[1]) == COMPLETE) 
     1045          return data_sock; 
     1046      } 
    9401047    } 
    941     close (data); 
    942     ftpfs_errno = EIO; 
    943     return -1; 
     1048 
     1049  close (data_sock); 
     1050  ftpfs_errno = EIO; 
     1051  return -1; 
    9441052} 
    9451053 
    9461054static int 
    9471055ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, const char *cmd, 
    9481056                      const char *remote, int isbinary, int reget) 
    9491057{ 
    950     struct sockaddr_in from; 
     1058    struct sockaddr_storage from; 
    9511059    int s, j, data; 
    9521060    socklen_t fromlen = sizeof(from); 
    9531061     
  • mc-2006-09-12-21/vfs/ftpfs.h

    old new extern int ftpfs_first_cd_then_ls; 
    1515void ftpfs_init_passwd (void); 
    1616void init_ftpfs (void); 
    1717 
     18#define FTP_INET  1 
     19#define FTP_INET6 2 
     20 
    1821#define OPT_FLUSH        1 
    1922#define OPT_IGNORE_ERROR 2 
    2023 
  • mc-2006-08-12-18/vfs/utilvfs.c

    old new vfs_split_url (const char *path, char ** 
    109109    } 
    110110 
    111111    /* Check if the host comes with a port spec, if so, chop it */ 
    112     colon = strchr (rest, ':'); 
     112    if ('[' == *rest) { 
     113      colon = strchr (++rest, ']'); 
     114      if (colon) { 
     115        colon[0] = '\0'; 
     116        colon[1] = '\0'; 
     117        colon++; 
     118      } else { 
     119        g_free (pcopy); 
     120        *host = NULL; 
     121        *port = 0; 
     122        return NULL; 
     123      } 
     124    } else 
     125      colon = strchr (rest, ':'); 
     126 
    113127    if (colon) { 
    114128        *colon = 0; 
    115129        if (sscanf (colon + 1, "%d", port) == 1) {