static PyObject * UPnP_discover(UPnPObject *self) { struct UPNPDev * dev; int i; PyObject *res = NULL; if(self->devlist) { freeUPNPDevlist(self->devlist); self->devlist = 0; } Py_BEGIN_ALLOW_THREADS self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/, 0/* multicast if*/, 0/*minissdpd socket*/, 0/*sameport flag*/, 0/*ip v6*/, 0/*error */); Py_END_ALLOW_THREADS /* Py_RETURN_NONE ??? */ for(dev = self->devlist, i = 0; dev; dev = dev->pNext) i++; res = Py_BuildValue("i", i); return res; }
static void UPnPObject_dealloc(UPnPObject *self) { freeUPNPDevlist(self->devlist); FreeUPNPUrls(&self->urls); self->ob_type->tp_free((PyObject*)self); }
static int init_upnp(void) { struct UPNPDev *devlist; struct UPNPDev *dev = NULL; struct UPNPDev *trydev = NULL; char *descXML; int descXMLsize = 0; const char *multicastif = 0; const char *minissdpdpath = 0; memset(&nat_globals.urls, 0, sizeof(struct UPNPUrls)); memset(&nat_globals.data, 0, sizeof(struct IGDdatas)); devlist = upnpDiscover(3000, multicastif, minissdpdpath, 0); if (devlist) { dev = devlist; while (dev) { if (strstr(dev->st, "InternetGatewayDevice")) { break; } if (!trydev && !switch_stristr("printer", dev->descURL)) { trydev = dev; } dev = dev->pNext; } } if (!dev && trydev) { dev = trydev; /* defaulting to first device */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No InternetGatewayDevice, using first entry as default (%s).\n", dev->descURL); } else if (devlist && !dev && !trydev) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No InternetGatewayDevice found and I am NOT going to try your printer because printers should not route to the internet, that would be DAFT\n"); } if (dev) { descXML = miniwget(dev->descURL, &descXMLsize); nat_globals.descURL = strdup(dev->descURL); if (descXML) { parserootdesc(descXML, descXMLsize, &nat_globals.data); free(descXML); descXML = 0; GetUPNPUrls(&nat_globals.urls, &nat_globals.data, dev->descURL); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to retrieve device description XML (%s).\n", dev->descURL); } freeUPNPDevlist(devlist); } if (get_upnp_pubaddr(nat_globals.pub_addr) == SWITCH_STATUS_SUCCESS) { nat_globals.nat_type = SWITCH_NAT_TYPE_UPNP; return 0; } return -2; }
// MiniUPNP bool UPNPCheckDlg::MiniUPnPc_init(string& url, string& service, string& device) { bool initialized = false; UPNPDev* devices = upnpDiscover(2000, SettingsManager::getInstance()->isDefault(SettingsManager::BIND_ADDRESS) ? nullptr : SETTING(BIND_ADDRESS).c_str(), 0, 0, 0, 0); if (!devices) return false; UPNPUrls urls = {0}; IGDdatas data = {0}; auto res = UPNP_GetValidIGD(devices, &urls, &data, 0, 0); initialized = res == 1; if (initialized) { url = urls.controlURL; service = data.first.servicetype; device = data.CIF.friendlyName; device += '(' + data.CIF.modelDescription + ')'; // [+]PPA TODO - fix cope-paste } if (res) { FreeUPNPUrls(&urls); freeUPNPDevlist(devices); } return initialized; }
bool Mapper_MiniUPnPc::init() { if(!url.empty()) return true; UPNPDev* devices = upnpDiscover(2000, localIp.empty() ? nullptr : localIp.c_str(), 0, 0, 0, 0); if(!devices) return false; UPNPUrls urls; IGDdatas data; auto ret = UPNP_GetValidIGD(devices, &urls, &data, 0, 0); bool ok = ret == 1; if(ok) { url = urls.controlURL; service = data.first.servicetype; device = data.CIF.friendlyName; } if(ret) { FreeUPNPUrls(&urls); freeUPNPDevlist(devices); } return ok; }
// called from ---UPnP--- thread // discovers the IGD bool NetPlayServer::initUPnP() { UPNPDev *devlist; std::vector<UPNPDev *> igds; int descXMLsize = 0, upnperror = 0; char *descXML; // Don't init if already inited if (m_upnp_inited) return true; // Don't init if it failed before if (m_upnp_error) return false; memset(&m_upnp_urls, 0, sizeof(UPNPUrls)); memset(&m_upnp_data, 0, sizeof(IGDdatas)); // Find all UPnP devices devlist = upnpDiscover(2000, NULL, NULL, 0, 0, &upnperror); if (!devlist) { WARN_LOG(NETPLAY, "An error occured trying to discover UPnP devices."); m_upnp_error = true; m_upnp_inited = false; return false; } // Look for the IGD for (UPNPDev* dev = devlist; dev; dev = dev->pNext) { if (strstr(dev->st, "InternetGatewayDevice")) igds.push_back(dev); } for (const UPNPDev* dev : igds) { descXML = (char *) miniwget(dev->descURL, &descXMLsize, 0); if (descXML) { parserootdesc(descXML, descXMLsize, &m_upnp_data); free(descXML); descXML = 0; GetUPNPUrls(&m_upnp_urls, &m_upnp_data, dev->descURL, 0); NOTICE_LOG(NETPLAY, "Got info from IGD at %s.", dev->descURL); break; } else { WARN_LOG(NETPLAY, "Error getting info from IGD at %s.", dev->descURL); } } freeUPNPDevlist(devlist); return true; }
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; }
bool Mapper_MiniUPnPc::init() { if(!url.empty()) return true; #if MINIUPNPC_API_VERSION < 14 UPNPDev* devices = upnpDiscover(2000, localIp.empty() ? nullptr : localIp.c_str(), 0, 0, v6, 0); #else UPNPDev* devices = upnpDiscover(2000, localIp.empty() ? nullptr : localIp.c_str(), 0, 0, v6, 2, 0); #endif if(!devices) return false; UPNPUrls urls; IGDdatas data; auto ret = UPNP_GetValidIGD(devices, &urls, &data, 0, 0); bool ok = ret == 1; if(ok) { if (localIp.empty()) { // We have no bind address configured in settings // Try to avoid choosing a random adapter for port mapping // Parse router IP from the control URL address auto controlUrl = string(string(data.urlbase).empty() ? urls.controlURL : data.urlbase); string routerIp, portTmp, protoTmp, pathTmp, queryTmp, fragmentTmp; Util::decodeUrl(controlUrl, protoTmp, routerIp, portTmp, pathTmp, queryTmp, fragmentTmp); routerIp = Socket::resolve(routerIp, v6 ? AF_INET6 : AF_INET); if (!routerIp.empty()) { auto adapters = AirUtil::getNetworkAdapters(v6); // Find a local IP that is within the same subnet auto p = boost::find_if(adapters, [&routerIp, this](const AirUtil::AdapterInfo& aInfo) { return isIPInRange(aInfo.ip, routerIp, aInfo.prefix, v6); }); if (p != adapters.end()) { localIp = p->ip; } } } url = urls.controlURL; service = data.first.servicetype; #ifdef _WIN32 device = data.CIF.friendlyName; #else // Doesn't work on Linux device = "Generic"; #endif } if(ret) { FreeUPNPUrls(&urls); freeUPNPDevlist(devices); } return ok; }
C4Network2UPnPP::~C4Network2UPnPP() { ClearMappings(); action.wait(); ProcessEvents(); // necessary for logging FreeUPNPUrls(&upnp_urls); freeUPNPDevlist(devlist); }
bool Mapper_MiniUPnPc::init() { if(!url.empty()) return true; #ifdef HAVE_OLD_MINIUPNPC UPNPDev* devices = upnpDiscover(2000, localIp.empty() ? nullptr : localIp.c_str(), 0, 0); #else UPNPDev* devices = upnpDiscover(2000, localIp.empty() ? nullptr : localIp.c_str(), 0, 0, v6, 0); #endif if(!devices) return false; UPNPUrls urls; IGDdatas data; auto ret = UPNP_GetValidIGD(devices, &urls, &data, 0, 0); bool ok = ret == 1; if(ok) { if (localIp.empty()) { AirUtil::IpList addresses; AirUtil::getIpAddresses(addresses, v6); auto remoteIP = string(string(data.urlbase).empty() ? urls.controlURL : data.urlbase); auto start = remoteIP.find("//"); if (start != string::npos) { start = start+2; auto end = remoteIP.find(":", start); if (end != string::npos) { remoteIP = Socket::resolve(remoteIP.substr(start, end-start), v6 ? AF_INET6 : AF_INET); if (!remoteIP.empty()) { auto p = boost::find_if(addresses, [&remoteIP, this](const AirUtil::AddressInfo& aInfo) { return isIPInRange(aInfo.ip, remoteIP, aInfo.prefix, v6); }); if (p != addresses.end()) { localIp = p->ip; } } } } } url = urls.controlURL; service = data.first.servicetype; #ifdef _WIN32 device = data.CIF.friendlyName; #else // Doesn't work on Linux device = "Generic"; #endif } if(ret) { FreeUPNPUrls(&urls); freeUPNPDevlist(devices); } return ok; }
static void UPnPObject_dealloc(UPnPObject *self) { freeUPNPDevlist(self->devlist); FreeUPNPUrls(&self->urls); free(self->multicastif); free(self->minissdpdsocket); Py_TYPE(self)->tp_free((PyObject*)self); }
bool Portfwd::init(unsigned int timeout) { #ifdef WIN32 WSADATA wsaData; int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(nResult != NO_ERROR) { fprintf(stderr, "WSAStartup() failed.\n"); return -1; } #endif struct UPNPDev * devlist; struct UPNPDev * dev; char * descXML; int descXMLsize = 0; printf("Portfwd::init()\n"); urls = (UPNPUrls*)malloc(sizeof(struct UPNPUrls)); data = (IGDdatas*)malloc(sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); memset(data, 0, sizeof(struct IGDdatas)); devlist = upnpDiscover(timeout, NULL, NULL, 0); if (devlist) { dev = devlist; while (dev) { if (strstr (dev->st, "InternetGatewayDevice")) break; dev = dev->pNext; } if (!dev) dev = devlist; /* defaulting to first device */ printf("UPnP device :\n" " desc: %s\n st: %s\n", dev->descURL, dev->st); descXML = (char*)miniwget(dev->descURL, &descXMLsize); if (descXML) { parserootdesc (descXML, descXMLsize, data); free (descXML); descXML = 0; GetUPNPUrls (urls, data, dev->descURL); } // get lan IP: char lanaddr[16]; int i; i = UPNP_GetValidIGD(devlist, urls, data, (char*)&lanaddr, 16); m_lanip = std::string(lanaddr); freeUPNPDevlist(devlist); get_status(); return true; } return false; }
bool Gateway::_getGatewayInfo() { int error; bool ret = true; char lanaddr[64]; struct UPNPDev *devlist = NULL; devlist = upnpDiscover(2000, 0, 0, 0, 0, &error); if (devlist == NULL) ret = false; else if (UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)) != 1) { ret = false; } freeUPNPDevlist(devlist); return ret; }
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")); } }
/** 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; }
int TearDown(void) { if(g_urls) { free(g_urls); g_urls = NULL; } if(g_data) { free(g_data); g_data = NULL; } if(g_devlist) { freeUPNPDevlist(g_devlist); g_devlist = NULL; } return 0; }
void natt_init(void) { #ifndef HAVE_SOCKET_LEGACY #if HAVE_MINIUPNPC struct UPNPDev * devlist; struct UPNPDev * dev; char * descXML; int descXMLsize = 0; int upnperror = 0; memset(&urls, 0, sizeof(struct UPNPUrls)); memset(&data, 0, sizeof(struct IGDdatas)); devlist = upnpDiscover(2000, NULL, NULL, 0, 0, 2, &upnperror); if (devlist) { dev = devlist; while (dev) { if (strstr (dev->st, "InternetGatewayDevice")) break; dev = dev->pNext; } if (!dev) dev = devlist; descXML = (char *) miniwget(dev->descURL, &descXMLsize, 0, NULL); if (descXML) { parserootdesc(descXML, descXMLsize, &data); free (descXML); descXML = 0; GetUPNPUrls (&urls, &data, dev->descURL, 0); } freeUPNPDevlist(devlist); } #endif #endif }
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; }
int main(int argc, char * * argv) { const char * searched_device = NULL; const char * * searched_devices = NULL; const char * multicastif = 0; const char * minissdpdpath = 0; int ipv6 = 0; int error = 0; struct UPNPDev * devlist = 0; struct UPNPDev * dev; int i; #ifdef _WIN32 WSADATA wsaData; int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); if(nResult != NO_ERROR) { fprintf(stderr, "WSAStartup() failed.\n"); return -1; } #endif for(i = 1; i < argc; i++) { if(strcmp(argv[i], "-6") == 0) ipv6 = 1; else if(strcmp(argv[i], "-d") == 0) { if(++i >= argc) { fprintf(stderr, "-d option needs one argument\n"); return 1; } searched_device = argv[i]; } else if(strcmp(argv[i], "-l") == 0) { if(++i >= argc) { fprintf(stderr, "-l option needs at least one argument\n"); return 1; } searched_devices = (const char * *)(argv + i); break; } else if(strcmp(argv[i], "-m") == 0) { if(++i >= argc) { fprintf(stderr, "-m option needs one argument\n"); return 1; } multicastif = argv[i]; } else { printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]); printf("options :\n"); printf(" -6 : use IPv6\n"); printf(" -m address/ifname : network interface to use for multicast\n"); printf(" -d <device string> : search only for this type of device\n"); printf(" -l <device1> <device2> ... : search only for theses types of device\n"); printf(" -h : this help\n"); return 1; } } if(searched_device) { printf("searching UPnP device type %s\n", searched_device); devlist = upnpDiscoverDevice(searched_device, 2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error); } else if(searched_devices) { printf("searching UPnP device types :\n"); for(i = 0; searched_devices[i]; i++) printf("\t%s\n", searched_devices[i]); devlist = upnpDiscoverDevices(searched_devices, 2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error, 1); } else { printf("searching all UPnP devices\n"); devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath, 0/*sameport*/, ipv6, &error); } if(devlist) { for(dev = devlist; dev != NULL; dev = dev->pNext) { printf("%-48s\t%s\n", dev->st, dev->descURL); } freeUPNPDevlist(devlist); } else { printf("no device found.\n"); } return 0; }
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 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 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; }
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; }
/** * 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; }
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; }
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" ); }
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; }
MiniUPnPInterface::~MiniUPnPInterface() { if (p->isValid) { FreeUPNPUrls(&p->urls); } freeUPNPDevlist(p->deviceList); }