"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,94,196,10\r
CONTROL "\90Ø\92f\8e\9e\82ÉQUIT\83R\83}\83\93\83h\82ð\91\97\82é(&U)",CONNECT_SENDQUIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,108,173,10\r
CONTROL "RAS\82Ì\90§\8cä\82ð\8ds\82í\82È\82¢(&R)",CONNECT_NORAS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,173,10\r
+ CONTROL "\94ñPASV\83\82\81[\83h\8e\9e\82ÉUPnP\82ð\90§\8cä\82·\82é(&U)",CONNECT_UPNP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,136,173,10\r
END\r
\r
rasnotify_dlg DIALOG 0, 0, 158, 46\r
#define PERM_A_WRITE 1018\r
#define CONNECT_NORAS 1018\r
#define PERM_A_EXEC 1019\r
+#define CONNECT_UPNP 1019\r
#define PERM_TEXT 1020\r
#define PERM_NOW 1021\r
#define SORT_LFILE_FILE 1022\r
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,109,173,10\r
CONTROL "Do not control dialup (&RAS) connection",CONNECT_NORAS,\r
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,173,10\r
+ CONTROL "Control &UPnP when using non PASV mode",CONNECT_UPNP,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,136,173,10\r
END\r
\r
rasnotify_dlg DIALOG 0, 0, 158, 46\r
#define PERM_A_WRITE 1018\r
#define CONNECT_NORAS 1018\r
#define PERM_A_EXEC 1019\r
+#define CONNECT_UPNP 1019\r
#define PERM_TEXT 1020\r
#define PERM_NOW 1021\r
#define SORT_LFILE_FILE 1022\r
// ソケットにデータを付与\r
int SetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks);\r
int SetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks);\r
+int SetAsyncTableDataMapPort(SOCKET s, int Port);\r
int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks);\r
int GetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks);\r
+int GetAsyncTableDataMapPort(SOCKET s, int* Port);\r
// IPv6対応\r
//struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork);\r
struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork);\r
int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork);\r
// 同時接続対応\r
void RemoveReceivedData(SOCKET s);\r
+// UPnP対応\r
+int LoadUPnP();\r
+void FreeUPnP();\r
+int IsUPnPLoaded();\r
+int AddPortMapping(char* Adrs, int Port);\r
+int RemovePortMapping(int Port);\r
int CheckClosedAndReconnect(void);\r
// 同時接続対応\r
int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork);\r
int Len;\r
int Fwall;\r
\r
+ // UPnP対応\r
+ char Adrs[16];\r
+ int Port;\r
+\r
// ソケットにデータを付与\r
GetAsyncTableDataIPv4(ctrl_skt, &CurSockAddr, &SocksSockAddr);\r
\r
\r
a = (char *)&saTmpAddr.sin_addr;\r
p = (char *)&saCtrlAddr.sin_port;\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(AddPortMapping(AddressToStringIPv4(Adrs, &saTmpAddr.sin_addr), ntohs(saCtrlAddr.sin_port)) == FFFTP_SUCCESS)\r
+ SetAsyncTableDataMapPort(listen_skt, ntohs(saCtrlAddr.sin_port));\r
+ }\r
}\r
else\r
{\r
// IPv6対応\r
// SetTaskMsg(MSGJPN031);\r
SetTaskMsg(MSGJPN031, MSGJPN333);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_skt, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
do_closesocket(listen_skt);\r
listen_skt = INVALID_SOCKET;\r
}\r
int Fwall;\r
\r
char Adrs[40];\r
+ // UPnP対応\r
+ int Port;\r
\r
// ソケットにデータを付与\r
GetAsyncTableDataIPv6(ctrl_skt, &CurSockAddr, &SocksSockAddr);\r
\r
a = (char *)&saTmpAddr.sin6_addr;\r
p = (char *)&saCtrlAddr.sin6_port;\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(AddPortMapping(AddressToStringIPv6(Adrs, &saTmpAddr.sin6_addr), ntohs(saCtrlAddr.sin6_port)) == FFFTP_SUCCESS)\r
+ SetAsyncTableDataMapPort(listen_skt, ntohs(saCtrlAddr.sin6_port));\r
+ }\r
}\r
else\r
{\r
(UC(p[0]) << 8) | UC(p[1])) / 100) != FTP_COMPLETE)\r
{\r
SetTaskMsg(MSGJPN031, MSGJPN334);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_skt, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
do_closesocket(listen_skt);\r
listen_skt = INVALID_SOCKET;\r
}\r
// struct sockaddr_in saSockAddr1;\r
struct sockaddr_in saSockAddrIPv4;\r
struct sockaddr_in6 saSockAddrIPv6;\r
+ // UPnP対応\r
+ int Port;\r
char Reply[ERR_MSG_LEN+7];\r
\r
if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, CancelCheckWork)) != INVALID_SOCKET)\r
\r
if(shutdown(listen_socket, 1) != 0)\r
ReportWSError("shutdown listen", WSAGetLastError());\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
listen_socket = DoClose(listen_socket);\r
\r
if(data_socket == INVALID_SOCKET)\r
{\r
SetErrorMsg(Reply);\r
SetTaskMsg(MSGJPN090);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
listen_socket = DoClose(listen_socket);\r
iRetCode = 500;\r
}\r
}\r
else\r
+ // バグ修正\r
+// iRetCode = 500;\r
+ {\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
+ listen_socket = DoClose(listen_socket);\r
iRetCode = 500;\r
+ }\r
}\r
else\r
{\r
// struct sockaddr_in saSockAddr1;\r
struct sockaddr_in saSockAddrIPv4;\r
struct sockaddr_in6 saSockAddrIPv6;\r
+ // UPnP対応\r
+ int Port;\r
int Resume;\r
char Reply[ERR_MSG_LEN+7];\r
\r
\r
if(shutdown(listen_socket, 1) != 0)\r
ReportWSError("shutdown listen", WSAGetLastError());\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
listen_socket = DoClose(listen_socket);\r
\r
if(data_socket == INVALID_SOCKET)\r
{\r
SetErrorMsg(Reply);\r
SetTaskMsg(MSGJPN108);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ {\r
+ if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+ RemovePortMapping(Port);\r
+ }\r
listen_socket = DoClose(listen_socket);\r
iRetCode = 500;\r
}\r
int LocalKanjiCode = KANJI_SJIS;\r
// 自動切断対策\r
int NoopEnable = NO;\r
+// UPnP対応\r
+int UPnPEnabled = NO;\r
time_t LastDataConnectionTime = 0;\r
\r
\r
\r
InitCommonControls();\r
\r
+ // UPnP対応\r
+ CoInitialize(NULL);\r
+ LoadUPnP();\r
+\r
// FTPS対応\r
#ifdef USE_OPENSSL\r
LoadOpenSSL();\r
#endif\r
// SFTP対応\r
FreePuTTY();\r
+ // UPnP対応\r
+ FreeUPnP();\r
+ CoUninitialize();\r
OleUninitialize();\r
return(Ret);\r
}\r
extern int DispPermissionsNumber;\r
// ディレクトリ自動作成\r
extern int MakeAllDir;\r
+// UPnP対応\r
+extern int UPnPEnabled;\r
\r
\r
/*----- オプションのプロパティシート ------------------------------------------\r
SendDlgItemMessage(hDlg, CONNECT_HIST_PASS, BM_SETCHECK, PassToHist, 0);\r
SendDlgItemMessage(hDlg, CONNECT_SENDQUIT, BM_SETCHECK, SendQuit, 0);\r
SendDlgItemMessage(hDlg, CONNECT_NORAS, BM_SETCHECK, NoRasControl, 0);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_SETCHECK, UPnPEnabled, 0);\r
+ else\r
+ {\r
+ SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_SETCHECK, BST_UNCHECKED, 0);\r
+ EnableWindow(GetDlgItem(hDlg, CONNECT_UPNP), FALSE);\r
+ }\r
return(TRUE);\r
\r
case WM_NOTIFY:\r
PassToHist = SendDlgItemMessage(hDlg, CONNECT_HIST_PASS, BM_GETCHECK, 0, 0);\r
SendQuit = SendDlgItemMessage(hDlg, CONNECT_SENDQUIT, BM_GETCHECK, 0, 0);\r
NoRasControl = SendDlgItemMessage(hDlg, CONNECT_NORAS, BM_GETCHECK, 0, 0);\r
+ // UPnP対応\r
+ if(IsUPnPLoaded() == YES)\r
+ UPnPEnabled = SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_GETCHECK, 0, 0);\r
break;\r
\r
case PSN_RESET :\r
extern int MakeAllDir;\r
// UTF-8対応\r
extern int LocalKanjiCode;\r
+// UPnP対応\r
+extern int UPnPEnabled;\r
\r
/*----- マスタパスワードの設定 ----------------------------------------------\r
*\r
WriteIntValueToReg(hKey4, "MakeDir", MakeAllDir);\r
// UTF-8対応\r
WriteIntValueToReg(hKey4, "Kanji", LocalKanjiCode);\r
+ // UPnP対応\r
+ WriteIntValueToReg(hKey4, "UPnP", UPnPEnabled);\r
}\r
CloseSubKey(hKey4);\r
}\r
ReadIntValueFromReg(hKey4, "MakeDir", &MakeAllDir);\r
// UTF-8対応\r
ReadIntValueFromReg(hKey4, "Kanji", &LocalKanjiCode);\r
+ // UPnP対応\r
+ ReadIntValueFromReg(hKey4, "UPnP", &UPnPEnabled);\r
\r
CloseSubKey(hKey4);\r
}\r
#include <time.h>\r
#include <windowsx.h>\r
#include <commctrl.h>\r
+// UPnP対応\r
+#include <natupnp.h>\r
\r
#include "common.h"\r
#include "resource.h"\r
struct sockaddr_in SocksAddrIPv4;\r
struct sockaddr_in6 HostAddrIPv6;\r
struct sockaddr_in6 SocksAddrIPv6;\r
+ int MapPort;\r
} ASYNCSIGNAL;\r
\r
\r
// スレッド衝突のバグ修正\r
static HANDLE hAsyncTblAccMutex;\r
\r
+// UPnP対応\r
+IUPnPNAT* pUPnPNAT;\r
+IStaticPortMappingCollection* pUPnPMap;\r
\r
\r
\r
memset(&Signal[Pos].SocksAddrIPv4, 0, sizeof(struct sockaddr_in));\r
memset(&Signal[Pos].HostAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
memset(&Signal[Pos].SocksAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
+ Signal[Pos].MapPort = 0;\r
Sts = YES;\r
break;\r
}\r
return(Sts);\r
}\r
\r
+int SetAsyncTableDataMapPort(SOCKET s, int Port)\r
+{\r
+ int Sts;\r
+ int Pos;\r
+\r
+ WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+ Sts = NO;\r
+ for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+ {\r
+ if(Signal[Pos].Socket == s)\r
+ {\r
+ Signal[Pos].MapPort = Port;\r
+ Sts = YES;\r
+ break;\r
+ }\r
+ }\r
+ ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+ return(Sts);\r
+}\r
+\r
int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)\r
{\r
int Sts;\r
return(Sts);\r
}\r
\r
+int GetAsyncTableDataMapPort(SOCKET s, int* Port)\r
+{\r
+ int Sts;\r
+ int Pos;\r
+\r
+ WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+ Sts = NO;\r
+ for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+ {\r
+ if(Signal[Pos].Socket == s)\r
+ {\r
+ *Port = Signal[Pos].MapPort;\r
+ Sts = YES;\r
+ break;\r
+ }\r
+ }\r
+ ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+ return(Sts);\r
+}\r
+\r
\r
\r
\r
}\r
}\r
\r
+// UPnP対応\r
+int LoadUPnP()\r
+{\r
+ int Sts;\r
+ Sts = FFFTP_FAIL;\r
+ if(CoCreateInstance(&CLSID_UPnPNAT, NULL, CLSCTX_ALL, &IID_IUPnPNAT, (void**)&pUPnPNAT) == S_OK)\r
+ {\r
+ if(pUPnPNAT->lpVtbl->get_StaticPortMappingCollection(pUPnPNAT, &pUPnPMap) == S_OK)\r
+ Sts = FFFTP_SUCCESS;\r
+ }\r
+ return Sts;\r
+}\r
+\r
+void FreeUPnP()\r
+{\r
+ if(pUPnPMap != NULL)\r
+ pUPnPMap->lpVtbl->Release(pUPnPMap);\r
+ pUPnPMap = NULL;\r
+ if(pUPnPNAT != NULL)\r
+ pUPnPNAT->lpVtbl->Release(pUPnPNAT);\r
+ pUPnPNAT = NULL;\r
+}\r
+\r
+int IsUPnPLoaded()\r
+{\r
+ int Sts;\r
+ Sts = FFFTP_FAIL;\r
+ if(pUPnPNAT != NULL && pUPnPMap != NULL)\r
+ Sts = FFFTP_SUCCESS;\r
+ return Sts;\r
+}\r
+\r
+int AddPortMapping(char* Adrs, int Port)\r
+{\r
+ int Sts;\r
+ WCHAR Tmp1[40];\r
+ BSTR Tmp2;\r
+ BSTR Tmp3;\r
+ BSTR Tmp4;\r
+ IStaticPortMapping* pPortMap;\r
+ Sts = FFFTP_FAIL;\r
+ MtoW(Tmp1, 40, Adrs, -1);\r
+ if((Tmp2 = SysAllocString(Tmp1)) != NULL)\r
+ {\r
+ if((Tmp3 = SysAllocString(L"TCP")) != NULL)\r
+ {\r
+ if((Tmp4 = SysAllocString(L"FFFTP")) != NULL)\r
+ {\r
+ if(pUPnPMap->lpVtbl->Add(pUPnPMap, Port, Tmp3, Port, Tmp2, VARIANT_TRUE, Tmp4, &pPortMap) == S_OK)\r
+ {\r
+ Sts = FFFTP_SUCCESS;\r
+ pPortMap->lpVtbl->Release(pPortMap);\r
+ }\r
+ SysFreeString(Tmp4);\r
+ }\r
+ SysFreeString(Tmp3);\r
+ }\r
+ SysFreeString(Tmp2);\r
+ }\r
+ return Sts;\r
+}\r
+\r
+int RemovePortMapping(int Port)\r
+{\r
+ int Sts;\r
+ BSTR Tmp;\r
+ Sts = FFFTP_FAIL;\r
+ if((Tmp = SysAllocString(L"TCP")) != NULL)\r
+ {\r
+ if(pUPnPMap->lpVtbl->Remove(pUPnPMap, Port, Tmp) == S_OK)\r
+ Sts = FFFTP_SUCCESS;\r
+ SysFreeString(Tmp);\r
+ }\r
+ return Sts;\r
+}\r
+\r
\r
/*----- \r
*\r
return Result;\r
}\r
\r
+char* AddressToStringIPv4(char* str, void* in)\r
+{\r
+ char* pResult;\r
+ unsigned char* p;\r
+ pResult = str;\r
+ p = (unsigned char*)in;\r
+ sprintf(str, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);\r
+ return pResult;\r
+}\r
+\r
char* AddressToStringIPv6(char* str, void* in6)\r
{\r
char* pResult;\r
\r
HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family);\r
int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle);\r
+char* AddressToStringIPv4(char* str, void* in);\r
char* AddressToStringIPv6(char* str, void* in6);\r
char* inet6_ntoa(struct in6_addr in6);\r
struct in6_addr inet6_addr(const char* cp);\r