void UPnP::Discover () { int nerror = 0; #if MINIUPNPC_API_VERSION >= 14 m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror); #else m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); #endif { // notify satrting thread std::unique_lock<std::mutex> l(m_StartedMutex); m_Started.notify_all (); } int r; r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); if (r == 1) { r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); if(r != UPNPCOMMAND_SUCCESS) { LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress() returned ", r); return; } else { if (!m_externalIPAddress[0]) { LogPrint (eLogError, "UPnP: GetExternalIPAddress() failed."); return; } } } else { LogPrint (eLogError, "UPnP: GetValidIGD() failed."); return; } // UPnP discovered LogPrint (eLogDebug, "UPnP: ExternalIPAddress is ", m_externalIPAddress); i2p::context.UpdateAddress (boost::asio::ip::address::from_string (m_externalIPAddress)); // port mapping PortMapping (); }
int SetUp(void) { int error = 0; g_devlist = upnpDiscover(1000, NULL, NULL, 0, 0, &error); if(!g_devlist) { printf("no upnp device list\n"); return -1; } g_urls = (struct UPNPUrls*)malloc(sizeof(struct UPNPUrls)); g_data = (struct IGDdatas*)malloc(sizeof(struct IGDdatas)); if(!g_urls || !g_data) { printf("malloc failed\n"); return -1; } memset(g_urls, 0, sizeof(struct UPNPUrls)); memset(g_data, 0, sizeof(struct IGDdatas)); int result = UPNP_GetValidIGD(g_devlist, g_urls, g_data, g_lanaddr, sizeof(g_lanaddr)); if(result == 1) { printf("%d, %s\n", result, g_urls->controlURL); } else if(result == 2) { printf("%d, %s\n", result, g_urls->controlURL); } else if(result == 3) { printf("%d, %s\n", result, g_urls->controlURL); } else { printf("no valid IGD\n"); return -1; } printf("local address: %s\n", g_lanaddr); return 0; }
static gboolean update_upnp_status (VinoUpnp *upnp) { struct UPNPDev * devlist; int res; if (upnp->priv->have_igd) return TRUE; clean_upnp_data (upnp); dprintf (UPNP, "UPnP: Doing the discovery... "); devlist = upnpDiscover (2000, NULL, NULL, 0); if (!devlist) { dprintf (UPNP, "nothing found, aborting."); return FALSE; } dprintf (UPNP, "found.\n"); dprintf (UPNP, "UPnP: Looking for a valid IGD... "); upnp->priv->urls = g_new0 (struct UPNPUrls, 1); upnp->priv->data = g_new0 (struct IGDdatas, 1); res = UPNP_GetValidIGD (devlist, upnp->priv->urls, upnp->priv->data, upnp->priv->lanaddr, sizeof (upnp->priv->lanaddr)); if (res == 1 || res == 2) { dprintf (UPNP, "found: %s\n", upnp->priv->urls->controlURL); upnp->priv->have_igd = TRUE; } else { dprintf (UPNP, "none found, aborting.\n"); upnp->priv->have_igd = FALSE; } freeUPNPDevlist (devlist); return upnp->priv->have_igd; }
static inline void I_InitUPnP(void) { struct UPNPDev * devlist = NULL; int upnp_error = -2; CONS_Printf(M_GetText("Looking for UPnP Internet Gateway Device\n")); devlist = upnpDiscover(2000, NULL, NULL, 0, false, &upnp_error); if (devlist) { struct UPNPDev *dev = devlist; char * descXML; int descXMLsize = 0; while (dev) { if (strstr (dev->st, "InternetGatewayDevice")) break; dev = dev->pNext; } if (!dev) dev = devlist; /* defaulting to first device */ CONS_Printf(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"), dev->descURL, dev->st); UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); CONS_Printf(M_GetText("Local LAN IP address: %s\n"), lanaddr); descXML = miniwget(dev->descURL, &descXMLsize); if (descXML) { parserootdesc(descXML, descXMLsize, &data); free(descXML); descXML = NULL; memset(&urls, 0, sizeof(struct UPNPUrls)); memset(&data, 0, sizeof(struct IGDdatas)); GetUPNPUrls(&urls, &data, dev->descURL); I_AddExitFunc(I_ShutdownUPnP); } freeUPNPDevlist(devlist); } else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR) { CONS_Printf(M_GetText("No UPnP devices discovered\n")); } }
static PyObject * UPnP_selectigd(UPnPObject *self) { int r; Py_BEGIN_ALLOW_THREADS r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data, self->lanaddr, sizeof(self->lanaddr)); Py_END_ALLOW_THREADS if(r) { return Py_BuildValue("s", self->urls.controlURL); } else { /* TODO: have our own exception type ! */ PyErr_SetString(PyExc_Exception, "No UPnP device discovered"); return NULL; } }
/** Initialize the UPnP backend and store the results in * <b>backend_state</b>.*/ int tor_upnp_init(tor_fw_options_t *options, void *backend_state) { /* This leaks the user agent from the client to the router - perhaps we don't want to do that? eg: User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4 */ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; struct UPNPDev *devlist; int r; memset(&(state->urls), 0, sizeof(struct UPNPUrls)); memset(&(state->data), 0, sizeof(struct IGDdatas)); state->init = 0; #ifdef MINIUPNPC15 devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0); #else devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0, 0, NULL); #endif if (NULL == devlist) { fprintf(stderr, "E: upnpDiscover returned: NULL\n"); return UPNP_ERR_NODEVICESFOUND; } assert(options); r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data), state->lanaddr, UPNP_LANADDR_SZ); fprintf(stderr, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r, r==UPNP_SUCCESS?"SUCCESS":"FAILED"); freeUPNPDevlist(devlist); if (r != 1 && r != 2) return UPNP_ERR_NOIGDFOUND; state->init = 1; return UPNP_ERR_SUCCESS; }
void threadMain() throw() { char lanaddr[4096]; char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P char inport[16]; char outport[16]; struct UPNPUrls urls; struct IGDdatas data; #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: started for UDP port %d"ZT_EOL_S,localPort); #endif unsigned int tryPortStart = 0; Utils::getSecureRandom(&tryPortStart,sizeof(tryPortStart)); tryPortStart = (tryPortStart % (65535 - 1025)) + 1025; while (run) { { int upnpError = 0; UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,0,&upnpError); if (devlist) { #ifdef ZT_UPNP_TRACE { UPNPDev *dev = devlist; while (dev) { fprintf(stderr,"UPNPClient: found device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st); dev = dev->pNext; } } #endif memset(lanaddr,0,sizeof(lanaddr)); memset(externalip,0,sizeof(externalip)); memset(&urls,0,sizeof(urls)); memset(&data,0,sizeof(data)); Utils::snprintf(inport,sizeof(inport),"%d",localPort); if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: my LAN IP address: %s"ZT_EOL_S,lanaddr); #endif if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: my external IP address: %s"ZT_EOL_S,externalip); #endif for(int tries=0;tries<64;++tries) { int tryPort = (int)tryPortStart + tries; if (tryPort >= 65535) tryPort = (tryPort - 65535) + 1025; Utils::snprintf(outport,sizeof(outport),"%u",tryPort); int mapResult = 0; if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,"ZeroTier","UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: reserved external port: %s"ZT_EOL_S,outport); #endif { Mutex::Lock sl(surface_l); surface.clear(); InetAddress tmp(externalip); tmp.setPort(tryPort); surface.push_back(tmp); } break; } else { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: UPNP_AddAnyPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult); #endif Thread::sleep(1000); } } } else { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: UPNP_GetExternalIPAddress failed"ZT_EOL_S); #endif } } else { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: UPNP_GetValidIGD failed"ZT_EOL_S); #endif } freeUPNPDevlist(devlist); } else { #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: upnpDiscover error code: %d"ZT_EOL_S,upnpError); #endif } } #ifdef ZT_UPNP_TRACE fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_UPNP_CLIENT_REFRESH_DELAY); #endif Thread::sleep(ZT_UPNP_CLIENT_REFRESH_DELAY); } delete this; }
/* sample upnp client program */ int main(int argc, char ** argv) { char command = 0; char ** commandargv = 0; int commandargc = 0; struct UPNPDev * devlist = 0; char lanaddr[64]; /* my ip address on the LAN */ int i; const char * rootdescurl = 0; const char * multicastif = 0; const char * minissdpdpath = 0; int retcode = 0; int error = 0; int ipv6 = 0; const char * description = 0; #ifdef _WIN32 WSADATA wsaData; int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(nResult != NO_ERROR) { fprintf(stderr, "WSAStartup() failed.\n"); return -1; } #endif printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n"); printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" "for more information.\n"); /* command line processing */ for(i=1; i<argc; i++) { if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h")) { command = 0; break; } if(argv[i][0] == '-') { if(argv[i][1] == 'u') rootdescurl = argv[++i]; else if(argv[i][1] == 'm') multicastif = argv[++i]; else if(argv[i][1] == 'p') minissdpdpath = argv[++i]; else if(argv[i][1] == '6') ipv6 = 1; else if(argv[i][1] == 'e') description = argv[++i]; else { command = argv[i][1]; i++; commandargv = argv + i; commandargc = argc - i; break; } } else { fprintf(stderr, "option '%s' invalid\n", argv[i]); } } if(!command || (command == 'a' && commandargc<4) || (command == 'd' && argc<2) || (command == 'r' && argc<2) || (command == 'A' && commandargc<6) || (command == 'U' && commandargc<2) || (command == 'D' && commandargc<1)) { fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -d external_port protocol <remote host>\n\t\tDelete port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); fprintf(stderr, "\nprotocol is UDP or TCP\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -e description : set description for port mapping.\n"); fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); return 1; } if( rootdescurl || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error))) { struct UPNPDev * device; struct UPNPUrls urls; struct IGDdatas data; if(devlist) { printf("List of UPNP devices found on the network :\n"); for(device = devlist; device; device = device->pNext) { printf(" desc: %s\n st: %s\n\n", device->descURL, device->st); } } else if(!rootdescurl) { printf("upnpDiscover() error code=%d\n", error); } i = 1; if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) { switch(i) { case 1: printf("Found valid IGD : %s\n", urls.controlURL); break; case 2: printf("Found a (not connected?) IGD : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; case 3: printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; default: printf("Found device (igd ?) : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); } printf("Local LAN ip address : %s\n", lanaddr); #if 0 printf("getting \"%s\"\n", urls.ipcondescURL); descXML = miniwget(urls.ipcondescURL, &descXMLsize); if(descXML) { /*fwrite(descXML, 1, descXMLsize, stdout);*/ free(descXML); descXML = NULL; } #endif switch(command) { case 'l': DisplayInfos(&urls, &data); ListRedirections(&urls, &data); break; case 'L': NewListRedirections(&urls, &data); break; case 'a': SetRedirectAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], (commandargc > 4)?commandargv[4]:"0", description, 0); break; case 'd': RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], commandargc > 2 ? commandargv[2] : NULL); break; case 'n': /* aNy */ SetRedirectAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], (commandargc > 4)?commandargv[4]:"0", description, 1); break; case 'N': if (commandargc < 3) fprintf(stderr, "too few arguments\n"); RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargc > 3 ? commandargv[3] : NULL); break; case 's': GetConnectionStatus(&urls, &data); break; case 'r': i=0; while(i<commandargc){ if(!is_int(commandargv[i+1])){ /* 2nd parameter not an integer, so format is '<port> <protocol>' */ /* Note: no 2nd parameter is also not-an-integer, and will lead to a "Wrong arguments" */ SetRedirectAndTest(&urls, &data, lanaddr, commandargv[i], commandargv[i], commandargv[i+1], "0", description, 0); i+=2; /* 2 parameters parsed */ } else { /* 2nd parameter is an integer, so format is '<port> <external_port> <protocol>' */ SetRedirectAndTest(&urls, &data, lanaddr, commandargv[i], commandargv[i+1], commandargv[i+2], "0", description, 0); i+=3; /* 3 parameters parsed */ } } break; case 'A': SetPinholeAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], commandargv[4], commandargv[5]); break; case 'U': GetPinholeAndUpdate(&urls, &data, commandargv[0], commandargv[1]); break; case 'C': for(i=0; i<commandargc; i++) { CheckPinhole(&urls, &data, commandargv[i]); } break; case 'K': for(i=0; i<commandargc; i++) { GetPinholePackets(&urls, &data, commandargv[i]); } break; case 'D': for(i=0; i<commandargc; i++) { RemovePinhole(&urls, &data, commandargv[i]); } break; case 'S': GetFirewallStatus(&urls, &data); break; case 'G': GetPinholeOutboundTimeout(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], commandargv[4]); break; case 'P': printf("Presentation URL found:\n"); printf(" %s\n", data.presentationurl); break; default: fprintf(stderr, "Unknown switch -%c\n", command); retcode = 1; } FreeUPNPUrls(&urls); } else { fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); retcode = 1; } freeUPNPDevlist(devlist); devlist = 0; } else { fprintf(stderr, "No IGD UPnP Device found on the network !\n"); retcode = 1; } #ifdef _WIN32 nResult = WSACleanup(); if(nResult != NO_ERROR) { fprintf(stderr, "WSACleanup() failed.\n"); } #endif /* _WIN32 */ return retcode; }
/** * 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; }
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.writeLastError("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; #if (MINIUPNPC_API_VERSION >= 14) /* miniUPnPc API version 14 adds TTL parameter */ devicelist = upnpDiscover(2000, NULL, NULL, 0, 0 /* ipv6 */, 2, &upnperror); #else devicelist = upnpDiscover(2000, NULL, NULL, 0, 0 /* ipv6 */, &upnperror); #endif #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; }
/// RakNet stuff void CDemo::UpdateRakNet(void) { RakNet::SystemAddress facilitatorSystemAddress(DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP, DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_PORT); RakNet::Packet *packet; RakNet::TimeMS curTime = RakNet::GetTimeMS(); RakNet::RakString targetName; for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive()) { if (strcmp(packet->systemAddress.ToString(false),DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP)==0) { targetName="NATPunchthroughServer"; } else { targetName=packet->systemAddress.ToString(true); } switch (packet->data[0]) { case ID_IP_RECENTLY_CONNECTED: { PushMessage(RakNet::RakString("This IP address recently connected from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_INCOMPATIBLE_PROTOCOL_VERSION: { PushMessage(RakNet::RakString("Incompatible protocol version from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_DISCONNECTION_NOTIFICATION: { PushMessage(RakNet::RakString("Disconnected from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) isConnectedToNATPunchthroughServer=false; } break; case ID_CONNECTION_LOST: { PushMessage(RakNet::RakString("Connection to ") + targetName + RakNet::RakString(" lost.")); if (packet->systemAddress==facilitatorSystemAddress) isConnectedToNATPunchthroughServer=false; } break; case ID_NO_FREE_INCOMING_CONNECTIONS: { PushMessage(RakNet::RakString("No free incoming connections to ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_NEW_INCOMING_CONNECTION: { if (fullyConnectedMesh2->IsHostSystem()) { PushMessage(RakNet::RakString("Sending player list to new connection")); fullyConnectedMesh2->StartVerifiedJoin(packet->guid); } } break; case ID_FCM2_VERIFIED_JOIN_START: { DataStructures::List<RakNet::SystemAddress> addresses; DataStructures::List<RakNet::RakNetGUID> guids; fullyConnectedMesh2->GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids); for (unsigned int i=0; i < guids.Size(); i++) natPunchthroughClient->OpenNAT(guids[i], facilitatorSystemAddress); } break; case ID_FCM2_VERIFIED_JOIN_FAILED: { PushMessage(RakNet::RakString("Failed to join game session")); } break; case ID_FCM2_VERIFIED_JOIN_CAPABLE: { fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, true, 0); } break; case ID_FCM2_VERIFIED_JOIN_ACCEPTED: { DataStructures::List<RakNet::RakNetGUID> systemsAccepted; bool thisSystemAccepted; fullyConnectedMesh2->GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, 0); if (thisSystemAccepted) PushMessage("Game join request accepted\n"); else PushMessage(RakNet::RakString("System %s joined the mesh\n", systemsAccepted[0].ToString())); // DataStructures::List<RakNetGUID> participantList; // fullyConnectedMesh2->GetParticipantList(participantList); for (unsigned int i=0; i < systemsAccepted.Size(); i++) replicaManager3->PushConnection(replicaManager3->AllocConnection(rakPeer->GetSystemAddressFromGuid(systemsAccepted[i]), systemsAccepted[i])); } break; case ID_CONNECTION_REQUEST_ACCEPTED: { PushMessage(RakNet::RakString("Connection request to ") + targetName + RakNet::RakString(" accepted.")); if (packet->systemAddress==facilitatorSystemAddress) { isConnectedToNATPunchthroughServer=true; // Open UPNP. struct UPNPDev * devlist = 0; devlist = upnpDiscover(1000, 0, 0, 0); if (devlist) { char lanaddr[64]; /* my ip address on the LAN */ struct UPNPUrls urls; struct IGDdatas data; if (UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))==1) { // External port is the port people will be connecting to us on. This is our port as seen by the directory server // Internal port is the port RakNet was internally started on char eport[32], iport[32]; natPunchthroughClient->GetUPNPPortMappings(eport, iport, facilitatorSystemAddress); int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport, iport, lanaddr, 0, "UDP", 0); if(r==UPNPCOMMAND_SUCCESS) { // UPNP done } } } // Query cloud for other running game instances RakNet::CloudQuery cloudQuery; cloudQuery.keys.Push(RakNet::CloudKey("IrrlichtDemo",0),_FILE_AND_LINE_); cloudClient->Get(&cloudQuery, packet->guid); } } break; case ID_FCM2_NEW_HOST: { if (packet->guid==rakPeer->GetMyGUID()) { // Original host dropped. I am the new session host. Upload to the cloud so new players join this system. RakNet::CloudKey cloudKey("IrrlichtDemo",0); cloudClient->Post(&cloudKey, 0, 0, rakPeer->GetGuidFromSystemAddress(facilitatorSystemAddress)); } } break; case ID_CLOUD_GET_RESPONSE: { RakNet::CloudQueryResult cloudQueryResult; cloudClient->OnGetReponse(&cloudQueryResult, packet); if (cloudQueryResult.rowsReturned.Size()>0) { PushMessage(RakNet::RakString("NAT punch to existing game instance")); natPunchthroughClient->OpenNAT(cloudQueryResult.rowsReturned[0]->clientGUID, facilitatorSystemAddress); } else { PushMessage(RakNet::RakString("Publishing new game instance")); // Start as a new game instance because no other games are running RakNet::CloudKey cloudKey("IrrlichtDemo",0); cloudClient->Post(&cloudKey, 0, 0, packet->guid); } cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult); } break; case ID_CONNECTION_ATTEMPT_FAILED: { PushMessage(RakNet::RakString("Connection attempt to ") + targetName + RakNet::RakString(" failed.")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_NAT_TARGET_NOT_CONNECTED: { RakNet::RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(RakNet::MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" not connected.")); } break; case ID_NAT_TARGET_UNRESPONSIVE: { RakNet::RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(RakNet::MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" unresponsive.")); } break; case ID_NAT_CONNECTION_TO_TARGET_LOST: { RakNet::RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(RakNet::MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target connection to ") + targetName + RakNet::RakString(" lost.")); } break; case ID_NAT_ALREADY_IN_PROGRESS: { RakNet::RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(RakNet::MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT punchthrough to ") + targetName + RakNet::RakString(" in progress (skipping).")); } break; case ID_NAT_PUNCHTHROUGH_SUCCEEDED: { if (packet->data[1]==1) { PushMessage(RakNet::RakString("Connecting to existing game instance")); RakNet::ConnectionAttemptResult car = rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0); RakAssert(car==RakNet::CONNECTION_ATTEMPT_STARTED); } } break; case ID_ADVERTISE_SYSTEM: if (packet->guid!=rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS)) { char hostIP[32]; packet->systemAddress.ToString(false,hostIP); RakNet::ConnectionAttemptResult car = rakPeer->Connect(hostIP,packet->systemAddress.GetPort(),0,0); RakAssert(car==RakNet::CONNECTION_ATTEMPT_STARTED); } break; } } // Call the Update function for networked game objects added to BaseIrrlichtReplica once the game is ready if (currentScene>=1) { unsigned int idx; for (idx=0; idx < replicaManager3->GetReplicaCount(); idx++) ((BaseIrrlichtReplica*)(replicaManager3->GetReplicaAtIndex(idx)))->Update(curTime);; } }
void upnp_service::map_port( uint16_t local_port ) { std::string port = fc::variant(local_port).as_string(); my->map_port_complete = my->upnp_thread.async( [=]() { const char * multicastif = 0; const char * minissdpdpath = 0; struct UPNPDev * devlist = 0; char lanaddr[64]; /* miniupnpc 1.6 */ int error = 0; devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); struct UPNPUrls urls; memset( &urls, 0, sizeof(urls) ); struct IGDdatas data; memset( &data, 0, sizeof(data) ); int r; r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); bool port_mapping_added = false; bool port_mapping_added_successfully = false; if (r == 1) { if (true) // TODO config this ? fDiscover) { char externalIPAddress[40]; r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); if(r != UPNPCOMMAND_SUCCESS) wlog("UPnP: GetExternalIPAddress() returned ${code}", ("code", r)); else { if(externalIPAddress[0]) { ulog("UPnP: ExternalIPAddress = ${address}", ("address", externalIPAddress)); my->external_ip = fc::ip::address( std::string(externalIPAddress) ); // AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); } else wlog("UPnP: GetExternalIPAddress failed."); } } std::string strDesc = "BitShares 0.0"; // TODO + FormatFullVersion(); // try { while(!my->done) // TODO provide way to exit cleanly { /* miniupnpc 1.6 */ r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); port_mapping_added = true; if(r!=UPNPCOMMAND_SUCCESS) wlog("AddPortMapping(${port}, ${port}, ${addr}) failed with code ${code} (${string})", ("port", port)("addr", lanaddr)("code", r)("string", strupnperror(r))); else { if (!port_mapping_added_successfully) ulog("UPnP Port Mapping successful"); port_mapping_added_successfully = true; my->mapped_port = local_port; } fc::usleep( fc::seconds(60*20) ); // Refresh every 20 minutes } } // catch (boost::thread_interrupted) { if( port_mapping_added ) { r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); ilog("UPNP_DeletePortMapping() returned : ${r}", ("r",r)); freeUPNPDevlist(devlist); devlist = 0; FreeUPNPUrls(&urls); } // throw; } } else { //printf("No valid UPnP IGDs found\n"); wlog("No valid UPnP IGDs found"); freeUPNPDevlist(devlist); devlist = 0; if (r != 0) { FreeUPNPUrls(&urls); } } }, "upnp::map_port" ); }
int CUPnPImplMiniLib::CStartDiscoveryThread::Run() { DbgSetThreadName("CUPnPImplMiniLib::CStartDiscoveryThread"); if ( !m_pOwner ) return 0; CSingleLock sLock(&m_pOwner->m_mutBusy); if (!sLock.Lock(0)){ DebugLogWarning(_T("CUPnPImplMiniLib::CStartDiscoveryThread::Run, failed to acquire Lock, another Mapping try might be running already")); return 0; } if (m_pOwner->m_bAbortDiscovery) // requesting to abort ASAP? return 0; UPNPDev* structDeviceList = upnpDiscover(2000, NULL, NULL); if (structDeviceList == NULL){ DebugLog(_T("UPNP: No Internet Gateway Devices found, aborting")); m_pOwner->m_bUPnPPortsForwarded = TRIS_FALSE; m_pOwner->SendResultMessage(); return 0; } if (m_pOwner->m_bAbortDiscovery){ // requesting to abort ASAP? freeUPNPDevlist(structDeviceList); return 0; } DebugLog(_T("List of UPNP devices found on the network:")); for(UPNPDev* pDevice = structDeviceList; pDevice != NULL; pDevice = pDevice->pNext) { DebugLog(_T("Desc: %S, st: %S"), pDevice->descURL, pDevice->st); } m_pOwner->m_pURLs = new UPNPUrls; ZeroMemory(m_pOwner->m_pURLs, sizeof(UPNPUrls)); m_pOwner->m_pIGDData = new IGDdatas; ZeroMemory(m_pOwner->m_pIGDData, sizeof(IGDdatas)); char achLanIP[16]; achLanIP[0] = 0; int iResult = UPNP_GetValidIGD(structDeviceList, m_pOwner->m_pURLs, m_pOwner->m_pIGDData, achLanIP, sizeof(achLanIP)); switch (iResult){ case 1: DebugLog(_T("Found valid IGD : %S"), m_pOwner->m_pURLs->controlURL); break; case 2: DebugLog(_T("Found a (not connected?) IGD : %S - Trying to continue anyway"), m_pOwner->m_pURLs->controlURL); break; case 3: DebugLog(_T("UPnP device found. Is it an IGD ? : %S - Trying to continue anyway"), m_pOwner->m_pURLs->controlURL); break; default: DebugLog(_T("Found device (igd ?) : %S - Trying to continue anyway"), m_pOwner->m_pURLs->controlURL); } freeUPNPDevlist(structDeviceList); DebugLog(_T("Our LAN IP: %S"), achLanIP); if (m_pOwner->m_bAbortDiscovery) // requesting to abort ASAP? return 0; // do we still have old mappings? Remove them first m_pOwner->DeletePorts(true); bool bSucceeded = OpenPort(m_pOwner->m_nTCPPort, true, achLanIP); if (bSucceeded && m_pOwner->m_nUDPPort != 0) bSucceeded = OpenPort(m_pOwner->m_nUDPPort, false, achLanIP); if (!m_pOwner->m_bAbortDiscovery){ // dont send a result on a abort request m_pOwner->m_bUPnPPortsForwarded = bSucceeded ? TRIS_TRUE : TRIS_FALSE; m_pOwner->SendResultMessage(); } return 0; }
// redirect port on external upnp enabled router to port on *this* host int upnpredirect(const char* eport, const char* iport, const char* proto, const char* description) { // Discovery parameters struct UPNPDev * devlist = 0; struct UPNPUrls urls; struct IGDdatas data; int i; char lanaddr[64]; // my ip address on the LAN const char* leaseDuration="0"; // Redirect & test parameters char intClient[40]; char intPort[6]; char externalIPAddress[40]; char duration[16]; int error=0; // Find UPNP devices on the network if ((devlist=upnpDiscover(2000, 0, 0,0, 0, &error))) { struct UPNPDev * device = 0; printf("UPNP INIALISED: List of UPNP devices found on the network.\n"); for(device = devlist; device; device = device->pNext) { printf("UPNP INFO: dev [%s] \n\t st [%s]\n", device->descURL, device->st); } } else { printf("UPNP ERROR: no device found - MANUAL PORTMAP REQUIRED\n"); return 0; } // Output whether we found a good one or not. if((error = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) { switch(error) { case 1: printf("UPNP OK: Found valid IGD : %s\n", urls.controlURL); break; case 2: printf("UPNP WARN: Found a (not connected?) IGD : %s\n", urls.controlURL); break; case 3: printf("UPNP WARN: UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); break; default: printf("UPNP WARN: Found device (igd ?) : %s\n", urls.controlURL); } printf("UPNP OK: Local LAN ip address : %s\n", lanaddr); } else { printf("UPNP ERROR: no device found - MANUAL PORTMAP REQUIRED\n"); return 0; } // Get the external IP address (just because we can really...) if(UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress)!=UPNPCOMMAND_SUCCESS) printf("UPNP WARN: GetExternalIPAddress failed.\n"); else printf("UPNP OK: ExternalIPAddress = %s\n", externalIPAddress); // Check for existing supernet mapping - from this host and another host // In theory I can adapt this so multiple nodes can exist on same lan and choose a different portmap // for each one :) // At the moment just delete a conflicting portmap and override with the one requested. i=0; error=0; do { char index[6]; char extPort[6]; char desc[80]; char enabled[6]; char rHost[64]; char protocol[4]; snprintf(index, 6, "%d", i++); if(!(error=UPNP_GetGenericPortMappingEntry(urls.controlURL, data.first.servicetype, index, extPort, intClient, intPort, protocol, desc, enabled, rHost, duration))) { // printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n",i, protocol, extPort, intClient, intPort,desc, rHost, duration); // check for an existing supernet mapping on this host if(!strcmp(lanaddr, intClient)) { // same host if(!strcmp(protocol,proto)) { //same protocol if(!strcmp(intPort,iport)) { // same port printf("UPNP WARN: existing mapping found (%s:%s)\n",lanaddr,iport); if(!strcmp(extPort,eport)) { printf("UPNP OK: exact mapping already in place (%s:%s->%s)\n", lanaddr, iport, eport); FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return 1; } else { // delete old mapping printf("UPNP WARN: deleting existing mapping (%s:%s->%s)\n",lanaddr, iport, extPort); if(UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, extPort, proto, rHost)) printf("UPNP WARN: error deleting old mapping (%s:%s->%s) continuing\n", lanaddr, iport, extPort); else printf("UPNP OK: old mapping deleted (%s:%s->%s)\n",lanaddr, iport, extPort); } } } } else { // ipaddr different - check to see if requested port is already mapped if(!strcmp(protocol,proto)) { if(!strcmp(extPort,eport)) { printf("UPNP WARN: EXT port conflict mapped to another ip (%s-> %s vs %s)\n", extPort, lanaddr, intClient); if(UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, extPort, proto, rHost)) printf("UPNP WARN: error deleting conflict mapping (%s:%s) continuing\n", intClient, extPort); else printf("UPNP OK: conflict mapping deleted (%s:%s)\n",intClient, extPort); } } } } else printf("UPNP OK: GetGenericPortMappingEntry() End-of-List (%d entries) \n", i); } while(error==0); // Set the requested port mapping if((i=UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport, iport, lanaddr, description, proto, 0, leaseDuration))!=UPNPCOMMAND_SUCCESS) { printf("UPNP ERROR: AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", eport, iport, lanaddr, i, strupnperror(i)); FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return 0; //error - adding the port map primary failure } if((i=UPNP_GetSpecificPortMappingEntry(urls.controlURL, data.first.servicetype, eport, proto, NULL/*remoteHost*/, intClient, intPort, NULL/*desc*/, NULL/*enabled*/, duration))!=UPNPCOMMAND_SUCCESS) { printf("UPNP ERROR: GetSpecificPortMappingEntry(%s, %s, %s) failed with code %d (%s)\n", eport, iport, lanaddr, i, strupnperror(i)); FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return 0; //error - port map wasnt returned by query so likely failed. } else printf("UPNP OK: EXT (%s:%s) %s redirected to INT (%s:%s) (duration=%s)\n",externalIPAddress, eport, proto, intClient, intPort, duration); FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return 1; //ok - we are mapped:) }
static int upnpPulse( ml_upnpmp_t * map ) { int ret; if( map->enabled && ( map->upnpState == ML_UPNP_DISCOVER ) ) { struct UPNPDev * devlist; errno = 0; devlist = upnpDiscover( 2000, NULL, NULL, 0, 0, 0 ); if( devlist == NULL ) { dbg_printf( "upnpDiscover failed (errno %d - %s)\n", errno, str_errno( errno ) ); } errno = 0; if( UPNP_IGD_VALID_CONNECTED == UPNP_GetValidIGD( devlist, &map->upnpUrls, &map->upnpData, map->lanaddr, sizeof( map->lanaddr ) ) ) { dbg_printf( "Found Internet Gateway Device \"%s\" \n", map->upnpUrls.controlURL ); dbg_printf( "Local Address is \"%s\" \n", map->lanaddr ); map->upnpState = ML_UPNP_IDLE; map->upnpDiscovered = 1; } else { map->upnpState = ML_UPNP_ERR; dbg_printf( "UPNP_GetValidIGD failed (errno %d - %s)\n", errno, str_errno( errno ) ); dbg_printf( "If your router supports UPnP, please make sure UPnP is enabled!\n" ); } freeUPNPDevlist( devlist ); } if( map->upnpState == ML_UPNP_IDLE ) { if( map->upnpMapped && ( !map->enabled ) ) map->upnpState = ML_UPNP_UNMAP; } if( map->enabled && map->upnpMapped && map->doPortCheck ) { char portStr[8]; char intPort[8]; char intClient[16]; char type[8]; int i; snprintf( portStr, sizeof( portStr ), "%d", map->extPort ); snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP" ) ); i = UPNP_GetSpecificPortMappingEntry( map->upnpUrls.controlURL, map->upnpData.first.servicetype, portStr, type, #if MINIUPNPC_API_VERSION >= 10 NULL, /* remoteHost */ #endif intClient, intPort, NULL, NULL, NULL ); if( i != UPNPCOMMAND_SUCCESS ) { dbg_printf( "Port %d isn't forwarded\n", map->extPort ); map->upnpMapped = 0; } map->doPortCheck = 0; } if( map->upnpState == ML_UPNP_UNMAP ) { char portStr[16]; char type[8]; snprintf( portStr, sizeof( portStr ), "%d", map->extPort ); snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP" ) ); UPNP_DeletePortMapping( map->upnpUrls.controlURL, map->upnpData.first.servicetype, portStr, type, NULL ); dbg_printf( "Stopping port forwarding through \"%s\", service \"%s\"\n", map->upnpUrls.controlURL, map->upnpData.first.servicetype ); map->upnpMapped = 0; map->upnpState = ML_UPNP_IDLE; map->extPort = 0; } if( map->upnpState == ML_UPNP_IDLE ) { if( map->enabled && !map->upnpMapped ) map->upnpState = ML_UPNP_MAP; } if( map->upnpState == ML_UPNP_MAP ) { int err = -1; errno = 0; if( !map->upnpUrls.controlURL || !map->upnpData.first.servicetype ) map->upnpMapped = 0; else { char intPortStr[16]; char extPortStr[16]; char desc[64]; char type[8]; snprintf( intPortStr, sizeof( intPortStr ), "%d", map->intPort ); snprintf( extPortStr, sizeof( extPortStr ), "%d", map->extPort ); snprintf( desc, sizeof( desc ), "%s", map->notes ); snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP" ) ); err = UPNP_AddPortMapping( map->upnpUrls.controlURL, map->upnpData.first.servicetype, extPortStr, intPortStr, map->lanaddr, desc, type, NULL, "0" ); map->upnpMapped = !err; } dbg_printf( "Port forwarding through \"%s\", service \"%s\". (local address[%s:%d])\n", map->upnpUrls.controlURL, map->upnpData.first.servicetype, map->lanaddr, map->intPort ); if( map->upnpMapped ) { dbg_printf( "Port forwarding successful!\n" ); //handle->port = port; map->upnpState = ML_UPNP_IDLE; } else { dbg_printf( "Port forwarding failed with error %d (errno %d - %s)\n", err, errno, str_errno( errno ) ); dbg_printf( "If your router supports UPnP, please make sure UPnP is enabled!\n" ); //handle->port = -1; map->upnpState = ML_UPNP_ERR; } } switch( map->upnpState ) { case ML_UPNP_DISCOVER: ret = ML_PORT_UNMAPPED; break; case ML_UPNP_MAP: ret = ML_PORT_MAPPING; break; case ML_UPNP_UNMAP: ret = ML_PORT_UNMAPPING; break; case ML_UPNP_IDLE: ret = map->upnpMapped ? ML_PORT_MAPPED : ML_PORT_UNMAPPED; break; default: ret = ML_PORT_ERROR; break; } return ret; }
int xshl5_redirect_remove(const char* ext_port_and_protocols[], int num, int ipv6, const char* interface_or_ipaddr) { int retcode = -1; struct UPNPDev * devlist = 0; const char * multicastif = interface_or_ipaddr; const char * minissdpdpath = 0; char lanaddr[64]; /* my ip address on the LAN */ int error = 0, i = 0; if(num <= 0) return retcode; if( (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error))) { struct UPNPDev * device; struct UPNPUrls urls; struct IGDdatas data; if(devlist) { printf("List of UPNP devices found on the network :\n"); for(device = devlist; device; device = device->pNext) { printf(" desc: %s\n st: %s\n\n", device->descURL, device->st); } } else { printf("upnpDiscover() error code=%d\n", error); } i = 1; if( (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))) ) { switch(i) { case 1: printf("Found valid IGD : %s\n", urls.controlURL); break; case 2: printf("Found a (not connected?) IGD : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; case 3: printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; default: printf("Found device (igd ?) : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); } printf("Local LAN ip address : %s\n", lanaddr); for(i=0; i<num; i+=2) { if(ext_port_and_protocols[i] == NULL || ext_port_and_protocols[i+1] == NULL) { retcode = -2; break; } RemoveRedirect(&urls, &data, ext_port_and_protocols[i], strcmp(ext_port_and_protocols[i+1], "udp")==0? "udp": "tcp"); } retcode = 0; FreeUPNPUrls(&urls); } else { fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); retcode = 1; } freeUPNPDevlist(devlist); devlist = 0; } else { fprintf(stderr, "No IGD UPnP Device found on the network !\n"); retcode = 1; } return retcode; }
int xshl5_redirect(unsigned short pri_port, unsigned short ext_port, const char* pri_ip, const char* protocol, int ipv6, const char* interface_or_ipaddr, const char* description, /*out*/char* ext_ipaddr) { int retcode = -1; struct UPNPDev * devlist = 0; const char * multicastif = interface_or_ipaddr; const char * minissdpdpath = 0; char lanaddr[64]; /* my ip address on the LAN */ int error = 0, i = 0; char used_protocol[16] = "tcp"; char used_ipaddr[32] = {0}; char used_pri_port[8] = {0}; char used_ext_port[8] = {0}; // used_pri_port sprintf(used_pri_port, "%u", pri_port); // used_ext_port if(ext_port == 0) sprintf(used_ext_port, "%u", pri_port); else sprintf(used_ext_port, "%u", ext_port); // used_protocol if(protocol != NULL && (protocol[0]=='u'&&protocol[1]=='d'&&protocol[2]=='p') ) { strncpy(used_protocol, protocol, 3); } if( (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error))) { struct UPNPDev * device; struct UPNPUrls urls; struct IGDdatas data; if(devlist) { printf("List of UPNP devices found on the network :\n"); for(device = devlist; device; device = device->pNext) { printf(" desc: %s\n st: %s\n\n", device->descURL, device->st); } } else { printf("upnpDiscover() error code=%d\n", error); } i = 1; if( (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))) ) { switch(i) { case 1: printf("Found valid IGD : %s\n", urls.controlURL); break; case 2: printf("Found a (not connected?) IGD : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; case 3: printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; default: printf("Found device (igd ?) : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); } printf("Local LAN ip address : %s\n", lanaddr); // used_ipaddr if(pri_ip == NULL) strcpy(used_ipaddr, lanaddr); else strcpy(used_ipaddr, pri_ip); SetRedirectAndTest(&urls, &data, used_ipaddr, used_pri_port, used_ext_port, used_protocol, "0", description, 0, ext_ipaddr); retcode = 0; /* case 'a': SetRedirectAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3], (commandargc > 4)?commandargv[4]:"0", description, 0); break; case 'd': for(i=0; i<commandargc; i+=2) { RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]); } break; */ FreeUPNPUrls(&urls); } else { fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); retcode = 1; } freeUPNPDevlist(devlist); devlist = 0; } else { fprintf(stderr, "No IGD UPnP Device found on the network !\n"); retcode = 1; } return retcode; }
bool UPnP::start() { int error = 0; UPNPDev *devlist = ::upnpDiscover(2000, NULL, NULL, FALSE, FALSE, &error); UPNPDev *devlistBegin = devlist; // get interface list /*foreach(interface, interfaces) { newdevlist = ::upnpDiscover(2000, interface, NULL, FALSE, FALSE, &error); // go to end of list and append }*/ while (devlist) { UPNPUrls urls; IGDdatas data; char lanaddr[64]; UPnPHash resultHash; int code = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); if (code > 0) // TODO maybe distinguish between the return codes (1,2,3) to add information what happend to the result { resultHash.insert(LanIpAddress, QLatin1String(lanaddr)); char externalIP[40]; if (UPNPCOMMAND_SUCCESS == UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP)) { resultHash.insert(ExternalIpAddress, QLatin1String(externalIP)); } char connectionType[64]; if (UPNPCOMMAND_SUCCESS == UPNP_GetConnectionTypeInfo(urls.controlURL, data.first.servicetype, connectionType)) { resultHash.insert(ConnectionType, QLatin1String(connectionType)); } quint32 uplink, downlink; if (UPNPCOMMAND_SUCCESS == UPNP_GetLinkLayerMaxBitRates(urls.controlURL_CIF, data.CIF.servicetype, &downlink, &uplink)) { resultHash.insert(LinkLayerMaxDownload, downlink); resultHash.insert(LinkLayerMaxUpload, uplink); } quint32 bytesSent, bytesReceived, packetsSent, packetsReceived; bytesSent = UPNP_GetTotalBytesSent(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != bytesSent) { resultHash.insert(TotalBytesSent, bytesSent); } bytesReceived = UPNP_GetTotalBytesReceived(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != bytesReceived) { resultHash.insert(TotalBytesReceived, bytesReceived); } packetsSent = UPNP_GetTotalPacketsSent(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != packetsSent) { resultHash.insert(TotalPacketsSent, packetsSent); } packetsReceived = UPNP_GetTotalPacketsReceived(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != packetsReceived) { resultHash.insert(TotalPacketsReceived, packetsReceived); } char status[100]; unsigned int uptime = 0; char lastConnectionError[128]; if (UPNPCOMMAND_SUCCESS == UPNP_GetStatusInfo(urls.controlURL, data.first.servicetype, status, &uptime, lastConnectionError)) { resultHash.insert(Status, status); resultHash.insert(Uptime, uptime); resultHash.insert(LastConnectionError, lastConnectionError); } quint32 num; if (UPNPCOMMAND_SUCCESS == UPNP_GetPortMappingNumberOfEntries(urls.controlURL, data.first.servicetype, &num)) { resultHash.insert(NumberOfPortMappings, num); } // TODO GetListOfPortMappings do we need this? int firewallEnabled, inboundPinholeAllowed; if (UPNPCOMMAND_SUCCESS == UPNP_GetFirewallStatus(urls.controlURL, data.first.servicetype, &firewallEnabled, &inboundPinholeAllowed)) { resultHash.insert(FirewallEnabled, firewallEnabled); resultHash.insert(InboundPinholeAllowed, inboundPinholeAllowed); } int bufferSize = 0; if (char *buffer = (char *)miniwget(urls.rootdescURL, &bufferSize, 0)) { NameValueParserData pdata; ParseNameValue(buffer, bufferSize, &pdata); free(buffer); buffer = NULL; QStringList modelName = GetValuesFromNameValueList(&pdata, "modelName"); if (!modelName.isEmpty()) { resultHash.insert(ModelName, modelName.last()); } QStringList manufacturer = GetValuesFromNameValueList(&pdata, "manufacturer"); if (!manufacturer.isEmpty()) { resultHash.insert(Manufacturer, manufacturer.last()); } QStringList friendlyName = GetValuesFromNameValueList(&pdata, "friendlyName"); if (!friendlyName.isEmpty()) { resultHash.insert(FriendlyName, friendlyName.last()); } ClearNameValueList(&pdata); } } FreeUPNPUrls(&urls); results.append(resultHash); devlist = devlist->pNext; } freeUPNPDevlist(devlistBegin); emit finished(); return true; // TODO return false if something went wrong or if there are no results }
int upnpPulse(upnp * handle, int port, int proto, char isEnabled, int doPortCheck, const char* name) { if(isEnabled && (handle->state == UPNP_DISCOVER)) { struct UPNPDev * devlist; devlist = upnpDiscover(200, NULL, NULL, 0); if(UPNP_GetValidIGD(devlist, &handle->urls, &handle->data, handle->lanaddr, sizeof(handle->lanaddr )) == UPNP_IGD_VALID_CONNECTED) { //qDebug() << QString("Found Internet Gateway Device \"%1\"").arg(QString(handle->urls.controlURL)); //qDebug() << QString("Local Address is \"%1\"").arg(QString(handle->lanaddr)); handle->state = UPNP_IDLE; handle->hasDiscovered = 1; } else { handle->state = UPNP_ERR; //qDebug() << QString("UPNP_GetValidIGD failed"); } freeUPNPDevlist(devlist); } if(handle->state == UPNP_IDLE) { if(handle->isMapped && (!isEnabled || handle->port != port)) handle->state = UPNP_UNMAP; } char* protoStr = ""; switch(proto) { case PORT_TCP: protoStr = "TCP"; break; case PORT_UDP: protoStr = "UDP"; break; } if(isEnabled && handle->isMapped && doPortCheck) { char portStr[8]; char intPort[8]; char intClient[16]; snprintf(portStr, sizeof(portStr), "%d", handle->port); if(UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, handle->data.first.servicetype, portStr, protoStr, intClient, intPort ) != UPNPCOMMAND_SUCCESS) { //qDebug() << QString("Port %1 isn't forwarded").arg(handle->port); handle->isMapped = 0; } } if( handle->state == UPNP_UNMAP ) { char portStr[16]; snprintf(portStr, sizeof(portStr), "%d", handle->port); UPNP_DeletePortMapping(handle->urls.controlURL, handle->data.first.servicetype, portStr, protoStr, NULL); //qDebug() << QString("Stopping port forwarding through \"%1\", service \"%1\"").arg(QString(handle->urls.controlURL)).arg(QString(handle->data.first.servicetype)); handle->isMapped = 0; handle->state = UPNP_IDLE; handle->port = -1; } if(handle->state == UPNP_IDLE) { if(isEnabled && !handle->isMapped) handle->state = UPNP_MAP; } if(handle->state == UPNP_MAP) { int err = -1; if(!handle->urls.controlURL || !handle->data.first.servicetype) handle->isMapped = 0; else { char portStr[16]; char desc[64]; snprintf(portStr, sizeof(portStr), "%d", port); snprintf(desc, sizeof(desc), "%s at %d", name, port); err = UPNP_AddPortMapping(handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, protoStr, NULL); //if(err) // qDebug() << QString("%1 Port forwarding failed with error %2").arg(QString(protoStr)).arg(err); handle->isMapped = !err; } //qDebug() << QString("Port forwarding through \"%1\", service \"%2\". (local address: %3:%4)") // .arg(QString(handle->urls.controlURL)).arg(QString(handle->data.first.servicetype)).arg(QString(handle->lanaddr)).arg(port); if(handle->isMapped) { //qDebug() << QString("Port forwarding successful!"); handle->port = port; handle->state = UPNP_IDLE; } else { //qDebug() << QString("If your router supports UPnP, please make sure UPnP is enabled!"); handle->port = -1; handle->state = UPNP_ERR; } } switch( handle->state ) { case UPNP_DISCOVER: return PORT_UNMAPPED; case UPNP_MAP: return PORT_MAPPING; case UPNP_UNMAP: return PORT_UNMAPPING; case UPNP_IDLE: return handle->isMapped ? PORT_MAPPED : PORT_UNMAPPED; default: return PORT_ERROR; } }
int tr_upnpPulse( tr_upnp * handle, int port, int isEnabled, int doPortCheck ) { int ret; if( isEnabled && ( handle->state == TR_UPNP_DISCOVER ) ) { struct UPNPDev * devlist; errno = 0; devlist = upnpDiscover( 2000, NULL, NULL, 0 ); if( devlist == NULL ) { tr_ndbg( getKey( ), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror( errno ) ); } errno = 0; if( UPNP_GetValidIGD( devlist, &handle->urls, &handle->data, handle->lanaddr, sizeof( handle->lanaddr ) ) == UPNP_IGD_VALID_CONNECTED ) { tr_ninf( getKey( ), _( "Found Internet Gateway Device \"%s\"" ), handle->urls.controlURL ); tr_ninf( getKey( ), _( "Local Address is \"%s\"" ), handle->lanaddr ); handle->state = TR_UPNP_IDLE; handle->hasDiscovered = 1; } else { handle->state = TR_UPNP_ERR; tr_ndbg( getKey( ), "UPNP_GetValidIGD failed (errno %d - %s)", errno, tr_strerror( errno ) ); tr_ndbg( getKey( ), "If your router supports UPnP, please make sure UPnP is enabled!" ); } freeUPNPDevlist( devlist ); } if( handle->state == TR_UPNP_IDLE ) { if( handle->isMapped && ( !isEnabled || ( handle->port != port ) ) ) handle->state = TR_UPNP_UNMAP; } if( isEnabled && handle->isMapped && doPortCheck ) { char portStr[8]; char intPort[8]; char intClient[16]; tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port ); if( UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, handle->data.first.servicetype, portStr, "TCP", intClient, intPort ) != UPNPCOMMAND_SUCCESS || UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, handle->data.first.servicetype, portStr, "UDP", intClient, intPort ) != UPNPCOMMAND_SUCCESS ) { tr_ninf( getKey( ), _( "Port %d isn't forwarded" ), handle->port ); handle->isMapped = FALSE; } } if( handle->state == TR_UPNP_UNMAP ) { char portStr[16]; tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port ); UPNP_DeletePortMapping( handle->urls.controlURL, handle->data.first.servicetype, portStr, "TCP", NULL ); UPNP_DeletePortMapping( handle->urls.controlURL, handle->data.first.servicetype, portStr, "UDP", NULL ); tr_ninf( getKey( ), _( "Stopping port forwarding through \"%s\", service \"%s\"" ), handle->urls.controlURL, handle->data.first.servicetype ); handle->isMapped = 0; handle->state = TR_UPNP_IDLE; handle->port = -1; } if( handle->state == TR_UPNP_IDLE ) { if( isEnabled && !handle->isMapped ) handle->state = TR_UPNP_MAP; } if( handle->state == TR_UPNP_MAP ) { int err_tcp = -1; int err_udp = -1; errno = 0; if( !handle->urls.controlURL || !handle->data.first.servicetype ) handle->isMapped = 0; else { char portStr[16]; char desc[64]; const int prev_errno = errno; tr_snprintf( portStr, sizeof( portStr ), "%d", port ); tr_snprintf( desc, sizeof( desc ), "%s at %d", TR_NAME, port ); errno = 0; err_tcp = UPNP_AddPortMapping( handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, "TCP", NULL ); if( err_tcp ) tr_ndbg( getKey( ), "TCP Port forwarding failed with error %d (errno %d - %s)", err_tcp, errno, tr_strerror( errno ) ); errno = 0; err_udp = UPNP_AddPortMapping( handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, "UDP", NULL ); if( err_udp ) tr_ndbg( getKey( ), "UDP Port forwarding failed with error %d (errno %d - %s)", err_udp, errno, tr_strerror( errno ) ); errno = prev_errno; handle->isMapped = !err_tcp | !err_udp; } tr_ninf( getKey( ), _( "Port forwarding through \"%s\", service \"%s\". (local address: %s:%d)" ), handle->urls.controlURL, handle->data.first.servicetype, handle->lanaddr, port ); if( handle->isMapped ) { tr_ninf( getKey( ), "%s", _( "Port forwarding successful!" ) ); handle->port = port; handle->state = TR_UPNP_IDLE; } else { tr_ndbg( getKey( ), "If your router supports UPnP, please make sure UPnP is enabled!" ); handle->port = -1; handle->state = TR_UPNP_ERR; } } switch( handle->state ) { case TR_UPNP_DISCOVER: ret = TR_PORT_UNMAPPED; break; case TR_UPNP_MAP: ret = TR_PORT_MAPPING; break; case TR_UPNP_UNMAP: ret = TR_PORT_UNMAPPING; break; case TR_UPNP_IDLE: ret = handle->isMapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED; break; default: ret = TR_PORT_ERROR; break; } return ret; }
void* CNetServerWorker::SetupUPnP(void*) { // Values we want to set. char psPort[6]; sprintf_s(psPort, ARRAY_SIZE(psPort), "%d", PS_DEFAULT_PORT); const char* leaseDuration = "0"; // Indefinite/permanent lease duration. const char* description = "0AD Multiplayer"; const char* protocall = "UDP"; char internalIPAddress[64]; char externalIPAddress[40]; // Variables to hold the values that actually get set. char intClient[40]; char intPort[6]; char duration[16]; // Intermediate variables. struct UPNPUrls urls; struct IGDdatas data; struct UPNPDev* devlist = NULL; // Cached root descriptor URL. std::string rootDescURL; CFG_GET_VAL("network.upnprootdescurl", rootDescURL); if (!rootDescURL.empty()) LOGMESSAGE("Net server: attempting to use cached root descriptor URL: %s", rootDescURL.c_str()); int ret = 0; bool allocatedUrls = false; // Try a cached URL first if (!rootDescURL.empty() && UPNP_GetIGDFromUrl(rootDescURL.c_str(), &urls, &data, internalIPAddress, sizeof(internalIPAddress))) { LOGMESSAGE("Net server: using cached IGD = %s", urls.controlURL); ret = 1; } // No cached URL, or it did not respond. Try getting a valid UPnP device for 10 seconds. else if ((devlist = upnpDiscover(10000, 0, 0, 0, 0, 0)) != NULL) { ret = UPNP_GetValidIGD(devlist, &urls, &data, internalIPAddress, sizeof(internalIPAddress)); allocatedUrls = ret != 0; // urls is allocated on non-zero return values } else { LOGMESSAGE("Net server: upnpDiscover failed and no working cached URL."); return NULL; } switch (ret) { case 0: LOGMESSAGE("Net server: No IGD found"); break; case 1: LOGMESSAGE("Net server: found valid IGD = %s", urls.controlURL); break; case 2: LOGMESSAGE("Net server: found a valid, not connected IGD = %s, will try to continue anyway", urls.controlURL); break; case 3: LOGMESSAGE("Net server: found a UPnP device unrecognized as IGD = %s, will try to continue anyway", urls.controlURL); break; default: debug_warn(L"Unrecognized return value from UPNP_GetValidIGD"); } // Try getting our external/internet facing IP. TODO: Display this on the game-setup page for conviniance. ret = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); if (ret != UPNPCOMMAND_SUCCESS) { LOGMESSAGE("Net server: GetExternalIPAddress failed with code %d (%s)", ret, strupnperror(ret)); return NULL; } LOGMESSAGE("Net server: ExternalIPAddress = %s", externalIPAddress); // Try to setup port forwarding. ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, psPort, psPort, internalIPAddress, description, protocall, 0, leaseDuration); if (ret != UPNPCOMMAND_SUCCESS) { LOGMESSAGE("Net server: AddPortMapping(%s, %s, %s) failed with code %d (%s)", psPort, psPort, internalIPAddress, ret, strupnperror(ret)); return NULL; } // Check that the port was actually forwarded. ret = UPNP_GetSpecificPortMappingEntry(urls.controlURL, data.first.servicetype, psPort, protocall, #if defined(MINIUPNPC_API_VERSION) && MINIUPNPC_API_VERSION >= 10 NULL/*remoteHost*/, #endif intClient, intPort, NULL/*desc*/, NULL/*enabled*/, duration); if (ret != UPNPCOMMAND_SUCCESS) { LOGMESSAGE("Net server: GetSpecificPortMappingEntry() failed with code %d (%s)", ret, strupnperror(ret)); return NULL; } LOGMESSAGE("Net server: External %s:%s %s is redirected to internal %s:%s (duration=%s)", externalIPAddress, psPort, protocall, intClient, intPort, duration); // Cache root descriptor URL to try to avoid discovery next time. g_ConfigDB.SetValueString(CFG_USER, "network.upnprootdescurl", urls.controlURL); g_ConfigDB.WriteFile(CFG_USER); LOGMESSAGE("Net server: cached UPnP root descriptor URL as %s", urls.controlURL); // Make sure everything is properly freed. if (allocatedUrls) FreeUPNPUrls(&urls); freeUPNPDevlist(devlist); return NULL; }
int CUPnPImplMiniLib::CStartDiscoveryThread::Run() { DbgSetThreadName("CUPnPImplMiniLib::CStartDiscoveryThread"); if ( !m_pOwner ) return 0; CSingleLock sLock(&m_pOwner->m_mutBusy); if (!sLock.Lock(0)){ DebugLogWarning(_T("CUPnPImplMiniLib::CStartDiscoveryThread::Run, failed to acquire Lock, another Mapping try might be running already")); return 0; } if (m_pOwner->m_bAbortDiscovery) // requesting to abort ASAP? return 0; bool bSucceeded = false; #if !(defined(_DEBUG) || defined(_BETA)) try #endif { if (!m_pOwner->m_bCheckAndRefresh) { UPNPDev* structDeviceList = upnpDiscover(2000, NULL, NULL, NULL); if (structDeviceList == NULL){ DebugLog(_T("UPNP: No Internet Gateway Devices found, aborting")); m_pOwner->m_bUPnPPortsForwarded = TRIS_FALSE; m_pOwner->SendResultMessage(); return 0; } if (m_pOwner->m_bAbortDiscovery){ // requesting to abort ASAP? freeUPNPDevlist(structDeviceList); return 0; } DebugLog(_T("List of UPNP devices found on the network:")); for(UPNPDev* pDevice = structDeviceList; pDevice != NULL; pDevice = pDevice->pNext) { DebugLog(_T("Desc: %S, st: %S"), pDevice->descURL, pDevice->st); } m_pOwner->m_pURLs = new UPNPUrls; ZeroMemory(m_pOwner->m_pURLs, sizeof(UPNPUrls)); m_pOwner->m_pIGDData = new IGDdatas; ZeroMemory(m_pOwner->m_pIGDData, sizeof(IGDdatas)); m_pOwner->m_achLanIP[0] = 0; int iResult = UPNP_GetValidIGD(structDeviceList, m_pOwner->m_pURLs, m_pOwner->m_pIGDData, m_pOwner->m_achLanIP, sizeof(m_pOwner->m_achLanIP)); freeUPNPDevlist(structDeviceList); bool bNotFound = false; switch (iResult){ case 1: DebugLog(_T("Found valid IGD : %S"), m_pOwner->m_pURLs->controlURL); break; case 2: DebugLog(_T("Found a (not connected?) IGD : %S - Trying to continue anyway"), m_pOwner->m_pURLs->controlURL); break; case 3: DebugLog(_T("UPnP device found. Is it an IGD ? : %S - Trying to continue anyway"), m_pOwner->m_pURLs->controlURL); break; default: DebugLog(_T("Found device (igd ?) : %S - Aborting"), m_pOwner->m_pURLs->controlURL != NULL ? m_pOwner->m_pURLs->controlURL : "(none)"); bNotFound = true; } if (bNotFound || m_pOwner->m_pURLs->controlURL == NULL) { m_pOwner->m_bUPnPPortsForwarded = TRIS_FALSE; m_pOwner->SendResultMessage(); return 0; } DebugLog(_T("Our LAN IP: %S"), m_pOwner->m_achLanIP); if (m_pOwner->m_bAbortDiscovery) // requesting to abort ASAP? return 0; // do we still have old mappings? Remove them first m_pOwner->DeletePorts(true); } bSucceeded = OpenPort(m_pOwner->m_nTCPPort, true, m_pOwner->m_achLanIP, m_pOwner->m_bCheckAndRefresh); if (bSucceeded && m_pOwner->m_nUDPPort != 0) bSucceeded = OpenPort(m_pOwner->m_nUDPPort, false, m_pOwner->m_achLanIP, m_pOwner->m_bCheckAndRefresh); if (bSucceeded && m_pOwner->m_nTCPWebPort != 0) OpenPort(m_pOwner->m_nTCPWebPort, true, m_pOwner->m_achLanIP, m_pOwner->m_bCheckAndRefresh); // don't fail if only the webinterface port fails for some reason } #if !(defined(_DEBUG) || defined(_BETA)) catch(...) { DebugLogError(_T("Unknown Exception in CUPnPImplMiniLib::CStartDiscoveryThread::Run()")); } #endif if (!m_pOwner->m_bAbortDiscovery){ // dont send a result on a abort request m_pOwner->m_bUPnPPortsForwarded = bSucceeded ? TRIS_TRUE : TRIS_FALSE; m_pOwner->m_bSucceededOnce |= bSucceeded; m_pOwner->SendResultMessage(); } return 0; }
int upnp_handler( struct upnp_handle_t *handle, unsigned short port, time_t lifespan, time_t now ) { struct UPNPDev * devlist; /* Retry later if we want to wait longer */ if( handle->retry > now ) { return PF_RETRY; } #ifdef DEBUG log_debug( "UPnP: Handle port: %hu, lifespan: %ld, state: %s", port, lifespan, upnp_statestr( handle->state ) ); #endif /* Get gateway address */ if( handle->state == UPNP_STATE_DISCOVER_GATEWAY ) { #if (MINIUPNPC_API_VERSION <= 5) devlist = upnpDiscover( 1000, NULL, NULL, 0 ); if( devlist == NULL ) { #else int err = UPNPDISCOVER_SUCCESS; devlist = upnpDiscover( 1000, NULL, NULL, 0, 0, &err ); if( err != UPNPDISCOVER_SUCCESS ) { #endif log_debug( "UPnP: Method upnpDiscover failed." ); handle->retry = now + (10 * 60); handle->state = UPNP_STATE_DISCOVER_GATEWAY; return PF_RETRY; } else if( UPNP_GetValidIGD( devlist, &handle->urls, &handle->data, handle->addr, sizeof(handle->addr) ) == 1 ) { freeUPNPDevlist( devlist ); log_info( "UPnP: Found gateway device \"%s\".", handle->urls.controlURL ); handle->state = UPNP_STATE_GET_PORTMAPPING; return PF_RETRY; } else { freeUPNPDevlist( devlist ); goto error; } } if( handle->state == UPNP_STATE_GET_PORTMAPPING ) { if( lifespan == 0 ) { /* Remove port forwarding */ int rc_tcp = upnpDeletePortMapping( handle, "TCP", port ); int rc_udp = upnpDeletePortMapping( handle, "UDP", port ); if( rc_tcp == UPNPCOMMAND_SUCCESS && rc_udp == UPNPCOMMAND_SUCCESS ) { log_debug( "UPnP: Removed port forwarding for local port %d through \"%s\".", port, handle->urls.controlURL ); handle->state = UPNP_STATE_GET_PORTMAPPING; return PF_DONE; } else { log_debug( "UPnP: Removing port mapping failed." ); goto error; } } else { /* Check port forwarding */ int rc_tcp = upnpGetSpecificPortMappingEntry( handle, "TCP", port ); int rc_udp = upnpGetSpecificPortMappingEntry( handle, "UDP", port ); if( rc_tcp == UPNPCOMMAND_SUCCESS && rc_udp == UPNPCOMMAND_SUCCESS ) { log_debug( "UPnP: Port forwarding for local port %d already exists.", port ); handle->state = UPNP_STATE_GET_PORTMAPPING; return PF_DONE; } else { log_debug( "UPnP: Port %d isn't forwarded.", port ); handle->state = UPNP_STATE_ADD_PORTMAPPING; return PF_RETRY; } } } /* Add port forwarding */ if( handle->state == UPNP_STATE_ADD_PORTMAPPING ) { if ( handle->urls.controlURL && handle->data.first.servicetype ) { int rc_tcp = upnpAddPortMapping( handle, "TCP", port ); int rc_udp = upnpAddPortMapping( handle, "UDP", port ); if( rc_tcp == UPNPCOMMAND_SUCCESS && rc_udp == UPNPCOMMAND_SUCCESS ) { log_info( "UPnP: Port %d through \"%s\" forwarded to local address %s:%d.", port, handle->urls.controlURL, handle->addr, port ); handle->state = UPNP_STATE_GET_PORTMAPPING; return PF_DONE; } else { log_debug( "UPnP: Port forwarding of port %d failed.", port ); goto error; } } else { goto error; } } error:; handle->retry = now + 60; handle->state = UPNP_STATE_ERROR; return PF_ERROR; }
/* sample upnp client program */ int main(int argc, char ** argv) { char command = 0; char ** commandargv = 0; int commandargc = 0; struct UPNPDev * devlist = 0; char lanaddr[64]; /* my ip address on the LAN */ int i; const char * rootdescurl = 0; const char * multicastif = 0; const char * minissdpdpath = 0; int retcode = 0; #ifdef WIN32 WSADATA wsaData; int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(nResult != NO_ERROR) { fprintf(stderr, "WSAStartup() failed.\n"); return -1; } #endif printf("upnpc : miniupnpc library test client. (c) 2006-2010 Thomas Bernard\n"); printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" "for more information.\n"); /* command line processing */ for(i=1; i<argc; i++) { if(argv[i][0] == '-') { if(argv[i][1] == 'u') rootdescurl = argv[++i]; else if(argv[i][1] == 'm') multicastif = argv[++i]; else if(argv[i][1] == 'p') minissdpdpath = argv[++i]; else { command = argv[i][1]; i++; commandargv = argv + i; commandargc = argc - i; break; } } else { fprintf(stderr, "option '%s' invalid\n", argv[i]); } } if(!command || (command == 'a' && commandargc<4) || (command == 'd' && argc<2) || (command == 'r' && argc<2)) { fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol\n\t\tAdd port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); fprintf(stderr, "\nprotocol is UDP or TCP\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); fprintf(stderr, " -m address : provide ip address of the interface to use for sending SSDP multicast packets.\n"); fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); return 1; } if( rootdescurl || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0))) { struct UPNPDev * device; struct UPNPUrls urls; struct IGDdatas data; if(devlist) { printf("List of UPNP devices found on the network :\n"); for(device = devlist; device; device = device->pNext) { printf(" desc: %s\n st: %s\n\n", device->descURL, device->st); } } i = 1; if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) { switch(i) { case 1: printf("Found valid IGD : %s\n", urls.controlURL); break; case 2: printf("Found a (not connected?) IGD : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; case 3: printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); break; default: printf("Found device (igd ?) : %s\n", urls.controlURL); printf("Trying to continue anyway\n"); } printf("Local LAN ip address : %s\n", lanaddr); #if 0 printf("getting \"%s\"\n", urls.ipcondescURL); descXML = miniwget(urls.ipcondescURL, &descXMLsize); if(descXML) { /*fwrite(descXML, 1, descXMLsize, stdout);*/ free(descXML); descXML = NULL; } #endif switch(command) { case 'l': DisplayInfos(&urls, &data); ListRedirections(&urls, &data); break; case 'a': SetRedirectAndTest(&urls, &data, commandargv[0], commandargv[1], commandargv[2], commandargv[3]); break; case 'd': for(i=0; i<commandargc; i+=2) { RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]); } break; case 's': GetConnectionStatus(&urls, &data); break; case 'r': for(i=0; i<commandargc; i+=2) { /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/ SetRedirectAndTest(&urls, &data, lanaddr, commandargv[i], commandargv[i], commandargv[i+1]); } break; default: fprintf(stderr, "Unknown switch -%c\n", command); retcode = 1; } FreeUPNPUrls(&urls); } else { fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); retcode = 1; } freeUPNPDevlist(devlist); devlist = 0; } else { fprintf(stderr, "No IGD UPnP Device found on the network !\n"); retcode = 1; } return retcode; }