Ticket #121: mc-ipv6.patch
File mc-ipv6.patch, 11.9 KB (added by slavazanko, 16 years ago) |
---|
-
mc-2006-09-12-21/vfs/ftpfs.c
old new ftpfs_get_proxy_host_and_port (const cha 639 639 static int 640 640 ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super) 641 641 { 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; 645 644 char *host; 646 int port = SUP.port; 645 char *port; 646 int tmp_port; 647 647 int free_host = 0; 648 int e; 648 649 649 650 (void) me; 650 651 … … ftpfs_open_socket (struct vfs_class *me, 657 658 return -1; 658 659 } 659 660 661 port = malloc (sizeof (char) * 6); 662 if (port == NULL) { 663 ftpfs_errno = errno; 664 return -1; 665 } 666 660 667 /* Hosts to connect to that start with a ! should use proxy */ 668 tmp_port = SUP.port; 669 661 670 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); 663 672 free_host = 1; 664 673 } 665 674 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; 686 681 } 687 682 688 server_address.sin_port = htons (port);683 enable_interrupt_key(); /* clear the interrupt flag */ 689 684 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) 701 693 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 ()) { 707 722 print_vfs_message (_("ftpfs: connection interrupted by user")); 708 else723 } else if (res->ai_next == NULL) { 709 724 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 } 714 734 } 715 disable_interrupt_key(); 735 736 freeaddrinfo (restmp); 737 disable_interrupt_key (); 716 738 return my_socket; 717 739 } 718 740 … … ftpfs_get_current_directory (struct vfs_ 861 883 862 884 /* Setup Passive ftp connection, we use it for source routed connections */ 863 885 static int 864 ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super, int my_socket, struct sockaddr_ in *sa)886 ftpfs_setup_passive (struct vfs_class *me, struct vfs_s_super *super, int my_socket, struct sockaddr_storage *sa, socklen_t *salen) 865 887 { 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) { 866 918 int xa, xb, xc, xd, xe, xf; 867 919 char n [6]; 868 char *c;869 920 870 921 if (ftpfs_command (me, super, WAIT_REPLY | WANT_STRING, "PASV") != COMPLETE) 871 872 922 return 0; 923 873 924 /* Parse remote parameters */ 874 925 for (c = reply_str + 4; (*c) && (!isdigit ((unsigned char) *c)); c++) 875 926 ; 876 927 if (!*c) 877 928 return 0; 878 929 if (!isdigit ((unsigned char) *c)) 879 930 return 0; 880 931 if (sscanf (c, "%d,%d,%d,%d,%d,%d", &xa, &xb, &xc, &xd, &xe, &xf) != 6) 881 932 return 0; 882 933 n [0] = (unsigned char) xa; 883 934 n [1] = (unsigned char) xb; 884 935 n [2] = (unsigned char) xc; 885 936 n [3] = (unsigned char) xd; 886 937 n [4] = (unsigned char) xe; 887 938 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; 888 944 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; 894 949 } 895 950 896 951 static int 897 952 ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super) 898 953 { 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; 903 957 904 pe = getprotobyname ("tcp");905 if (pe == NULL)906 ERRNOR (EIO, -1);907 958 again: 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); 915 961 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 } 922 976 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; 926 983 } 984 print_vfs_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno)); 985 return -1; 986 } 927 987 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 928 999 /* If passive setup fails, fallback to active connections */ 929 1000 /* 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)) 933 1004 { 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; 936 1042 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 } 940 1047 } 941 close (data); 942 ftpfs_errno = EIO; 943 return -1; 1048 1049 close (data_sock); 1050 ftpfs_errno = EIO; 1051 return -1; 944 1052 } 945 1053 946 1054 static int 947 1055 ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, const char *cmd, 948 1056 const char *remote, int isbinary, int reget) 949 1057 { 950 struct sockaddr_ infrom;1058 struct sockaddr_storage from; 951 1059 int s, j, data; 952 1060 socklen_t fromlen = sizeof(from); 953 1061 -
mc-2006-09-12-21/vfs/ftpfs.h
old new extern int ftpfs_first_cd_then_ls; 15 15 void ftpfs_init_passwd (void); 16 16 void init_ftpfs (void); 17 17 18 #define FTP_INET 1 19 #define FTP_INET6 2 20 18 21 #define OPT_FLUSH 1 19 22 #define OPT_IGNORE_ERROR 2 20 23 -
mc-2006-08-12-18/vfs/utilvfs.c
old new vfs_split_url (const char *path, char ** 109 109 } 110 110 111 111 /* 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 113 127 if (colon) { 114 128 *colon = 0; 115 129 if (sscanf (colon + 1, "%d", port) == 1) {