bool Mapper_WinUPnP::add(const unsigned short port, const Protocol protocol, const string& description) { IStaticPortMappingCollection* pSPMC = getStaticPortMappingCollection(); if(!pSPMC) return false; /// @todo use a BSTR wrapper BSTR protocol_ = SysAllocString(Text::toT(protocols[protocol]).c_str()); BSTR description_ = SysAllocString(Text::toT(description).c_str()); BSTR localIP = SysAllocString(Text::toT(Util::getLocalIp()).c_str()); IStaticPortMapping* pSPM = 0; HRESULT hr = pSPMC->Add(port, protocol_, port, localIP, VARIANT_TRUE, description_, &pSPM); SysFreeString(protocol_); SysFreeString(description_); SysFreeString(localIP); bool ret = SUCCEEDED(hr); if(ret) { pSPM->Release(); lastPort = port; lastProtocol = protocol; } pSPMC->Release(); return ret; }
bool UPNPCheckDlg::WinUPnP_add(const unsigned short port, const string& protocol, const string& description, IUPnPNAT* pUN) { #ifdef HAVE_NATUPNP_H IStaticPortMappingCollection* pSPMC = WinUPnP_getStaticPortMappingCollection(pUN); if (!pSPMC) return false; /// @todo use a BSTR wrapper BSTR protocol_ = SysAllocString(Text::toT(protocol).c_str()); BSTR description_ = SysAllocString(Text::toT(description).c_str()); BSTR localIP = SysAllocString(Text::toT(Util::getLocalOrBindIp(false)).c_str()); IStaticPortMapping* pSPM = 0; HRESULT hr = pSPMC->Add(port, protocol_, port, localIP, VARIANT_TRUE, description_, &pSPM); SysFreeString(protocol_); SysFreeString(description_); SysFreeString(localIP); bool ret = SUCCEEDED(hr); if (ret) { safe_release(pSPM); } safe_release(pSPMC); return ret; #else return false; #endif }
void UPnP::ClosePort() { if(remote_port_ == 0) return; #ifdef _MSC_VER HRESULT hr; IUPnPNAT* upnpnat; hr = CoCreateInstance (CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void**)&upnpnat); if(FAILED(hr) || !upnpnat) return; IStaticPortMappingCollection* upnpspmc = NULL; hr = upnpnat->get_StaticPortMappingCollection(&upnpspmc); if(FAILED(hr) || !upnpspmc) return; BSTR bstrProtocol = A2BSTR("TCP"); hr = upnpspmc->Remove(remote_port_, bstrProtocol); if(FAILED(hr)) LOG.getlasterror("Automatisches Entfernen des Portforwardings mit UPnP fehlgeschlagen\nFehler"); SysFreeString(bstrProtocol); if(FAILED(hr)) return; #else int hr; UPNPDev* devicelist = NULL; #ifdef UPNPDISCOVER_SUCCESS int upnperror = 0; devicelist = upnpDiscover(2000, NULL, NULL, 0, 0 /* ipv6 */, &upnperror); #else devicelist = upnpDiscover(2000, NULL, NULL, 0); #endif if(!devicelist) return; UPNPUrls urls; IGDdatas data; hr = UPNP_GetValidIGD(devicelist, &urls, &data, NULL, 0); if(hr == 1 || hr == 2) { std::stringstream p; p << remote_port_; hr = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, p.str().c_str(), "TCP", NULL); } freeUPNPDevlist(devicelist); if(hr != 0) return; #endif remote_port_ = 0; }
// Opens the UPnP ports defined when the object was created HRESULT UPnP::OpenPorts(bool log) { CoInitializeEx ( NULL ,COINIT_MULTITHREADED); HRESULT hr = CoCreateInstance (__uuidof(UPnPNAT), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUPnPNAT), (void**)&pUN); if(SUCCEEDED(hr)) { IStaticPortMappingCollection * pSPMC = NULL; hr = pUN->get_StaticPortMappingCollection (&pSPMC); int counter=0; while(SUCCEEDED(hr) && !pSPMC && counter<20) { debug("Retry StaticPortMappingCollection"); hr = pUN->get_StaticPortMappingCollection (&pSPMC); counter++; Sleep(1500); } if(SUCCEEDED(hr) && pSPMC) { // see comment in "else" if(bstrProtocol && bstrInternalClient && bstrDescription) { IStaticPortMapping * pSPM = NULL; hr = pSPMC->Add(PortNumber, bstrProtocol, PortNumber, bstrInternalClient, VARIANT_TRUE, bstrDescription, &pSPM ); if(SUCCEEDED(hr)) { if(log)debug("UPNP: open port %i",PortNumber); PortsAreOpen = true; } else { if(log)debug("UpNP: fail %s, Ignore external IP",_com_error(hr).ErrorMessage()); } } else { hr = E_OUTOFMEMORY; debug("UPNP: Failed "); } } else { debug("UPNP: Failed "); hr = E_FAIL; // work around a known bug here: in some error // conditions, get_SPMC NULLs out the pointer, but incorrectly returns a success code. } pUN->Release(); pUN=NULL; } CoUninitialize(); return hr; }
void UPnP::Destroy() { IUPnPNAT * Nat = NULL; IStaticPortMappingCollection * PortMappingCollection = NULL; HRESULT Result; wchar_t Protocol[256]; WORD Port; if(m_Port == 0) return; Port = m_Port; m_Port = 0; #ifdef MFC TRACE("UPnP: Removing Port\n"); #endif wcscpy_s(Protocol, L"TCP"); // Create IUPnPNat Result = CoCreateInstance(CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void **)&Nat); if(FAILED(Result)) { #ifdef MFC TRACE("UPnP: Unable to create UPnPNAT interface\n"); #endif return; } Result = Nat->get_StaticPortMappingCollection(&PortMappingCollection); if(!PortMappingCollection || FAILED(Result)) { if(PortMappingCollection) PortMappingCollection->Release(); Nat->Release(); #ifdef MFC TRACE("UPnP: Unable to acquire a static portmapping collection\n"); #endif return; } Result = PortMappingCollection->Remove(Port, Protocol); if(FAILED(Result)) { PortMappingCollection->Release(); Nat->Release(); #ifdef MFC TRACE("UPnP: Unable to remove port\n"); #endif return; } }
string Mapper_WinUPnP::getExternalIP() { // Get the External IP from the last added mapping if(!lastPort) return Util::emptyString; IStaticPortMappingCollection* pSPMC = getStaticPortMappingCollection(); if(!pSPMC) return Util::emptyString; /// @todo use a BSTR wrapper BSTR protocol_ = SysAllocString(Text::toT(protocols[lastProtocol]).c_str()); // Lets Query our mapping IStaticPortMapping* pSPM; HRESULT hr = pSPMC->get_Item(lastPort, protocol_, &pSPM); SysFreeString(protocol_); // Query failed! if(FAILED(hr) || !pSPM) { pSPMC->Release(); return Util::emptyString; } BSTR bstrExternal = 0; hr = pSPM->get_ExternalIPAddress(&bstrExternal); if(FAILED(hr) || !bstrExternal) { pSPM->Release(); pSPMC->Release(); return Util::emptyString; } // convert the result string ret = Text::wideToAcp(bstrExternal); // no longer needed SysFreeString(bstrExternal); // no longer needed pSPM->Release(); pSPMC->Release(); return ret; }
bool Mapper_WinUPnP::remove(const unsigned short port, const Protocol protocol) { IStaticPortMappingCollection* pSPMC = getStaticPortMappingCollection(); if(!pSPMC) return false; /// @todo use a BSTR wrapper BSTR protocol_ = SysAllocString(Text::toT(protocols[protocol]).c_str()); HRESULT hr = pSPMC->Remove(port, protocol_); pSPMC->Release(); SysFreeString(protocol_); bool ret = SUCCEEDED(hr); if(ret && port == lastPort && protocol == lastProtocol) { lastPort = 0; } return ret; }
bool UPNPCheckDlg::WinUPnP_remove(const unsigned short port, const string& protocol, IUPnPNAT* pUN) { #ifdef HAVE_NATUPNP_H IStaticPortMappingCollection* pSPMC = WinUPnP_getStaticPortMappingCollection(pUN); if (!pSPMC) return false; /// @todo use a BSTR wrapper BSTR protocol_ = SysAllocString(Text::toT(protocol).c_str()); HRESULT hr = pSPMC->Remove(port, protocol_); safe_release(pSPMC); SysFreeString(protocol_); return SUCCEEDED(hr); #else return false; #endif }
// Closes the UPnP ports defined when the object was created HRESULT UPnP::ClosePorts(bool log) { // if(PortsAreOpen == false) { // return S_OK; // } HRESULT hr = E_FAIL; HRESULT hr2 = E_FAIL; CoInitializeEx ( NULL ,COINIT_MULTITHREADED); hr = CoCreateInstance (__uuidof(UPnPNAT), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUPnPNAT), (void**)&pUN); if(SUCCEEDED(hr)) { if(bstrProtocol && bstrInternalClient && bstrDescription) { IStaticPortMappingCollection * pSPMC = NULL; hr2 = pUN->get_StaticPortMappingCollection (&pSPMC); if(SUCCEEDED(hr2) && pSPMC) { hr = pSPMC->Remove(PortNumber, bstrProtocol); if(SUCCEEDED(hr)) if(log)debug("UPNP: closed port %i",PortNumber); pSPMC->Release(); } SysFreeString(bstrProtocol); SysFreeString(bstrInternalClient); SysFreeString(bstrDescription); SysFreeString(bstrExternalIP); } pUN->Release(); pUN=NULL; } CoUninitialize(); return hr; }
/** * Erstellt per UPnP ein Portforwarding. * * @author FloSoft */ bool UPnP::OpenPort(const unsigned short& port) { if(remote_port_ != 0) ClosePort(); remote_port_ = port; #ifdef _MSC_VER HRESULT hr; CoInitialize(NULL); IUPnPNAT* upnpnat; hr = CoCreateInstance (CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void**)&upnpnat); if(FAILED(hr) || !upnpnat) { if(!upnpnat) hr = E_NOINTERFACE; SetLastError(hr); return false; } IStaticPortMappingCollection* upnpspmc = NULL; hr = upnpnat->get_StaticPortMappingCollection(&upnpspmc); if(FAILED(hr) || !upnpspmc) { if(!upnpspmc) hr = E_NOINTERFACE; SetLastError(hr); return false; } std::string local_address; std::vector<std::string> addresses = GetAllv4Addresses(); // if we have multiple addresses, search the private one if(addresses.size() > 1) { for(std::vector<std::string>::iterator addr = addresses.begin(); addr != addresses.end(); ++addr) { std::string ss = *addr; std::stringstream s, sc; s << ss; std::getline(s, ss, '.'); sc << ss << " "; std::getline(s, ss, '.'); sc << ss << " "; int a, b; sc >> a; sc >> b; int ab = (a << 24) | (b << 16); if( (ab & 0xff000000) == 0x0a000000 || // 10.0.0.0/8 (ab & 0xff000000) == 0x7f000000 || // 127.0.0.0/8 (ab & 0xfff00000) == 0xac100000 || // 172.16.0.0/12 (ab & 0xffff0000) == 0xc0a80000 ) // 192.168.0.0/16 local_address = *addr; } } // otherwise use the first one if(local_address == "" && !addresses.empty()) local_address = addresses.front(); // I hope we found one ... if(local_address == "") { SetLastError(E_FAIL); return false; } BSTR bstrProtocol = A2BSTR("TCP"); BSTR bstrLocalAddress = A2BSTR(local_address.c_str()); BSTR bstrDescription = A2BSTR("Return To The Roots"); IStaticPortMapping* upnpspm = NULL; hr = upnpspmc->Add(port, bstrProtocol, port, bstrLocalAddress, VARIANT_TRUE, bstrDescription, &upnpspm); SysFreeString(bstrProtocol); SysFreeString(bstrLocalAddress); SysFreeString(bstrDescription); if(SUCCEEDED(hr) && !upnpspm) hr = E_NOINTERFACE; SetLastError(hr); if(SUCCEEDED(hr) && upnpspm) return true; #else int hr; UPNPDev* devicelist = NULL; #ifdef UPNPDISCOVER_SUCCESS int upnperror = 0; devicelist = upnpDiscover(2000, NULL, NULL, 0, 0 /* ipv6 */, &upnperror); #else devicelist = upnpDiscover(2000, NULL, NULL, 0); #endif if(!devicelist) return false; UPNPUrls urls; IGDdatas data; char lanAddr[64]; hr = UPNP_GetValidIGD(devicelist, &urls, &data, lanAddr, sizeof(lanAddr)); if(hr == 1 || hr == 2) { std::stringstream p; p << port; #ifdef UPNPDISCOVER_SUCCESS hr = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, p.str().c_str(), p.str().c_str(), lanAddr, "Return To The Roots", "TCP", NULL, NULL); #else hr = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, p.str().c_str(), p.str().c_str(), lanAddr, "Return To The Roots", "TCP", NULL); #endif } freeUPNPDevlist(devicelist); if(hr == 0) return true; #endif return false; }
bool UPnP::Create(u16 Port) { IUPnPNAT * Nat = NULL; IStaticPortMappingCollection * PortMappingCollection = NULL; IStaticPortMapping * PortMap = NULL; HRESULT Result; wchar_t Protocol[256]; wchar_t InternalClient[256]; wchar_t Description[256]; Destroy(); #ifdef MFC TRACE("UPnP: Adding port\n"); #endif if(!GetIp()) { return false; } size_t num_chars_converted{}; mbstowcs_s(&num_chars_converted, InternalClient, m_Address, 256); wcscpy_s(Protocol, L"UDP"); wcscpy_s(Description, L"Gunz"); // Create IUPnPNat Result = CoCreateInstance(CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void **)&Nat); if(FAILED(Result)) { #ifdef MFC TRACE("UPnP: Unable to create UPnPNAT interface\n"); #endif return false; } Result = Nat->get_StaticPortMappingCollection(&PortMappingCollection); if(!PortMappingCollection || FAILED(Result)) { if(PortMappingCollection) PortMappingCollection->Release(); Nat->Release(); #ifdef MFC TRACE("UPnP: Unable to acquire a static portmapping collection\n"); #endif return false; } Result = PortMappingCollection->Add(Port, Protocol, Port, InternalClient, VARIANT_TRUE, Description, &PortMap); if(!PortMap || FAILED(Result)) { if(PortMap) PortMap->Release(); PortMappingCollection->Release(); Nat->Release(); #ifdef MFC TRACE("UPnP: Unable add port\n"); #endif return false; } #ifdef MFC TRACE("UPnP: Port %d forwarded to %s\n", Port, m_Address); #endif PortMap->Release(); PortMappingCollection->Release(); Nat->Release(); m_Port = Port; return true; }
// Add a UPnP port bool Win32UPnPAddPort(UINT outside_port, UINT inside_port, bool udp, char *local_ip, wchar_t *description, bool remove_before_add) { bool ret = false; HRESULT hr; IUPnPNAT *nat = NULL; wchar_t ip_str[MAX_SIZE]; BSTR bstr_ip, bstr_description, bstr_protocol; wchar_t *protocol_str = (udp ? L"UDP" : L"TCP"); // Validate arguments if (outside_port == 0 || outside_port >= 65536 || inside_port == 0 || inside_port >= 65536 || IsEmptyStr(local_ip) || UniIsEmptyStr(description)) { return false; } StrToUni(ip_str, sizeof(ip_str), local_ip); bstr_ip = SysAllocString(ip_str); bstr_description = SysAllocString(description); bstr_protocol = SysAllocString(protocol_str); hr = CoCreateInstance(CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void **)&nat); if (SUCCEEDED(hr)) { if (nat != NULL) { IStaticPortMappingCollection *collection = NULL; hr = nat->get_StaticPortMappingCollection(&collection); if (SUCCEEDED(hr)) { if (collection != NULL) { IStaticPortMapping *mapping = NULL; if (remove_before_add) { hr = collection->Remove((long)outside_port, bstr_protocol); } hr = collection->Add((long)outside_port, bstr_protocol, (long)inside_port, bstr_ip, VARIANT_TRUE, bstr_description, &mapping); if (SUCCEEDED(hr)) { ret = true; if (mapping != NULL) { mapping->Release(); } } collection->Release(); } else { WHERE; } } else { WHERE; } nat->Release(); } else { WHERE; } } else { WHERE; } SysFreeString(bstr_ip); SysFreeString(bstr_description); SysFreeString(bstr_protocol); return ret; }
// Returns the current external IP address _bstr_t UPnP::GetExternalIP() { HRESULT hr; // Check if we opened the desired port, 'cause we use it for getting the IP // This shouldn't be a problem because we only try to get the external IP when // we opened the mapping // This function is not used somewhere else, hence it is "save" to do it like this if(!PortsAreOpen) { return ""; } BSTR bstrExternal = NULL; _bstr_t bstrWrapper; CoInitializeEx ( NULL ,COINIT_MULTITHREADED); hr = CoCreateInstance (__uuidof(UPnPNAT), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUPnPNAT), (void**)&pUN); if(SUCCEEDED(hr)) { // Get the Collection IStaticPortMappingCollection *pIMaps = NULL; hr = pUN->get_StaticPortMappingCollection(&pIMaps); // Check it // We also check against that bug mentioned in OpenPorts() if(!SUCCEEDED(hr) || !pIMaps ) { // Only release when OK if(pIMaps != NULL) { pIMaps->Release(); } pUN->Release(); pUN=NULL; CoUninitialize(); return ""; } // Lets Query our mapping IStaticPortMapping *pISM; hr = pIMaps->get_Item( PortNumber, bstrProtocol, &pISM ); // Query failed! if(!SUCCEEDED(hr)) { pIMaps->Release(); pUN->Release(); pUN=NULL; CoUninitialize(); return ""; } // Get the External IP from our mapping hr = pISM->get_ExternalIPAddress(&bstrExternal); // D'OH. Failed if(!SUCCEEDED(hr)) { pIMaps->Release(); pISM->Release(); pUN->Release(); pUN=NULL; CoUninitialize(); return ""; } // Check and convert the result if(bstrExternal != NULL) { bstrWrapper.Assign(bstrExternal); } else { bstrWrapper = ""; } // no longer needed SysFreeString(bstrExternal); // no longer needed pIMaps->Release(); pISM->Release(); pUN->Release(); pUN=NULL; CoUninitialize(); } return bstrWrapper; }
int SetPortForwarding(char *localIP, char *description, int internalPort, int *externalPort) { CoInitialize(NULL); int errorCode = 0; IUPnPNAT *nat = NULL; IStaticPortMappingCollection *mappingCollection = NULL; IStaticPortMapping *mapping = NULL; if( !SUCCEEDED( CoCreateInstance(__uuidof(UPnPNAT), NULL, CLSCTX_ALL, __uuidof(IUPnPNAT), (void **)&nat) ) || ( nat==NULL ) ) { errorCode = ERROR_COCREATEINSTANCE; goto ERROR_EXIT; } if ( !SUCCEEDED( nat->get_StaticPortMappingCollection(&mappingCollection) ) || (mappingCollection==NULL ) ) { errorCode = ERROR_UPNP_NOT_FOUNDED; goto ERROR_EXIT; } while( TRUE ) { IStaticPortMapping *existMapping = NULL; BOOL hasMappingInformation = SUCCEEDED( mappingCollection->get_Item(*externalPort, L"TCP", &existMapping) ); if ( hasMappingInformation ) { //printf( "hasMappingInformation \n" ); BSTR bStrIP = NULL; existMapping->get_InternalClient(&bStrIP); BSTR bstrDescryption = NULL; existMapping->get_Description(&bstrDescryption); long iExistInternalPort = 0; existMapping->get_InternalPort(&iExistInternalPort); if( bStrIP != NULL && bstrDescryption != NULL ) { //printf( "bStrIP != NULL && bstrDescryption != NULL \n" ); USES_CONVERSION; char *sClientIP = OLE2A(bStrIP); char *sDescryption = OLE2A(bstrDescryption); BOOL hasMapping = ( strcmp(sClientIP, localIP) == 0 ) && ( strcmp(sDescryption, description) == 0) && ( iExistInternalPort == internalPort ); if ( hasMapping ) { //printf( "hasMapping \n" ); SysFreeString(bStrIP); SysFreeString(bstrDescryption); break; } SysFreeString(bStrIP); SysFreeString(bstrDescryption); } existMapping->Release(); (*externalPort)++; //printf( "(*externalPort)++: %d \n", *externalPort ); } else { //printf( "not hasMappingInformation \n" ); VARIANT_BOOL vb = VARIANT_TRUE; USES_CONVERSION; BOOL isNewMappingRegistered = SUCCEEDED( mappingCollection->Add(*externalPort, L"TCP", internalPort, A2W(localIP), vb, A2W(description), &mapping) ); if( ! isNewMappingRegistered ) { //printf( "not isNewMappingRegistered \n" ); errorCode = ERROR_PORTMAPPING_FAILED; goto ERROR_EXIT; } break; } } ERROR_EXIT: if ( NULL != mapping ) { mapping->Release(); mapping = NULL; } if ( NULL != mappingCollection ) { mappingCollection->Release(); mappingCollection = NULL; } if ( NULL != nat ) { nat->Release(); nat = NULL; } CoUninitialize(); return errorCode; }