void tr_upnpClose (tr_upnp * handle) { assert (!handle->isMapped); assert ((handle->state == TR_UPNP_IDLE) || (handle->state == TR_UPNP_ERR) || (handle->state == TR_UPNP_DISCOVER)); if (handle->hasDiscovered) FreeUPNPUrls (&handle->urls); tr_free (handle); }
/** Tear down the UPnP connection stored in <b>backend_state</b>.*/ int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state) { miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; assert(options); if (state->init) FreeUPNPUrls(&(state->urls)); state->init = 0; return UPNP_ERR_SUCCESS; }
static void clean_upnp_data (VinoUpnp *upnp) { if (upnp->priv->urls) { FreeUPNPUrls (upnp->priv->urls); g_free (upnp->priv->urls); upnp->priv->urls = NULL; } if (upnp->priv->data) { g_free (upnp->priv->data); upnp->priv->data = NULL; } }
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool) { /* try free dynamic data structures prior to resetting to 0 */ FreeUPNPUrls(&nat_globals.urls); switch_safe_free(nat_globals.descURL); memset(&nat_globals, 0, sizeof(nat_globals)); if (first_init) { memset(&nat_globals_perm, 0, sizeof(nat_globals_perm)); nat_globals_perm.pool = pool; } switch_find_local_ip(nat_globals.pvt_addr, sizeof(nat_globals.pvt_addr), NULL, AF_INET); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Scanning for NAT\n"); init_pmp(); if (!nat_globals.nat_type) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for UPnP\n"); init_upnp(); } if (nat_globals.nat_type) { switch_core_set_variable("nat_public_addr", nat_globals.pub_addr); switch_core_set_variable("nat_private_addr", nat_globals.pvt_addr); switch_core_set_variable("nat_type", nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "pmp" : "upnp"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "NAT detected type: %s, ExtIP: '%s'\n", nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "pmp" : "upnp", nat_globals.pub_addr); if (!nat_thread_p) { switch_nat_thread_start(); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "No PMP or UPnP NAT devices detected!\n"); } first_init = SWITCH_FALSE; initialized = SWITCH_TRUE; }
int test_igd_desc_parse(char * buffer, int len) { struct IGDdatas igd; struct xmlparser parser; struct UPNPUrls urls; memset(&igd, 0, sizeof(struct IGDdatas)); memset(&parser, 0, sizeof(struct xmlparser)); parser.xmlstart = buffer; parser.xmlsize = len; parser.data = &igd; parser.starteltfunc = IGDstartelt; parser.endeltfunc = IGDendelt; parser.datafunc = IGDdata; parsexml(&parser); printIGD(&igd); GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); printf("ipcondescURL='%s'\n", urls.ipcondescURL); printf("controlURL='%s'\n", urls.controlURL); printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); FreeUPNPUrls(&urls); return 0; }
void CUPnPImplMiniLib::StartDiscovery(uint16 nTCPPort, uint16 nUDPPort){ DebugLog(_T("Using MiniUPnPLib based implementation")); DebugLog(_T("miniupnpc (c) 2006-2008 Thomas Bernard - http://miniupnp.free.fr/")); m_nOldUDPPort = (ArePortsForwarded() == TRIS_TRUE) ? m_nUDPPort : 0; m_nUDPPort = nUDPPort; m_nOldTCPPort = (ArePortsForwarded() == TRIS_TRUE) ? m_nTCPPort : 0; m_nTCPPort = nTCPPort; m_bUPnPPortsForwarded = TRIS_UNKNOWN; if (m_pURLs != NULL) FreeUPNPUrls(m_pURLs); delete m_pURLs; m_pURLs = NULL; delete m_pIGDData; m_pIGDData = NULL; if (m_bAbortDiscovery) return; CStartDiscoveryThread* pStartDiscoveryThread = (CStartDiscoveryThread*) AfxBeginThread(RUNTIME_CLASS(CStartDiscoveryThread), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED); m_hThreadHandle = pStartDiscoveryThread->m_hThread; pStartDiscoveryThread->SetValues(this); pStartDiscoveryThread->ResumeThread(); }
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 }
/* UPNP_GetValidIGDe) : * return values : * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { struct xml_desc { char * xml; int size; int is_igd; } * desc = NULL; struct UPNPDev * dev; int ndev = 0; int i; int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ int n_igd = 0; char extIpAddr[16]; struct UPNPDevInfo IGDInfo; char *dut_lanaddr; char IGDDescURL[256]; if(!devlist) { #ifdef DEBUG printf("Empty devlist\n"); #endif return 0; } /* counting total number of devices in the list */ for(dev = devlist; dev; dev = dev->pNext) ndev++; if(ndev > 0) { desc = calloc(ndev, sizeof(struct xml_desc)); if(!desc) return -1; /* memory allocation error */ } dut_lanaddr = get_lan_ipaddr(); /* Step 1 : downloading descriptions and testing type */ for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { memset(&IGDInfo, 0, sizeof(struct UPNPDevInfo)); /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ strcpy(IGDDescURL, dev->descURL); desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), lanaddr, lanaddrlen, dev->scope_id, &IGDInfo, dut_lanaddr); #ifdef DEBUG if(!desc[i].xml) { printf("error getting XML description %s\n", dev->descURL); } #endif if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); /* parserootdesc(desc[i].xml, desc[i].size, data); */ #ifdef DEBUG FILE *xml_fd; xml_fd = fopen("/tmp/upnpc_xml.log", "w"); fprintf(xml_fd, "============= XML ==============\n"); fprintf(xml_fd, "%s\n", desc[i].xml); parsedescxml(desc[i].xml, &IGDInfo.friendlyName, &IGDInfo.iconUrl); fprintf(xml_fd, " HostName: %s\n", IGDInfo.hostname); fprintf(xml_fd, " type: %s\n", IGDInfo.type); fprintf(xml_fd, " F Name: %s\n", IGDInfo.friendlyName); fprintf(xml_fd, " Icon URL: %s\n", IGDInfo.iconUrl); fprintf(xml_fd, "================================\n\n"); syslog(LOG_NOTICE, "parse icon url: %s", IGDInfo.iconUrl); #endif strcpy(dev->DevInfo.hostname, IGDInfo.hostname); strcpy(dev->DevInfo.type, IGDInfo.type); strcpy(dev->DevInfo.friendlyName, IGDInfo.friendlyName); strcpy(dev->DevInfo.iconUrl, IGDInfo.iconUrl); #ifdef RTCONFIG_JFFS2USERICON if(strcmp(IGDInfo.iconUrl, "") != NULL) { char realIconUrl[158], iconFile[32], iconBuf[512]; char *ico_head, *ico_end; char *icon, *p, *q; int iconSize, i = 0, iconCheck = 0; FILE *ico_fd; memset(realIconUrl, 0, 158); if(strstr(IGDInfo.iconUrl, "http://")) { strcpy(realIconUrl, IGDInfo.iconUrl); } else { q = IGDDescURL; while(q = strchr(q, '/')) { i++; if(i == 3) { p = IGDDescURL; i = 0; while ( p < q ) { realIconUrl[i++] = *p++; } strcat(realIconUrl, IGDInfo.iconUrl); #ifdef DEBUG printf("\n*** Real URL=%s=\n\n", realIconUrl); #endif break; } q++; } } get_icon: #ifdef DEBUG syslog(LOG_NOTICE, "Real icon url: %s", realIconUrl); fprintf(xml_fd, "Real icon url: %s\n", realIconUrl); #endif sprintf(iconFile, "/tmp/upnpicon/%s.ico", IGDInfo.hostname); icon = miniwget_getaddr(realIconUrl, &iconSize, lanaddr, lanaddrlen, 0, &IGDInfo, dut_lanaddr); if( iconSize > 512 ) { ico_fd = fopen(iconFile, "w"); if(ico_fd) { fwrite(icon, sizeof(char), iconSize, ico_fd); fclose(ico_fd); } } else if(iconSize > 0) { ico_head = strstr(icon, "<a href="); if(ico_head) { ico_head = ico_head+9; ico_end = strstr(icon, "\">"); if(ico_end) { *ico_end = '\0'; strcpy(realIconUrl, ico_head); goto get_icon; } } } } #endif if(COMPARE(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { desc[i].is_igd = 1; n_igd++; } #ifdef DEBUG fclose(xml_fd); #endif } else memset(dev->DevInfo.hostname, 0, 65); } /* iterate the list to find a device depending on state */ for(state = 1; state <= 3; state++) /*if(0)*/ { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(desc[i].is_igd || state >= 3 ) { GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); /* in state 2 and 3 we dont test if device is connected ! */ if(state >= 2) goto free_and_return; #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif /* checks that status is connected AND there is a external IP address assigned */ if(UPNPIGD_IsConnected(urls, data) && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) goto free_and_return; FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG printf("We tried %s, now we try %s !\n", data->first.servicetype, data->second.servicetype); #endif /* swaping WANPPPConnection and WANIPConnection ! */ memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif if(UPNPIGD_IsConnected(urls, data) && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) goto free_and_return; FreeUPNPUrls(urls); } } memset(data, 0, sizeof(struct IGDdatas)); } } } state = 0; free_and_return: if(desc) { for(i = 0; i < ndev; i++) { if(desc[i].xml) { free(desc[i].xml); } } free(desc); } return state; }
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; }
static void I_ShutdownUPnP(void) { FreeUPNPUrls(&urls); }
MiniUPnPInterface::~MiniUPnPInterface() { if (p->isValid) { FreeUPNPUrls(&p->urls); } freeUPNPDevlist(p->deviceList); }
// 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:) }
/* UPNP_GetValidIGD() : * return values : * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { char * descXML; int descXMLsize = 0; struct UPNPDev * dev; int ndev = 0; int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ if(!devlist) { #ifdef DEBUG printf("Empty devlist\n"); #endif return 0; } for(state = 1; state <= 3; state++) { for(dev = devlist; dev; dev = dev->pNext) { /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ descXML = miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, lanaddrlen); if(descXML) { ndev++; memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; if(0==strcmp(data->servicetype_CIF, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") || state >= 3 ) { GetUPNPUrls(urls, data, dev->descURL); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif if((state >= 2) || UPNPIGD_IsConnected(urls, data)) return state; FreeUPNPUrls(urls); } memset(data, 0, sizeof(struct IGDdatas)); } #ifdef DEBUG else { printf("error getting XML description %s\n", dev->descURL); } #endif } } return 0; }
/* 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; }
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" ); }
SWITCH_DECLARE(void) switch_nat_shutdown(void) { switch_nat_thread_stop(); FreeUPNPUrls(&nat_globals.urls); switch_safe_free(nat_globals.descURL); }
Gateway::~Gateway() { FreeUPNPUrls(&urls); }
void UPnP::Close () { freeUPNPDevlist (m_Devlist); m_Devlist = 0; FreeUPNPUrls (&m_upnpUrls); }
~MiniUPnPWrapper() { FreeUPNPUrls(upnpurls); delete upnpurls; delete igddatas; }
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; }
/* UPNP_GetValidIGD() : * return values : * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to * free allocated memory. */ MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { struct xml_desc { char * xml; int size; int is_igd; } * desc = NULL; struct UPNPDev * dev; int ndev = 0; int i; int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ char extIpAddr[16]; char myLanAddr[40]; int status_code = -1; if(!devlist) { #ifdef DEBUG printf("Empty devlist\n"); #endif return 0; } /* counting total number of devices in the list */ for(dev = devlist; dev; dev = dev->pNext) ndev++; /* ndev is always > 0 */ desc = calloc(ndev, sizeof(struct xml_desc)); if(!desc) return -1; /* memory allocation error */ /* Step 1 : downloading descriptions and testing type */ for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), myLanAddr, sizeof(myLanAddr), dev->scope_id, &status_code); #ifdef DEBUG if(!desc[i].xml) { printf("error getting XML description %s\n", dev->descURL); } #endif if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(COMPARE(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { desc[i].is_igd = 1; if(lanaddr) strncpy(lanaddr, myLanAddr, lanaddrlen); } } } /* iterate the list to find a device depending on state */ for(state = 1; state <= 3; state++) { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(desc[i].is_igd || state >= 3 ) { int is_connected; GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); /* in state 2 and 3 we don't test if device is connected ! */ if(state >= 2) goto free_and_return; is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif /* checks that status is connected AND there is a external IP address assigned */ if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') && (0 != strcmp(extIpAddr, "0.0.0.0"))) goto free_and_return; } FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG printf("We tried %s, now we try %s !\n", data->first.servicetype, data->second.servicetype); #endif /* swaping WANPPPConnection and WANIPConnection ! */ memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') && (0 != strcmp(extIpAddr, "0.0.0.0"))) goto free_and_return; } FreeUPNPUrls(urls); } } memset(data, 0, sizeof(struct IGDdatas)); } } } state = 0; free_and_return: for(i = 0; i < ndev; i++) free(desc[i].xml); free(desc); return state; }
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; }
/* UPNP_GetValidIGD() : * return values : * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { struct xml_desc { char * xml; int size; } * desc = NULL; struct UPNPDev * dev; int ndev = 0; int i; int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ if(!devlist) { #ifdef DEBUG printf("Empty devlist\n"); #endif return 0; } for(dev = devlist; dev; dev = dev->pNext) ndev++; if(ndev > 0) { desc = calloc(ndev, sizeof(struct xml_desc)); if(!desc) return -1; /* memory allocation error */ } for(state = 1; state <= 3; state++) { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { /* we should choose an internet gateway device. * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ if(state == 1) { desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), lanaddr, lanaddrlen, dev->scope_id); #ifdef DEBUG if(!desc[i].xml) { printf("error getting XML description %s\n", dev->descURL); } #endif } if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); if(0==strcmp(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") || state >= 3 ) { GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif if((state >= 2) || UPNPIGD_IsConnected(urls, data)) goto free_and_return; FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG printf("We tried %s, now we try %s !\n", data->first.servicetype, data->second.servicetype); #endif /* swaping WANPPPConnection and WANIPConnection ! */ memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif if((state >= 2) || UPNPIGD_IsConnected(urls, data)) goto free_and_return; FreeUPNPUrls(urls); } } memset(data, 0, sizeof(struct IGDdatas)); } } } state = 0; free_and_return: if(desc) { for(i = 0; i < ndev; i++) { if(desc[i].xml) { free(desc[i].xml); } } free(desc); } return state; }
/* 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; }