#include <string.h>\r
#include <mbstring.h>\r
#include <time.h>\r
-#include <winsock.h>\r
+// IPv6対応\r
+//#include <winsock.h>\r
+#include <ws2tcpip.h>\r
#include <windowsx.h>\r
#include <commctrl.h>\r
\r
static int CheckOneTimePassword(char *Pass, char *Reply, int Type);\r
static BOOL CALLBACK BlkHookFnc(void);\r
static int Socks5MakeCmdPacket(SOCKS5REQUEST *Packet, char Cmd, int ValidIP, ulong IP, char *Host, ushort Port);\r
+// IPv6対応\r
+static int Socks5MakeCmdPacketIPv6(SOCKS5REQUEST *Packet, char Cmd, int ValidIP, char *IP, char *Host, ushort Port);\r
static int SocksSendCmd(SOCKET Socket, void *Data, int Size, int *CancelCheckWork);\r
// 同時接続対応\r
//static int Socks5GetCmdReply(SOCKET Socket, SOCKS5REPLY *Packet);\r
\r
/* 接続中の接続先、SOCKSサーバのアドレス情報を保存しておく */\r
/* この情報はlistenソケットを取得する際に用いる */\r
-static struct sockaddr_in SocksSockAddr; /* SOCKSサーバのアドレス情報 */\r
-static struct sockaddr_in CurSockAddr; /* 接続先ホストのアドレス情報 */\r
+// IPv6対応\r
+//static struct sockaddr_in SocksSockAddr; /* SOCKSサーバのアドレス情報 */\r
+//static struct sockaddr_in CurSockAddr; /* 接続先ホストのアドレス情報 */\r
+static struct sockaddr_in SocksSockAddrIPv4; /* SOCKSサーバのアドレス情報 */\r
+static struct sockaddr_in CurSockAddrIPv4; /* 接続先ホストのアドレス情報 */\r
+static struct sockaddr_in6 SocksSockAddrIPv6; /* SOCKSサーバのアドレス情報 */\r
+static struct sockaddr_in6 CurSockAddrIPv6; /* 接続先ホストのアドレス情報 */\r
+static const struct in6_addr IN6ADDR_NONE = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};\r
\r
static int UseIPadrs;\r
static char DomainName[HOST_ADRS_LEN+1];\r
* SOCKET ソケット\r
*----------------------------------------------------------------------------*/\r
\r
+// IPv6対応\r
SOCKET connectsock(char *host, int port, char *PreMsg, int *CancelCheckWork)\r
{\r
+ SOCKET Result;\r
+ Result = INVALID_SOCKET;\r
+ switch(CurHost.InetFamily)\r
+ {\r
+ case AF_UNSPEC:\r
+ if((Result = connectsockIPv4(host, port, PreMsg, CancelCheckWork)) != INVALID_SOCKET)\r
+ CurHost.InetFamily = AF_INET;\r
+ else if(CurHost.UseIPv6 == YES && (Result = connectsockIPv6(host, port, PreMsg, CancelCheckWork)) != INVALID_SOCKET)\r
+ CurHost.InetFamily = AF_INET6;\r
+ break;\r
+ case AF_INET:\r
+ Result = connectsockIPv4(host, port, PreMsg, CancelCheckWork);\r
+ break;\r
+ case AF_INET6:\r
+ Result = connectsockIPv6(host, port, PreMsg, CancelCheckWork);\r
+ break;\r
+ }\r
+ return Result;\r
+}\r
+\r
+\r
+// IPv6対応\r
+//SOCKET connectsock(char *host, int port, char *PreMsg, int *CancelCheckWork)\r
+SOCKET connectsockIPv4(char *host, int port, char *PreMsg, int *CancelCheckWork)\r
+{\r
struct sockaddr_in saSockAddr;\r
char HostEntry[MAXGETHOSTSTRUCT];\r
struct hostent *pHostEntry;\r
\r
UseIPadrs = YES;\r
strcpy(DomainName, host);\r
- memset(&CurSockAddr, 0, sizeof(CurSockAddr));\r
- CurSockAddr.sin_port = htons((u_short)port);\r
- CurSockAddr.sin_family = AF_INET;\r
- if((CurSockAddr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)\r
+ // IPv6対応\r
+// memset(&CurSockAddr, 0, sizeof(CurSockAddr));\r
+// CurSockAddr.sin_port = htons((u_short)port);\r
+// CurSockAddr.sin_family = AF_INET;\r
+// if((CurSockAddr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)\r
+ memset(&CurSockAddrIPv4, 0, sizeof(CurSockAddrIPv4));\r
+ CurSockAddrIPv4.sin_port = htons((u_short)port);\r
+ CurSockAddrIPv4.sin_family = AF_INET;\r
+ if((CurSockAddrIPv4.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)\r
{\r
// ホスト名が指定された\r
// ホスト名からアドレスを求める\r
{\r
// アドレスを取得\r
SetTaskMsg(MSGJPN016, DomainName);\r
- pHostEntry = do_gethostbyname(host, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork);\r
+ // IPv6対応\r
+// pHostEntry = do_gethostbyname(host, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork);\r
+ pHostEntry = do_gethostbynameIPv4(host, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork);\r
}\r
\r
if(pHostEntry != NULL)\r
{\r
- memcpy((char *)&CurSockAddr.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
- SetTaskMsg(MSGJPN017, PreMsg, DomainName, inet_ntoa(CurSockAddr.sin_addr), ntohs(CurSockAddr.sin_port));\r
+ // IPv6対応\r
+// memcpy((char *)&CurSockAddr.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+// SetTaskMsg(MSGJPN017, PreMsg, DomainName, inet_ntoa(CurSockAddr.sin_addr), ntohs(CurSockAddr.sin_port));\r
+ memcpy((char *)&CurSockAddrIPv4.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+ SetTaskMsg(MSGJPN017, PreMsg, DomainName, inet_ntoa(CurSockAddrIPv4.sin_addr), ntohs(CurSockAddrIPv4.sin_port));\r
}\r
else\r
{\r
if((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
{\r
UseIPadrs = NO;\r
- SetTaskMsg(MSGJPN018, PreMsg, DomainName, ntohs(CurSockAddr.sin_port));\r
+ // IPv6対応\r
+// SetTaskMsg(MSGJPN018, PreMsg, DomainName, ntohs(CurSockAddr.sin_port));\r
+ SetTaskMsg(MSGJPN018, PreMsg, DomainName, ntohs(CurSockAddrIPv4.sin_port));\r
}\r
else\r
{\r
}\r
}\r
else\r
- SetTaskMsg(MSGJPN020, PreMsg, inet_ntoa(CurSockAddr.sin_addr), ntohs(CurSockAddr.sin_port));\r
+ // IPv6対応\r
+// SetTaskMsg(MSGJPN020, PreMsg, inet_ntoa(CurSockAddr.sin_addr), ntohs(CurSockAddr.sin_port));\r
+ SetTaskMsg(MSGJPN020, PreMsg, inet_ntoa(CurSockAddrIPv4.sin_addr), ntohs(CurSockAddrIPv4.sin_port));\r
\r
if((Fwall == FWALL_SOCKS4) || (Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
{\r
{\r
Socks4Cmd.Ver = SOCKS4_VER;\r
Socks4Cmd.Cmd = SOCKS4_CMD_CONNECT;\r
- Socks4Cmd.Port = CurSockAddr.sin_port;\r
- Socks4Cmd.AdrsInt = CurSockAddr.sin_addr.s_addr;\r
+ // IPv6対応\r
+// Socks4Cmd.Port = CurSockAddr.sin_port;\r
+// Socks4Cmd.AdrsInt = CurSockAddr.sin_addr.s_addr;\r
+ Socks4Cmd.Port = CurSockAddrIPv4.sin_port;\r
+ Socks4Cmd.AdrsInt = CurSockAddrIPv4.sin_addr.s_addr;\r
strcpy(Socks4Cmd.UserID, FwallUser);\r
Len = offsetof(SOCKS4CMD, UserID) + strlen(FwallUser) + 1;\r
}\r
else\r
{\r
- Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_CONNECT, UseIPadrs, CurSockAddr.sin_addr.s_addr, DomainName, CurSockAddr.sin_port);\r
+ // IPv6対応\r
+// Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_CONNECT, UseIPadrs, CurSockAddr.sin_addr.s_addr, DomainName, CurSockAddr.sin_port);\r
+ Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_CONNECT, UseIPadrs, CurSockAddrIPv4.sin_addr.s_addr, DomainName, CurSockAddrIPv4.sin_port);\r
}\r
\r
- memset(&SocksSockAddr, 0, sizeof(SocksSockAddr));\r
- if((SocksSockAddr.sin_addr.s_addr = inet_addr(FwallHost)) == INADDR_NONE)\r
+ // IPv6対応\r
+// memset(&SocksSockAddr, 0, sizeof(SocksSockAddr));\r
+// if((SocksSockAddr.sin_addr.s_addr = inet_addr(FwallHost)) == INADDR_NONE)\r
+ memset(&SocksSockAddrIPv4, 0, sizeof(SocksSockAddrIPv4));\r
+ if((SocksSockAddrIPv4.sin_addr.s_addr = inet_addr(FwallHost)) == INADDR_NONE)\r
{\r
- if((pHostEntry = do_gethostbyname(FwallHost, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork)) != NULL)\r
- memcpy((char *)&SocksSockAddr.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+ // IPv6対応\r
+// if((pHostEntry = do_gethostbyname(FwallHost, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork)) != NULL)\r
+// memcpy((char *)&SocksSockAddr.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+ if((pHostEntry = do_gethostbynameIPv4(FwallHost, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork)) != NULL)\r
+ memcpy((char *)&SocksSockAddrIPv4.sin_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
else\r
{\r
SetTaskMsg(MSGJPN021, FwallHost);\r
return INVALID_SOCKET;\r
}\r
}\r
- SocksSockAddr.sin_port = htons((u_short)FwallPort);\r
- SocksSockAddr.sin_family = AF_INET;\r
- SetTaskMsg(MSGJPN022, inet_ntoa(SocksSockAddr.sin_addr), ntohs(SocksSockAddr.sin_port));\r
+ // IPv6対応\r
+// SocksSockAddr.sin_port = htons((u_short)FwallPort);\r
+// SocksSockAddr.sin_family = AF_INET;\r
+// SetTaskMsg(MSGJPN022, inet_ntoa(SocksSockAddr.sin_addr), ntohs(SocksSockAddr.sin_port));\r
+ SocksSockAddrIPv4.sin_port = htons((u_short)FwallPort);\r
+ SocksSockAddrIPv4.sin_family = AF_INET;\r
+ SetTaskMsg(MSGJPN022, inet_ntoa(SocksSockAddrIPv4.sin_addr), ntohs(SocksSockAddrIPv4.sin_port));\r
// connectで接続する先はSOCKSサーバ\r
- memcpy(&saSockAddr, &SocksSockAddr, sizeof(SocksSockAddr));\r
+ // IPv6対応\r
+// memcpy(&saSockAddr, &SocksSockAddr, sizeof(SocksSockAddr));\r
+ memcpy(&saSockAddr, &SocksSockAddrIPv4, sizeof(SocksSockAddrIPv4));\r
}\r
else\r
{\r
// connectで接続するのは接続先のホスト\r
- memcpy(&saSockAddr, &CurSockAddr, sizeof(CurSockAddr));\r
+ // IPv6対応\r
+// memcpy(&saSockAddr, &CurSockAddr, sizeof(CurSockAddr));\r
+ memcpy(&saSockAddr, &CurSockAddrIPv4, sizeof(CurSockAddrIPv4));\r
}\r
\r
/////////////\r
}\r
\r
\r
+SOCKET connectsockIPv6(char *host, int port, char *PreMsg, int *CancelCheckWork)\r
+{\r
+ struct sockaddr_in6 saSockAddr;\r
+ char HostEntry[MAXGETHOSTSTRUCT];\r
+ struct hostent *pHostEntry;\r
+ SOCKET sSocket;\r
+ int Len;\r
+ int Fwall;\r
+ SOCKS5REQUEST Socks5Cmd;\r
+ SOCKS5REPLY Socks5Reply;\r
+\r
+ //////////////////////////////\r
+ // ホスト名解決と接続の準備\r
+ //////////////////////////////\r
+\r
+ Fwall = FWALL_NONE;\r
+ if(AskHostFireWall() == YES)\r
+ Fwall = FwallType;\r
+\r
+ sSocket = INVALID_SOCKET;\r
+\r
+ UseIPadrs = YES;\r
+ strcpy(DomainName, host);\r
+ memset(&CurSockAddrIPv6, 0, sizeof(CurSockAddrIPv6));\r
+ CurSockAddrIPv6.sin6_port = htons((u_short)port);\r
+ CurSockAddrIPv6.sin6_family = AF_INET6;\r
+ CurSockAddrIPv6.sin6_addr = inet6_addr(host);\r
+ if(memcmp(&CurSockAddrIPv6.sin6_addr, &IN6ADDR_NONE, sizeof(struct in6_addr)) == 0)\r
+ {\r
+ // ホスト名が指定された\r
+ // ホスト名からアドレスを求める\r
+ if(((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER)) &&\r
+ (FwallResolv == YES))\r
+ {\r
+ // ホスト名解決はSOCKSサーバに任せる\r
+ pHostEntry = NULL;\r
+ }\r
+ else\r
+ {\r
+ // アドレスを取得\r
+ SetTaskMsg(MSGJPN016, DomainName);\r
+ pHostEntry = do_gethostbynameIPv6(host, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork);\r
+ }\r
+\r
+ if(pHostEntry != NULL)\r
+ {\r
+ memcpy((char *)&CurSockAddrIPv6.sin6_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+ SetTaskMsg(MSGJPN017, PreMsg, DomainName, inet6_ntoa(CurSockAddrIPv6.sin6_addr), ntohs(CurSockAddrIPv6.sin6_port));\r
+ }\r
+ else\r
+ {\r
+ if((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
+ {\r
+ UseIPadrs = NO;\r
+ SetTaskMsg(MSGJPN018, PreMsg, DomainName, ntohs(CurSockAddrIPv6.sin6_port));\r
+ }\r
+ else\r
+ {\r
+ SetTaskMsg(MSGJPN019, host);\r
+ return(INVALID_SOCKET);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ SetTaskMsg(MSGJPN020, PreMsg, inet6_ntoa(CurSockAddrIPv6.sin6_addr), ntohs(CurSockAddrIPv6.sin6_port));\r
+\r
+ if((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
+ {\r
+ // SOCKSを使う\r
+ // SOCKSに接続する準備\r
+ {\r
+ Len = Socks5MakeCmdPacketIPv6(&Socks5Cmd, SOCKS5_CMD_CONNECT, UseIPadrs, (char*)&CurSockAddrIPv6.sin6_addr, DomainName, CurSockAddrIPv6.sin6_port);\r
+ }\r
+\r
+ memset(&SocksSockAddrIPv6, 0, sizeof(SocksSockAddrIPv6));\r
+ SocksSockAddrIPv6.sin6_addr = inet6_addr(FwallHost);\r
+ if(memcmp(&SocksSockAddrIPv6.sin6_addr, &IN6ADDR_NONE, sizeof(struct in6_addr)) == 0)\r
+ {\r
+ if((pHostEntry = do_gethostbynameIPv6(FwallHost, HostEntry, MAXGETHOSTSTRUCT, CancelCheckWork)) != NULL)\r
+ memcpy((char *)&SocksSockAddrIPv6.sin6_addr, pHostEntry->h_addr, pHostEntry->h_length);\r
+ else\r
+ {\r
+ SetTaskMsg(MSGJPN021, FwallHost);\r
+ return INVALID_SOCKET;\r
+ }\r
+ }\r
+ SocksSockAddrIPv6.sin6_port = htons((u_short)FwallPort);\r
+ SocksSockAddrIPv6.sin6_family = AF_INET6;\r
+ SetTaskMsg(MSGJPN022, inet6_ntoa(SocksSockAddrIPv6.sin6_addr), ntohs(SocksSockAddrIPv6.sin6_port));\r
+ // connectで接続する先はSOCKSサーバ\r
+ memcpy(&saSockAddr, &SocksSockAddrIPv6, sizeof(SocksSockAddrIPv6));\r
+ }\r
+ else\r
+ {\r
+ // connectで接続するのは接続先のホスト\r
+ memcpy(&saSockAddr, &CurSockAddrIPv6, sizeof(CurSockAddrIPv6));\r
+ }\r
+\r
+ /////////////\r
+ // 接続実行\r
+ /////////////\r
+\r
+ inet6_ntoa(saSockAddr.sin6_addr);\r
+ if((sSocket = do_socket(AF_INET6, SOCK_STREAM, TCP_PORT)) != INVALID_SOCKET)\r
+ {\r
+ if(do_connect(sSocket, (struct sockaddr *)&saSockAddr, sizeof(saSockAddr), CancelCheckWork) != SOCKET_ERROR)\r
+ {\r
+ if((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
+ {\r
+ if(Socks5SelMethod(sSocket, CancelCheckWork) == FFFTP_FAIL)\r
+ {\r
+ DoClose(sSocket);\r
+ sSocket = INVALID_SOCKET;\r
+ }\r
+\r
+ Socks5Reply.Result = -1;\r
+ // 同時接続対応\r
+// if((SocksSendCmd(sSocket, &Socks5Cmd, Len, CancelCheckWork) != FFFTP_SUCCESS) ||\r
+// (Socks5GetCmdReply(sSocket, &Socks5Reply) != FFFTP_SUCCESS) || \r
+// (Socks5Reply.Result != SOCKS5_RES_OK))\r
+ if((SocksSendCmd(sSocket, &Socks5Cmd, Len, CancelCheckWork) != FFFTP_SUCCESS) ||\r
+ (Socks5GetCmdReply(sSocket, &Socks5Reply, CancelCheckWork) != FFFTP_SUCCESS) || \r
+ (Socks5Reply.Result != SOCKS5_RES_OK))\r
+ {\r
+ SetTaskMsg(MSGJPN024, Socks5Reply.Result);\r
+ DoClose(sSocket);\r
+ sSocket = INVALID_SOCKET;\r
+ }\r
+\r
+ }\r
+\r
+ if(sSocket != INVALID_SOCKET)\r
+ SetTaskMsg(MSGJPN025);\r
+ }\r
+ else\r
+ {\r
+//#pragma aaa\r
+ SetTaskMsg(MSGJPN026/*"接続できません(2) %x", sSocket*/);\r
+ DoClose(sSocket);\r
+ sSocket = INVALID_SOCKET;\r
+ }\r
+ }\r
+ else\r
+ SetTaskMsg(MSGJPN027);\r
+\r
+ return(sSocket);\r
+}\r
+\r
+\r
/*----- リッスンソケットを取得 ------------------------------------------------\r
*\r
* Parameter\r
* SOCKET リッスンソケット\r
*----------------------------------------------------------------------------*/\r
\r
+// IPv6対応\r
SOCKET GetFTPListenSocket(SOCKET ctrl_skt, int *CancelCheckWork)\r
{\r
+ SOCKET Result;\r
+ Result = INVALID_SOCKET;\r
+ switch(CurHost.InetFamily)\r
+ {\r
+ case AF_UNSPEC:\r
+ break;\r
+ case AF_INET:\r
+ Result = GetFTPListenSocketIPv4(ctrl_skt, CancelCheckWork);\r
+ break;\r
+ case AF_INET6:\r
+ Result = GetFTPListenSocketIPv6(ctrl_skt, CancelCheckWork);\r
+ break;\r
+ }\r
+ return Result;\r
+}\r
+\r
+\r
+// IPv6対応\r
+//SOCKET GetFTPListenSocket(SOCKET ctrl_skt, int *CancelCheckWork)\r
+SOCKET GetFTPListenSocketIPv4(SOCKET ctrl_skt, int *CancelCheckWork)\r
+{\r
SOCKET listen_skt;\r
int iLength;\r
char *a,*p;\r
{\r
/*===== SOCKS4を使う =====*/\r
DoPrintf("Use SOCKS4 BIND");\r
- if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddr, sizeof(SocksSockAddr), CancelCheckWork) != SOCKET_ERROR)\r
+ // IPv6対応\r
+// if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddr, sizeof(SocksSockAddr), CancelCheckWork) != SOCKET_ERROR)\r
+ if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddrIPv4, sizeof(SocksSockAddrIPv4), CancelCheckWork) != SOCKET_ERROR)\r
{\r
Socks4Cmd.Ver = SOCKS4_VER;\r
Socks4Cmd.Cmd = SOCKS4_CMD_BIND;\r
- Socks4Cmd.Port = CurSockAddr.sin_port;\r
- Socks4Cmd.AdrsInt = CurSockAddr.sin_addr.s_addr;\r
+ // IPv6対応\r
+// Socks4Cmd.Port = CurSockAddr.sin_port;\r
+// Socks4Cmd.AdrsInt = CurSockAddr.sin_addr.s_addr;\r
+ Socks4Cmd.Port = CurSockAddrIPv4.sin_port;\r
+ Socks4Cmd.AdrsInt = CurSockAddrIPv4.sin_addr.s_addr;\r
strcpy(Socks4Cmd.UserID, FwallUser);\r
Len = offsetof(SOCKS4CMD, UserID) + strlen(FwallUser) + 1;\r
\r
}\r
\r
if(Socks4Reply.AdrsInt == 0)\r
- Socks4Reply.AdrsInt = SocksSockAddr.sin_addr.s_addr;\r
+ // IPv6対応\r
+// Socks4Reply.AdrsInt = SocksSockAddr.sin_addr.s_addr;\r
+ Socks4Reply.AdrsInt = SocksSockAddrIPv4.sin_addr.s_addr;\r
\r
a = (char *)&Socks4Reply.AdrsInt;\r
p = (char *)&Socks4Reply.Port;\r
{\r
/*===== SOCKS5を使う =====*/\r
DoPrintf("Use SOCKS5 BIND");\r
- if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddr, sizeof(SocksSockAddr), CancelCheckWork) != SOCKET_ERROR)\r
+ // IPv6対応\r
+// if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddr, sizeof(SocksSockAddr), CancelCheckWork) != SOCKET_ERROR)\r
+ if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddrIPv4, sizeof(SocksSockAddrIPv4), CancelCheckWork) != SOCKET_ERROR)\r
{\r
if(Socks5SelMethod(listen_skt, CancelCheckWork) == FFFTP_FAIL)\r
{\r
return(listen_skt);\r
}\r
\r
- Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_BIND, UseIPadrs, CurSockAddr.sin_addr.s_addr, DomainName, CurSockAddr.sin_port);\r
+ // IPv6対応\r
+// Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_BIND, UseIPadrs, CurSockAddr.sin_addr.s_addr, DomainName, CurSockAddr.sin_port);\r
+ Len = Socks5MakeCmdPacket(&Socks5Cmd, SOCKS5_CMD_BIND, UseIPadrs, CurSockAddrIPv4.sin_addr.s_addr, DomainName, CurSockAddrIPv4.sin_port);\r
\r
Socks5Reply.Result = -1;\r
// 同時接続対応\r
listen_skt = INVALID_SOCKET;\r
}\r
\r
- if(Socks5Reply.AdrsInt == 0)\r
- Socks5Reply.AdrsInt = SocksSockAddr.sin_addr.s_addr;\r
+ // IPv6対応\r
+// if(Socks5Reply.AdrsInt == 0)\r
+// Socks5Reply.AdrsInt = SocksSockAddr.sin_addr.s_addr;\r
\r
- a = (char *)&Socks5Reply.AdrsInt;\r
- p = (char *)&Socks5Reply.Port;\r
+ // IPv6対応\r
+// a = (char *)&Socks5Reply.AdrsInt;\r
+// p = (char *)&Socks5Reply.Port;\r
+ a = (char *)&Socks5Reply._dummy[0];\r
+ p = (char *)&Socks5Reply._dummy[4];\r
}\r
}\r
else\r
}\r
\r
\r
+SOCKET GetFTPListenSocketIPv6(SOCKET ctrl_skt, int *CancelCheckWork)\r
+{\r
+ SOCKET listen_skt;\r
+ int iLength;\r
+ char *a,*p;\r
+ struct sockaddr_in6 saCtrlAddr;\r
+ struct sockaddr_in6 saTmpAddr;\r
+ SOCKS5REQUEST Socks5Cmd;\r
+ SOCKS5REPLY Socks5Reply;\r
+\r
+ int Len;\r
+ int Fwall;\r
+\r
+ char Adrs[40];\r
+\r
+ Fwall = FWALL_NONE;\r
+ if(AskHostFireWall() == YES)\r
+ Fwall = FwallType;\r
+\r
+ if((listen_skt = do_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET)\r
+ {\r
+ if((Fwall == FWALL_SOCKS5_NOAUTH) || (Fwall == FWALL_SOCKS5_USER))\r
+ {\r
+ /*===== SOCKS5を使う =====*/\r
+ DoPrintf("Use SOCKS5 BIND");\r
+ if(do_connect(listen_skt, (struct sockaddr *)&SocksSockAddrIPv6, sizeof(SocksSockAddrIPv6), CancelCheckWork) != SOCKET_ERROR)\r
+ {\r
+ if(Socks5SelMethod(listen_skt, CancelCheckWork) == FFFTP_FAIL)\r
+ {\r
+ DoClose(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ return(listen_skt);\r
+ }\r
+\r
+ Len = Socks5MakeCmdPacketIPv6(&Socks5Cmd, SOCKS5_CMD_BIND, UseIPadrs, (char*)&CurSockAddrIPv6.sin6_addr, DomainName, CurSockAddrIPv6.sin6_port);\r
+\r
+ Socks5Reply.Result = -1;\r
+ // 同時接続対応\r
+// if((SocksSendCmd(listen_skt, &Socks5Cmd, Len, CancelCheckWork) != FFFTP_SUCCESS) ||\r
+// (Socks5GetCmdReply(listen_skt, &Socks5Reply) != FFFTP_SUCCESS) || \r
+// (Socks5Reply.Result != SOCKS5_RES_OK))\r
+ if((SocksSendCmd(listen_skt, &Socks5Cmd, Len, CancelCheckWork) != FFFTP_SUCCESS) ||\r
+ (Socks5GetCmdReply(listen_skt, &Socks5Reply, CancelCheckWork) != FFFTP_SUCCESS) || \r
+ (Socks5Reply.Result != SOCKS5_RES_OK))\r
+ {\r
+ SetTaskMsg(MSGJPN029, Socks5Reply.Result);\r
+ DoClose(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ }\r
+\r
+ // IPv6対応\r
+// if(Socks5Reply.AdrsInt == 0)\r
+// Socks5Reply.AdrsInt = SocksSockAddr.sin_addr.s_addr;\r
+\r
+ // IPv6対応\r
+// a = (char *)&Socks5Reply.AdrsInt;\r
+// p = (char *)&Socks5Reply.Port;\r
+ a = (char *)&Socks5Reply._dummy[0];\r
+ p = (char *)&Socks5Reply._dummy[16];\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*===== SOCKSを使わない =====*/\r
+ DoPrintf("Use normal BIND");\r
+ saCtrlAddr.sin6_port = htons(0);\r
+ saCtrlAddr.sin6_family = AF_INET6;\r
+ memset(&saCtrlAddr.sin6_addr, 0, 16);\r
+\r
+ if(bind(listen_skt, (struct sockaddr *)&saCtrlAddr, sizeof(struct sockaddr_in6)) != SOCKET_ERROR)\r
+ {\r
+ iLength = sizeof(saCtrlAddr);\r
+ if(getsockname(listen_skt, (struct sockaddr *)&saCtrlAddr, &iLength) != SOCKET_ERROR)\r
+ {\r
+ if(do_listen(listen_skt, 1) == 0)\r
+ {\r
+ iLength = sizeof(saTmpAddr);\r
+ if(getsockname(ctrl_skt, (struct sockaddr *)&saTmpAddr, &iLength) == SOCKET_ERROR)\r
+ ReportWSError("getsockname", WSAGetLastError());\r
+\r
+ a = (char *)&saTmpAddr.sin6_addr;\r
+ p = (char *)&saCtrlAddr.sin6_port;\r
+ }\r
+ else\r
+ {\r
+ ReportWSError("listen", WSAGetLastError());\r
+ do_closesocket(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ReportWSError("getsockname", WSAGetLastError());\r
+ do_closesocket(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ReportWSError("bind", WSAGetLastError());\r
+ do_closesocket(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ }\r
+\r
+ if(listen_skt == INVALID_SOCKET)\r
+ SetTaskMsg(MSGJPN030);\r
+ }\r
+ }\r
+ else\r
+ ReportWSError("socket create", WSAGetLastError());\r
+\r
+ if(listen_skt != INVALID_SOCKET)\r
+ {\r
+#define US(w) (((int)w)&0xffff)\r
+ // 同時接続対応\r
+// if((command(ctrl_skt,NULL, &CancelFlg, "PORT %d,%d,%d,%d,%d,%d",\r
+// UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),\r
+// UC(p[0]), UC(p[1])) / 100) != FTP_COMPLETE)\r
+ if((command(ctrl_skt,NULL, CancelCheckWork, "EPRT |2|%s|%d|",\r
+ AddressToStringIPv6(Adrs, a),\r
+ US(p[0])) / 100) != FTP_COMPLETE)\r
+ {\r
+ SetTaskMsg(MSGJPN031);\r
+ do_closesocket(listen_skt);\r
+ listen_skt = INVALID_SOCKET;\r
+ }\r
+// else\r
+// DoPrintf("Skt=%u : listener %s port %u",listen_skt,inet_ntoa(saCtrlAddr.sin_addr),ntohs(saCtrlAddr.sin_port));\r
+ }\r
+\r
+ return(listen_skt);\r
+}\r
+\r
+\r
/*----- ホストへ接続処理中かどうかを返す---------------------------------------\r
*\r
* Parameter\r
}\r
\r
\r
+// IPv6対応\r
+static int Socks5MakeCmdPacketIPv6(SOCKS5REQUEST *Packet, char Cmd, int ValidIP, char *IP, char *Host, ushort Port)\r
+{\r
+ uchar *Pos;\r
+ int Len;\r
+ int TotalLen;\r
+\r
+ Pos = (uchar *)Packet;\r
+ Pos += SOCKS5REQUEST_SIZE;\r
+ TotalLen = SOCKS5REQUEST_SIZE + 2; /* +2はポートの分 */\r
+\r
+ Packet->Ver = SOCKS5_VER;\r
+ Packet->Cmd = Cmd;\r
+ Packet->Rsv = 0;\r
+ if(ValidIP == YES)\r
+ {\r
+ /* IPアドレスを指定 */\r
+ Packet->Type = SOCKS5_ADRS_IPV6;\r
+ memcpy(Pos, IP, 16);\r
+ Pos += 16;\r
+ TotalLen += 16;\r
+ }\r
+ else\r
+ {\r
+ /* ホスト名を指定 */\r
+ Packet->Type = SOCKS5_ADRS_NAME;\r
+ Len = strlen(Host);\r
+ *Pos++ = Len;\r
+ strcpy(Pos, Host);\r
+ Pos += Len;\r
+ TotalLen += Len + 1;\r
+ }\r
+ *((ushort *)Pos) = Port;\r
+\r
+ return(TotalLen);\r
+}\r
+\r
+\r
/*----- SOCKSのコマンドを送る -------------------------------------------------\r
*\r
* Parameter\r
if(Packet->Type == SOCKS5_ADRS_IPV4)\r
Len = 4 + 2;\r
else if(Packet->Type == SOCKS5_ADRS_IPV6)\r
- Len = 6 + 2;\r
+ Len = 16 + 2;\r
else\r
{\r
// 同時接続対応\r
}\r
\r
// IPv6対応\r
+int AskInetFamily(void)\r
+{\r
+ return(CurHost.InetFamily);\r
+}\r
+\r
int AskUseIPv6(void)\r
{\r
return(CurHost.UseIPv6);\r
#include <time.h>\r
// IPv6対応\r
//#include <winsock.h>\r
-#include <winsock2.h>\r
+#include <ws2tcpip.h>\r
#include <windowsx.h>\r
#include <commctrl.h>\r
#include <process.h>\r
static LRESULT CALLBACK TransDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);\r
static void DispTransferStatus(HWND hWnd, int End, TRANSPACKET *Pkt);\r
static void DispTransFileInfo(TRANSPACKET *Pkt, char *Title, int SkipButton, int Info);\r
-static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max);\r
+// IPv6対応\r
+//static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max);\r
+static int GetAdrsAndPort(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max);\r
+static int GetAdrsAndPortIPv4(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max);\r
+static int GetAdrsAndPortIPv6(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max);\r
static int IsSpecialDevice(char *Fname);\r
static int MirrorDelNotify(int Cur, int Notify, TRANSPACKET *Pkt);\r
static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);\r
SOCKET listen_socket = INVALID_SOCKET; // data listen socket\r
char Buf[1024];\r
int CreateMode;\r
- struct sockaddr_in saSockAddr1;\r
+ // IPv6対応\r
+// struct sockaddr_in saSockAddr1;\r
+ struct sockaddr_in saSockAddrIPv4;\r
+ struct sockaddr_in6 saSockAddrIPv6;\r
char Reply[ERR_MSG_LEN+7];\r
\r
if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, CancelCheckWork)) != INVALID_SOCKET)\r
// if(SocksGet2ndBindReply(listen_socket, &data_socket) == FFFTP_FAIL)\r
if(SocksGet2ndBindReply(listen_socket, &data_socket, CancelCheckWork) == FFFTP_FAIL)\r
{\r
- iLength = sizeof(saSockAddr1);\r
- data_socket = do_accept(listen_socket, (struct sockaddr *)&saSockAddr1, (int *)&iLength);\r
+ // IPv6対応\r
+// iLength = sizeof(saSockAddr1);\r
+// data_socket = do_accept(listen_socket, (struct sockaddr *)&saSockAddr1, (int *)&iLength);\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ iLength=sizeof(saSockAddrIPv4);\r
+ data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv4, (int *)&iLength);\r
+ break;\r
+ case AF_INET6:\r
+ iLength=sizeof(saSockAddrIPv6);\r
+ data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv6, (int *)&iLength);\r
+ break;\r
+ }\r
\r
if(shutdown(listen_socket, 1) != 0)\r
ReportWSError("shutdown listen", WSAGetLastError());\r
iRetCode = 500;\r
}\r
else\r
- DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port));\r
+ // IPv6対応\r
+// DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port));\r
+ {\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddrIPv4.sin_addr), ntohs(saSockAddrIPv4.sin_port));\r
+ break;\r
+ case AF_INET6:\r
+ DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet6_ntoa(saSockAddrIPv6.sin6_addr), ntohs(saSockAddrIPv6.sin6_port));\r
+ break;\r
+ }\r
+ }\r
}\r
\r
if(data_socket != INVALID_SOCKET)\r
SOCKET data_socket = INVALID_SOCKET; // data channel socket\r
char Buf[1024];\r
int CreateMode;\r
- char Adrs[20];\r
+ // IPv6対応\r
+// char Adrs[20];\r
+ char Adrs[40];\r
int Port;\r
int Flg;\r
char Reply[ERR_MSG_LEN+7];\r
\r
- iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV");\r
+ // IPv6対応\r
+// iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV");\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV");\r
+ break;\r
+ case AF_INET6:\r
+ iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "EPSV");\r
+ break;\r
+ }\r
if(iRetCode/100 == FTP_COMPLETE)\r
{\r
- if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS)\r
+ // IPv6対応\r
+// if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS)\r
+ if(GetAdrsAndPort(Pkt->ctrl_skt, Buf, Adrs, &Port, 39) == FFFTP_SUCCESS)\r
{\r
if((data_socket = connectsock(Adrs, Port, MSGJPN091, CancelCheckWork)) != INVALID_SOCKET)\r
{\r
SOCKET data_socket = INVALID_SOCKET; // data channel socket\r
SOCKET listen_socket = INVALID_SOCKET; // data listen socket\r
char Buf[1024];\r
- struct sockaddr_in saSockAddr1;\r
+ // IPv6対応\r
+// struct sockaddr_in saSockAddr1;\r
+ struct sockaddr_in saSockAddrIPv4;\r
+ struct sockaddr_in6 saSockAddrIPv6;\r
int Resume;\r
char Reply[ERR_MSG_LEN+7];\r
\r
// if(SocksGet2ndBindReply(listen_socket, &data_socket) == FFFTP_FAIL)\r
if(SocksGet2ndBindReply(listen_socket, &data_socket, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL)\r
{\r
- iLength=sizeof(saSockAddr1);\r
- data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddr1, (int *)&iLength);\r
+ // IPv6対応\r
+// iLength=sizeof(saSockAddr1);\r
+// data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddr1, (int *)&iLength);\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ iLength=sizeof(saSockAddrIPv4);\r
+ data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv4, (int *)&iLength);\r
+ break;\r
+ case AF_INET6:\r
+ iLength=sizeof(saSockAddrIPv6);\r
+ data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv6, (int *)&iLength);\r
+ break;\r
+ }\r
\r
if(shutdown(listen_socket, 1) != 0)\r
ReportWSError("shutdown listen", WSAGetLastError());\r
iRetCode = 500;\r
}\r
else\r
- DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port));\r
+ // IPv6対応\r
+// DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port));\r
+ {\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddrIPv4.sin_addr), ntohs(saSockAddrIPv4.sin_port));\r
+ break;\r
+ case AF_INET6:\r
+ DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet6_ntoa(saSockAddrIPv6.sin6_addr), ntohs(saSockAddrIPv6.sin6_port));\r
+ break;\r
+ }\r
+ }\r
}\r
\r
if(data_socket != INVALID_SOCKET)\r
int iRetCode;\r
SOCKET data_socket = INVALID_SOCKET; // data channel socket\r
char Buf[1024];\r
- char Adrs[20];\r
+ // IPv6対応\r
+// char Adrs[20];\r
+ char Adrs[40];\r
int Port;\r
int Flg;\r
int Resume;\r
\r
// 同時接続対応\r
// iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled, "PASV");\r
- iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "PASV");\r
+ // IPv6対応\r
+// iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "PASV");\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "PASV");\r
+ break;\r
+ case AF_INET6:\r
+ iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "EPSV");\r
+ break;\r
+ }\r
if(iRetCode/100 == FTP_COMPLETE)\r
{\r
- if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS)\r
+ // IPv6対応\r
+// if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS)\r
+ if(GetAdrsAndPort(Pkt->ctrl_skt, Buf, Adrs, &Port, 39) == FFFTP_SUCCESS)\r
{\r
// 同時接続対応\r
// if((data_socket = connectsock(Adrs, Port, MSGJPN109, &Canceled)) != INVALID_SOCKET)\r
* FFFTP_SUCCESS/FFFTP_FAIL\r
*----------------------------------------------------------------------------*/\r
\r
-static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max)\r
+static int GetAdrsAndPort(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max)\r
+{\r
+ int Result;\r
+ Result = FFFTP_FAIL;\r
+ switch(AskInetFamily())\r
+ {\r
+ case AF_INET:\r
+ Result = GetAdrsAndPortIPv4(Skt, Str, Adrs, Port, Max);\r
+ break;\r
+ case AF_INET6:\r
+ Result = GetAdrsAndPortIPv6(Skt, Str, Adrs, Port, Max);\r
+ break;\r
+ }\r
+ return Result;\r
+}\r
+\r
+\r
+// IPv6対応\r
+//static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max)\r
+static int GetAdrsAndPortIPv4(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max)\r
{\r
char *Pos;\r
char *Btm;\r
\r
\r
// IPv6対応\r
-static int GetAdrsAndPortIPv6(char *Str, char *Adrs, int *Port, int Max, short *Family)\r
+static int GetAdrsAndPortIPv6(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max)\r
{\r
char *Pos;\r
char *Btm;\r
int Sts;\r
+ int i;\r
+ struct sockaddr_in6 SockAddr;\r
\r
Sts = FFFTP_FAIL;\r
\r
- Pos = strchr(Str, '|');\r
- if(Pos != NULL)\r
+ Btm = strchr(Str, '(');\r
+ if(Btm != NULL)\r
{\r
- Pos++;\r
- Btm = strchr(Pos, '|');\r
+ Btm++;\r
+ Btm = strchr(Btm, '|');\r
if(Btm != NULL)\r
{\r
- switch(atoi(Pos))\r
- {\r
- case 1:\r
- *Family = AF_INET;\r
- break;\r
- case 2:\r
- *Family = AF_INET6;\r
- break;\r
- }\r
Pos = Btm + 1;\r
Btm = strchr(Pos, '|');\r
if(Btm != NULL)\r
{\r
- if((Btm - Pos) <= Max)\r
+ Pos = Btm + 1;\r
+ Btm = strchr(Pos, '|');\r
+ if(Btm != NULL)\r
{\r
- if((Btm - Pos) > 0)\r
+ if((Btm - Pos) <= Max)\r
{\r
- strncpy(Adrs, Pos, Btm - Pos);\r
- *(Adrs + (Btm - Pos)) = NUL;\r
- }\r
+ if((Btm - Pos) > 0)\r
+ {\r
+ strncpy(Adrs, Pos, Btm - Pos);\r
+ *(Adrs + (Btm - Pos)) = NUL;\r
+ }\r
+ else\r
+ {\r
+ i = sizeof(SockAddr);\r
+ if(getpeername(Skt, (struct sockaddr*)&SockAddr, &i) != SOCKET_ERROR)\r
+ AddressToStringIPv6(Adrs, &SockAddr.sin6_addr);\r
+ }\r
\r
- Pos = Btm + 1;\r
- Btm = strchr(Pos, '|');\r
- if(Btm != NULL)\r
- {\r
- Btm++;\r
- *Port = atoi(Pos);\r
- Sts = FFFTP_SUCCESS;\r
+ Pos = Btm + 1;\r
+ Btm = strchr(Pos, '|');\r
+ if(Btm != NULL)\r
+ {\r
+ Btm++;\r
+ *Port = atoi(Pos);\r
+ Btm = strchr(Btm, ')');\r
+ if(Btm != NULL)\r
+ Sts = FFFTP_SUCCESS;\r
+ }\r
}\r
}\r
}\r