Path: blob/master/thirdparty/miniupnpc/src/upnpcommands.c
9904 views
/* $Id: upnpcommands.c,v 1.56 2025/03/29 18:08:59 nanard Exp $ */1/* vim: tabstop=4 shiftwidth=4 noexpandtab2* Project : miniupnp3* Author : Thomas Bernard4* Copyright (c) 2005-2025 Thomas Bernard5* This software is subject to the conditions detailed in the6* LICENCE file provided in this distribution.7* */8#include <stdlib.h>9#include <stdio.h>10#include <string.h>11#include "upnpcommands.h"12#include "miniupnpc.h"13#include "portlistingparse.h"14#include "upnpreplyparse.h"1516/*! \file upnpcommands.c17* \brief Internet Gateway Device methods implementations18* \def STRTOUI19* \brief strtoull() if available, strtol() if not20*/21#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L22#define STRTOUI strtoull23#else24#define STRTOUI strtoul25#endif2627static UNSIGNED_INTEGER28my_atoui(const char * s)29{30return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;31}3233/*34* */35MINIUPNP_LIBSPEC UNSIGNED_INTEGER36UPNP_GetTotalBytesSent(const char * controlURL,37const char * servicetype)38{39struct NameValueParserData pdata;40char * buffer;41int bufsize;42unsigned int r = 0;43char * p;44if(!(buffer = simpleUPnPcommand(controlURL, servicetype,45"GetTotalBytesSent", 0, &bufsize))) {46return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;47}48ParseNameValue(buffer, bufsize, &pdata);49/*DisplayNameValueList(buffer, bufsize);*/50free(buffer);51p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");52r = my_atoui(p);53ClearNameValueList(&pdata);54return r;55}5657/*58* */59MINIUPNP_LIBSPEC UNSIGNED_INTEGER60UPNP_GetTotalBytesReceived(const char * controlURL,61const char * servicetype)62{63struct NameValueParserData pdata;64char * buffer;65int bufsize;66unsigned int r = 0;67char * p;68if(!(buffer = simpleUPnPcommand(controlURL, servicetype,69"GetTotalBytesReceived", 0, &bufsize))) {70return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;71}72ParseNameValue(buffer, bufsize, &pdata);73/*DisplayNameValueList(buffer, bufsize);*/74free(buffer);75p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");76r = my_atoui(p);77ClearNameValueList(&pdata);78return r;79}8081/*82* */83MINIUPNP_LIBSPEC UNSIGNED_INTEGER84UPNP_GetTotalPacketsSent(const char * controlURL,85const char * servicetype)86{87struct NameValueParserData pdata;88char * buffer;89int bufsize;90unsigned int r = 0;91char * p;92if(!(buffer = simpleUPnPcommand(controlURL, servicetype,93"GetTotalPacketsSent", 0, &bufsize))) {94return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;95}96ParseNameValue(buffer, bufsize, &pdata);97/*DisplayNameValueList(buffer, bufsize);*/98free(buffer);99p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");100r = my_atoui(p);101ClearNameValueList(&pdata);102return r;103}104105/*106* */107MINIUPNP_LIBSPEC UNSIGNED_INTEGER108UPNP_GetTotalPacketsReceived(const char * controlURL,109const char * servicetype)110{111struct NameValueParserData pdata;112char * buffer;113int bufsize;114unsigned int r = 0;115char * p;116if(!(buffer = simpleUPnPcommand(controlURL, servicetype,117"GetTotalPacketsReceived", 0, &bufsize))) {118return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;119}120ParseNameValue(buffer, bufsize, &pdata);121/*DisplayNameValueList(buffer, bufsize);*/122free(buffer);123p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");124r = my_atoui(p);125ClearNameValueList(&pdata);126return r;127}128129/* UPNP_GetStatusInfo() call the corresponding UPNP method130* returns the current status and uptime */131MINIUPNP_LIBSPEC int132UPNP_GetStatusInfo(const char * controlURL,133const char * servicetype,134char * status,135unsigned int * uptime,136char * lastconnerror)137{138struct NameValueParserData pdata;139char * buffer;140int bufsize;141char * p;142char * up;143char * err;144int ret = UPNPCOMMAND_UNKNOWN_ERROR;145146if(!status && !uptime)147return UPNPCOMMAND_INVALID_ARGS;148149if(!(buffer = simpleUPnPcommand(controlURL, servicetype,150"GetStatusInfo", 0, &bufsize))) {151return UPNPCOMMAND_HTTP_ERROR;152}153ParseNameValue(buffer, bufsize, &pdata);154/*DisplayNameValueList(buffer, bufsize);*/155free(buffer);156up = GetValueFromNameValueList(&pdata, "NewUptime");157p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");158err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");159if(p && up)160ret = UPNPCOMMAND_SUCCESS;161162if(status) {163if(p){164strncpy(status, p, 64 );165status[63] = '\0';166}else167status[0]= '\0';168}169170if(uptime) {171if(!up || sscanf(up,"%u",uptime) != 1)172*uptime = 0;173}174175if(lastconnerror) {176if(err) {177strncpy(lastconnerror, err, 64 );178lastconnerror[63] = '\0';179} else180lastconnerror[0] = '\0';181}182183p = GetValueFromNameValueList(&pdata, "errorCode");184if(p) {185if(sscanf(p, "%d", &ret) != 1)186ret = UPNPCOMMAND_UNKNOWN_ERROR;187}188ClearNameValueList(&pdata);189return ret;190}191192/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method193* returns the connection type */194MINIUPNP_LIBSPEC int195UPNP_GetConnectionTypeInfo(const char * controlURL,196const char * servicetype,197char * connectionType)198{199struct NameValueParserData pdata;200char * buffer;201int bufsize;202char * p;203int ret = UPNPCOMMAND_UNKNOWN_ERROR;204205if(!connectionType)206return UPNPCOMMAND_INVALID_ARGS;207208if(!(buffer = simpleUPnPcommand(controlURL, servicetype,209"GetConnectionTypeInfo", 0, &bufsize))) {210return UPNPCOMMAND_HTTP_ERROR;211}212ParseNameValue(buffer, bufsize, &pdata);213free(buffer);214p = GetValueFromNameValueList(&pdata, "NewConnectionType");215/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/216/* PossibleConnectionTypes will have several values.... */217if(p) {218strncpy(connectionType, p, 64 );219connectionType[63] = '\0';220ret = UPNPCOMMAND_SUCCESS;221} else222connectionType[0] = '\0';223p = GetValueFromNameValueList(&pdata, "errorCode");224if(p) {225if(sscanf(p, "%d", &ret) != 1)226ret = UPNPCOMMAND_UNKNOWN_ERROR;227}228ClearNameValueList(&pdata);229return ret;230}231232/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.233* Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.234* One of the values can be null235* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only236* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */237MINIUPNP_LIBSPEC int238UPNP_GetLinkLayerMaxBitRates(const char * controlURL,239const char * servicetype,240unsigned int * bitrateDown,241unsigned int * bitrateUp)242{243struct NameValueParserData pdata;244char * buffer;245int bufsize;246int ret = UPNPCOMMAND_UNKNOWN_ERROR;247char * down;248char * up;249char * p;250251if(!bitrateDown && !bitrateUp)252return UPNPCOMMAND_INVALID_ARGS;253254/* shouldn't we use GetCommonLinkProperties ? */255if(!(buffer = simpleUPnPcommand(controlURL, servicetype,256"GetCommonLinkProperties", 0, &bufsize))) {257/*"GetLinkLayerMaxBitRates", 0, &bufsize);*/258return UPNPCOMMAND_HTTP_ERROR;259}260/*DisplayNameValueList(buffer, bufsize);*/261ParseNameValue(buffer, bufsize, &pdata);262free(buffer);263/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/264/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/265down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");266up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");267/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/268/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/269if(down && up)270ret = UPNPCOMMAND_SUCCESS;271272if(bitrateDown) {273if(!down || sscanf(down,"%u",bitrateDown) != 1)274*bitrateDown = 0;275}276277if(bitrateUp) {278if(!up || sscanf(up,"%u",bitrateUp) != 1)279*bitrateUp = 0;280}281p = GetValueFromNameValueList(&pdata, "errorCode");282if(p) {283if(sscanf(p, "%d", &ret) != 1)284ret = UPNPCOMMAND_UNKNOWN_ERROR;285}286ClearNameValueList(&pdata);287return ret;288}289290291/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.292* if the third arg is not null the value is copied to it.293* at least 16 bytes must be available294*295* Return values :296* 0 : SUCCESS297* NON ZERO : ERROR Either an UPnP error code or an unknown error.298*299* 402 Invalid Args - See UPnP Device Architecture section on Control.300* 501 Action Failed - See UPnP Device Architecture section on Control.301*/302MINIUPNP_LIBSPEC int303UPNP_GetExternalIPAddress(const char * controlURL,304const char * servicetype,305char * extIpAdd)306{307struct NameValueParserData pdata;308char * buffer;309int bufsize;310char * p;311int ret = UPNPCOMMAND_UNKNOWN_ERROR;312313if(!extIpAdd || !controlURL || !servicetype)314return UPNPCOMMAND_INVALID_ARGS;315316if(!(buffer = simpleUPnPcommand(controlURL, servicetype,317"GetExternalIPAddress", 0, &bufsize))) {318return UPNPCOMMAND_HTTP_ERROR;319}320/*DisplayNameValueList(buffer, bufsize);*/321ParseNameValue(buffer, bufsize, &pdata);322free(buffer);323/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/324p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");325if(p) {326strncpy(extIpAdd, p, 16 );327extIpAdd[15] = '\0';328ret = UPNPCOMMAND_SUCCESS;329} else330extIpAdd[0] = '\0';331332p = GetValueFromNameValueList(&pdata, "errorCode");333if(p) {334if(sscanf(p, "%d", &ret) != 1)335ret = UPNPCOMMAND_UNKNOWN_ERROR;336}337338ClearNameValueList(&pdata);339return ret;340}341342MINIUPNP_LIBSPEC int343UPNP_AddPortMapping(const char * controlURL, const char * servicetype,344const char * extPort,345const char * inPort,346const char * inClient,347const char * desc,348const char * proto,349const char * remoteHost,350const char * leaseDuration)351{352struct UPNParg AddPortMappingArgs[] = {353{"NewRemoteHost", remoteHost},354{"NewExternalPort", extPort},355{"NewProtocol", proto},356{"NewInternalPort", inPort},357{"NewInternalClient", inClient},358{"NewEnabled", "1"},359{"NewPortMappingDescription", desc?desc:"libminiupnpc"},360{"NewLeaseDuration", leaseDuration?leaseDuration:"0"},361{NULL, NULL}362};363char * buffer;364int bufsize;365struct NameValueParserData pdata;366const char * resVal;367int ret;368369if(!inPort || !inClient || !proto || !extPort)370return UPNPCOMMAND_INVALID_ARGS;371372buffer = simpleUPnPcommand(controlURL, servicetype,373"AddPortMapping", AddPortMappingArgs,374&bufsize);375if(!buffer) {376return UPNPCOMMAND_HTTP_ERROR;377}378/*DisplayNameValueList(buffer, bufsize);*/379/*buffer[bufsize] = '\0';*/380/*puts(buffer);*/381ParseNameValue(buffer, bufsize, &pdata);382free(buffer);383resVal = GetValueFromNameValueList(&pdata, "errorCode");384if(resVal) {385/*printf("AddPortMapping errorCode = '%s'\n", resVal); */386if(sscanf(resVal, "%d", &ret) != 1)387ret = UPNPCOMMAND_UNKNOWN_ERROR;388} else {389ret = UPNPCOMMAND_SUCCESS;390}391ClearNameValueList(&pdata);392return ret;393}394395MINIUPNP_LIBSPEC int396UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,397const char * extPort,398const char * inPort,399const char * inClient,400const char * desc,401const char * proto,402const char * remoteHost,403const char * leaseDuration,404char * reservedPort)405{406struct UPNParg AddAnyPortMappingArgs[] = {407{"NewRemoteHost", remoteHost},408{"NewExternalPort", extPort},409{"NewProtocol", proto},410{"NewInternalPort", inPort},411{"NewInternalClient", inClient},412{"NewEnabled", "1"},413{"NewPortMappingDescription", desc?desc:"libminiupnpc"},414{"NewLeaseDuration", leaseDuration?leaseDuration:"0"},415{NULL, NULL}416};417char * buffer;418int bufsize;419struct NameValueParserData pdata;420const char * resVal;421int ret;422423if(!inPort || !inClient || !proto || !extPort || !reservedPort)424return UPNPCOMMAND_INVALID_ARGS;425buffer = simpleUPnPcommand(controlURL, servicetype,426"AddAnyPortMapping", AddAnyPortMappingArgs,427&bufsize);428if(!buffer) {429return UPNPCOMMAND_HTTP_ERROR;430}431ParseNameValue(buffer, bufsize, &pdata);432free(buffer);433resVal = GetValueFromNameValueList(&pdata, "errorCode");434if(resVal) {435if(sscanf(resVal, "%d", &ret) != 1)436ret = UPNPCOMMAND_UNKNOWN_ERROR;437} else {438char *p;439440p = GetValueFromNameValueList(&pdata, "NewReservedPort");441if(p) {442strncpy(reservedPort, p, 6);443reservedPort[5] = '\0';444ret = UPNPCOMMAND_SUCCESS;445} else {446ret = UPNPCOMMAND_INVALID_RESPONSE;447}448}449ClearNameValueList(&pdata);450return ret;451}452453MINIUPNP_LIBSPEC int454UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,455const char * extPort, const char * proto,456const char * remoteHost)457{458/*struct NameValueParserData pdata;*/459struct UPNParg DeletePortMappingArgs[] = {460{"NewRemoteHost", remoteHost},461{"NewExternalPort", extPort},462{"NewProtocol", proto},463{NULL, NULL}464};465char * buffer;466int bufsize;467struct NameValueParserData pdata;468const char * resVal;469int ret;470471if(!extPort || !proto)472return UPNPCOMMAND_INVALID_ARGS;473474buffer = simpleUPnPcommand(controlURL, servicetype,475"DeletePortMapping",476DeletePortMappingArgs, &bufsize);477if(!buffer) {478return UPNPCOMMAND_HTTP_ERROR;479}480/*DisplayNameValueList(buffer, bufsize);*/481ParseNameValue(buffer, bufsize, &pdata);482free(buffer);483resVal = GetValueFromNameValueList(&pdata, "errorCode");484if(resVal) {485if(sscanf(resVal, "%d", &ret) != 1)486ret = UPNPCOMMAND_UNKNOWN_ERROR;487} else {488ret = UPNPCOMMAND_SUCCESS;489}490ClearNameValueList(&pdata);491return ret;492}493494MINIUPNP_LIBSPEC int495UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,496const char * extPortStart, const char * extPortEnd,497const char * proto,498const char * manage)499{500struct UPNParg DeletePortMappingRangeArgs[] = {501{"NewStartPort", extPortStart},502{"NewEndPort", extPortEnd},503{"NewProtocol", proto},504{"NewManage", manage},505{NULL, NULL}506};507char * buffer;508int bufsize;509struct NameValueParserData pdata;510const char * resVal;511int ret;512513if(!extPortStart || !extPortEnd || !proto || !manage)514return UPNPCOMMAND_INVALID_ARGS;515516517buffer = simpleUPnPcommand(controlURL, servicetype,518"DeletePortMappingRange",519DeletePortMappingRangeArgs, &bufsize);520if(!buffer) {521return UPNPCOMMAND_HTTP_ERROR;522}523ParseNameValue(buffer, bufsize, &pdata);524free(buffer);525resVal = GetValueFromNameValueList(&pdata, "errorCode");526if(resVal) {527if(sscanf(resVal, "%d", &ret) != 1)528ret = UPNPCOMMAND_UNKNOWN_ERROR;529} else {530ret = UPNPCOMMAND_SUCCESS;531}532ClearNameValueList(&pdata);533return ret;534}535536MINIUPNP_LIBSPEC int537UPNP_GetGenericPortMappingEntry(const char * controlURL,538const char * servicetype,539const char * index,540char * extPort,541char * intClient,542char * intPort,543char * protocol,544char * desc,545char * enabled,546char * rHost,547char * duration)548{549return UPNP_GetGenericPortMappingEntryExt(controlURL, servicetype, index,550extPort, intClient, intPort,551protocol, desc, 80, enabled,552rHost, 64, duration);553}554555MINIUPNP_LIBSPEC int556UPNP_GetGenericPortMappingEntryExt(const char * controlURL,557const char * servicetype,558const char * index,559char * extPort,560char * intClient,561char * intPort,562char * protocol,563char * desc,564size_t desclen,565char * enabled,566char * rHost,567size_t rHostlen,568char * duration)569{570struct NameValueParserData pdata;571struct UPNParg GetPortMappingArgs[] = {572{"NewPortMappingIndex", index},573{NULL, NULL}574};575char * buffer;576int bufsize;577char * p;578int ret = UPNPCOMMAND_UNKNOWN_ERROR;579if(!index || !extPort || !intClient || !intPort || !protocol)580return UPNPCOMMAND_INVALID_ARGS;581buffer = simpleUPnPcommand(controlURL, servicetype,582"GetGenericPortMappingEntry",583GetPortMappingArgs, &bufsize);584if(!buffer) {585return UPNPCOMMAND_HTTP_ERROR;586}587ParseNameValue(buffer, bufsize, &pdata);588free(buffer);589590p = GetValueFromNameValueList(&pdata, "NewRemoteHost");591if(p && rHost)592{593strncpy(rHost, p, rHostlen);594rHost[rHostlen-1] = '\0';595}596p = GetValueFromNameValueList(&pdata, "NewExternalPort");597if(p)598{599strncpy(extPort, p, 6);600extPort[5] = '\0';601ret = UPNPCOMMAND_SUCCESS;602}603else604{605extPort[0] = '\0';606}607p = GetValueFromNameValueList(&pdata, "NewProtocol");608if(p)609{610strncpy(protocol, p, 4);611protocol[3] = '\0';612}613else614{615protocol[0] = '\0';616}617p = GetValueFromNameValueList(&pdata, "NewInternalClient");618if(p)619{620strncpy(intClient, p, 16);621intClient[15] = '\0';622ret = 0;623}624else625{626intClient[0] = '\0';627}628p = GetValueFromNameValueList(&pdata, "NewInternalPort");629if(p)630{631strncpy(intPort, p, 6);632intPort[5] = '\0';633}634else635{636intPort[0] = '\0';637}638p = GetValueFromNameValueList(&pdata, "NewEnabled");639if(p && enabled)640{641strncpy(enabled, p, 4);642enabled[3] = '\0';643}644p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");645if(p && desc)646{647strncpy(desc, p, desclen);648desc[desclen-1] = '\0';649}650p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");651if(p && duration)652{653strncpy(duration, p, 16);654duration[15] = '\0';655}656p = GetValueFromNameValueList(&pdata, "errorCode");657if(p) {658if(sscanf(p, "%d", &ret) != 1)659ret = UPNPCOMMAND_UNKNOWN_ERROR;660}661ClearNameValueList(&pdata);662return ret;663}664665MINIUPNP_LIBSPEC int666UPNP_GetPortMappingNumberOfEntries(const char * controlURL,667const char * servicetype,668unsigned int * numEntries)669{670struct NameValueParserData pdata;671char * buffer;672int bufsize;673char* p;674int ret = UPNPCOMMAND_UNKNOWN_ERROR;675if(!(buffer = simpleUPnPcommand(controlURL, servicetype,676"GetPortMappingNumberOfEntries", 0,677&bufsize))) {678return UPNPCOMMAND_HTTP_ERROR;679}680#ifdef DEBUG681DisplayNameValueList(buffer, bufsize);682#endif683ParseNameValue(buffer, bufsize, &pdata);684free(buffer);685686p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");687if(numEntries && p) {688*numEntries = 0;689sscanf(p, "%u", numEntries);690ret = UPNPCOMMAND_SUCCESS;691}692693p = GetValueFromNameValueList(&pdata, "errorCode");694if(p) {695if(sscanf(p, "%d", &ret) != 1)696ret = UPNPCOMMAND_UNKNOWN_ERROR;697}698699ClearNameValueList(&pdata);700return ret;701}702703/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping704* the result is returned in the intClient and intPort strings705* please provide 16 and 6 bytes of data */706MINIUPNP_LIBSPEC int707UPNP_GetSpecificPortMappingEntry(const char * controlURL,708const char * servicetype,709const char * extPort,710const char * proto,711const char * remoteHost,712char * intClient,713char * intPort,714char * desc,715char * enabled,716char * leaseDuration)717{718return UPNP_GetSpecificPortMappingEntryExt(controlURL, servicetype,719extPort, proto, remoteHost,720intClient, intPort,721desc, 80, enabled,722leaseDuration);723}724725MINIUPNP_LIBSPEC int726UPNP_GetSpecificPortMappingEntryExt(const char * controlURL,727const char * servicetype,728const char * extPort,729const char * proto,730const char * remoteHost,731char * intClient,732char * intPort,733char * desc,734size_t desclen,735char * enabled,736char * leaseDuration)737{738struct NameValueParserData pdata;739struct UPNParg GetPortMappingArgs[] = {740{"NewRemoteHost", remoteHost},741{"NewExternalPort", extPort},742{"NewProtocol", proto},743{NULL, NULL}744};745char * buffer;746int bufsize;747char * p;748int ret = UPNPCOMMAND_UNKNOWN_ERROR;749750if(!intPort || !intClient || !extPort || !proto)751return UPNPCOMMAND_INVALID_ARGS;752753buffer = simpleUPnPcommand(controlURL, servicetype,754"GetSpecificPortMappingEntry",755GetPortMappingArgs, &bufsize);756if(!buffer) {757return UPNPCOMMAND_HTTP_ERROR;758}759/*DisplayNameValueList(buffer, bufsize);*/760ParseNameValue(buffer, bufsize, &pdata);761free(buffer);762763p = GetValueFromNameValueList(&pdata, "NewInternalClient");764if(p) {765strncpy(intClient, p, 16);766intClient[15] = '\0';767ret = UPNPCOMMAND_SUCCESS;768} else769intClient[0] = '\0';770771p = GetValueFromNameValueList(&pdata, "NewInternalPort");772if(p) {773strncpy(intPort, p, 6);774intPort[5] = '\0';775} else776intPort[0] = '\0';777778p = GetValueFromNameValueList(&pdata, "NewEnabled");779if(p && enabled) {780strncpy(enabled, p, 4);781enabled[3] = '\0';782}783784p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");785if(p && desc) {786strncpy(desc, p, desclen);787desc[desclen-1] = '\0';788}789790p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");791if(p && leaseDuration)792{793strncpy(leaseDuration, p, 16);794leaseDuration[15] = '\0';795}796797p = GetValueFromNameValueList(&pdata, "errorCode");798if(p) {799if(sscanf(p, "%d", &ret) != 1)800ret = UPNPCOMMAND_UNKNOWN_ERROR;801}802803ClearNameValueList(&pdata);804return ret;805}806807/* UPNP_GetListOfPortMappings()808*809* Possible UPNP Error codes :810* 606 Action not Authorized811* 730 PortMappingNotFound - no port mapping is found in the specified range.812* 733 InconsistantParameters - NewStartPort and NewEndPort values are not813* consistent.814*/815MINIUPNP_LIBSPEC int816UPNP_GetListOfPortMappings(const char * controlURL,817const char * servicetype,818const char * startPort,819const char * endPort,820const char * protocol,821const char * numberOfPorts,822struct PortMappingParserData * data)823{824struct NameValueParserData pdata;825struct UPNParg GetListOfPortMappingsArgs[] = {826{"NewStartPort", startPort},827{"NewEndPort", endPort},828{"NewProtocol", protocol},829{"NewManage", "1"},830{"NewNumberOfPorts", numberOfPorts?numberOfPorts:"1000"},831{NULL, NULL}832};833const char * p;834char * buffer;835int bufsize;836int ret = UPNPCOMMAND_UNKNOWN_ERROR;837838if(!startPort || !endPort || !protocol)839return UPNPCOMMAND_INVALID_ARGS;840841buffer = simpleUPnPcommand(controlURL, servicetype,842"GetListOfPortMappings",843GetListOfPortMappingsArgs, &bufsize);844if(!buffer) {845return UPNPCOMMAND_HTTP_ERROR;846}847848/*DisplayNameValueList(buffer, bufsize);*/849ParseNameValue(buffer, bufsize, &pdata);850free(buffer);851852/*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/853/*if(p) {854printf("NewPortListing : %s\n", p);855}*/856/*printf("NewPortListing(%d chars) : %s\n",857pdata.portListingLength, pdata.portListing);*/858if(pdata.portListing)859{860/*struct PortMapping * pm;861int i = 0;*/862ParsePortListing(pdata.portListing, pdata.portListingLength,863data);864ret = UPNPCOMMAND_SUCCESS;865/*866for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next)867{868printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n",869i, pm->protocol, pm->externalPort, pm->internalClient,870pm->internalPort,871pm->description, pm->remoteHost);872i++;873}874*/875/*FreePortListing(&data);*/876}877878p = GetValueFromNameValueList(&pdata, "errorCode");879if(p) {880if(sscanf(p, "%d", &ret) != 1)881ret = UPNPCOMMAND_UNKNOWN_ERROR;882}883ClearNameValueList(&pdata);884885/*printf("%.*s", bufsize, buffer);*/886887return ret;888}889890/* IGD:2, functions for service WANIPv6FirewallControl:1 */891MINIUPNP_LIBSPEC int892UPNP_GetFirewallStatus(const char * controlURL,893const char * servicetype,894int * firewallEnabled,895int * inboundPinholeAllowed)896{897struct NameValueParserData pdata;898char * buffer;899int bufsize;900char * fe, *ipa, *p;901int ret = UPNPCOMMAND_UNKNOWN_ERROR;902903if(!firewallEnabled || !inboundPinholeAllowed)904return UPNPCOMMAND_INVALID_ARGS;905906buffer = simpleUPnPcommand(controlURL, servicetype,907"GetFirewallStatus", 0, &bufsize);908if(!buffer) {909return UPNPCOMMAND_HTTP_ERROR;910}911ParseNameValue(buffer, bufsize, &pdata);912free(buffer);913fe = GetValueFromNameValueList(&pdata, "FirewallEnabled");914ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed");915if(ipa && fe)916ret = UPNPCOMMAND_SUCCESS;917if(fe)918*firewallEnabled = my_atoui(fe);919/*else920*firewallEnabled = 0;*/921if(ipa)922*inboundPinholeAllowed = my_atoui(ipa);923/*else924*inboundPinholeAllowed = 0;*/925p = GetValueFromNameValueList(&pdata, "errorCode");926if(p)927{928if(sscanf(p, "%d", &ret) != 1)929ret = UPNPCOMMAND_UNKNOWN_ERROR;930}931ClearNameValueList(&pdata);932return ret;933}934935MINIUPNP_LIBSPEC int936UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,937const char * remoteHost,938const char * remotePort,939const char * intClient,940const char * intPort,941const char * proto,942int * opTimeout)943{944struct UPNParg GetOutboundPinholeTimeoutArgs[] = {945{"RemoteHost", remoteHost},946{"RemotePort", remotePort},947{"Protocol", proto},948{"InternalPort", intPort},949{"InternalClient", intClient},950{NULL, NULL}951};952char * buffer;953int bufsize;954struct NameValueParserData pdata;955const char * resVal;956int ret;957958if(!intPort || !intClient || !proto || !remotePort || !remoteHost)959return UPNPCOMMAND_INVALID_ARGS;960961buffer = simpleUPnPcommand(controlURL, servicetype,962"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);963if(!buffer)964return UPNPCOMMAND_HTTP_ERROR;965ParseNameValue(buffer, bufsize, &pdata);966free(buffer);967resVal = GetValueFromNameValueList(&pdata, "errorCode");968if(resVal)969{970if(sscanf(resVal, "%d", &ret) != 1)971ret = UPNPCOMMAND_UNKNOWN_ERROR;972}973else974{975const char * p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");976if(p)977*opTimeout = my_atoui(p);978ret = UPNPCOMMAND_SUCCESS;979}980ClearNameValueList(&pdata);981return ret;982}983984MINIUPNP_LIBSPEC int985UPNP_AddPinhole(const char * controlURL, const char * servicetype,986const char * remoteHost,987const char * remotePort,988const char * intClient,989const char * intPort,990const char * proto,991const char * leaseTime,992char * uniqueID)993{994struct UPNParg AddPinholeArgs[] = {995{"RemoteHost", ""},996{"RemotePort", remotePort},997{"Protocol", proto},998{"InternalPort", intPort},999{"InternalClient", ""},1000{"LeaseTime", leaseTime},1001{NULL, NULL}1002};1003char * buffer;1004int bufsize;1005struct NameValueParserData pdata;1006const char * resVal;1007char * p;1008int ret;10091010if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime)1011return UPNPCOMMAND_INVALID_ARGS;10121013/* RemoteHost and InternalClient can be wilcarded1014* accept both the empty string and "empty" as wildcard */1015if(strncmp(remoteHost, "empty", 5) != 0)1016AddPinholeArgs[0].val = remoteHost;1017if(strncmp(intClient, "empty", 5) != 0)1018AddPinholeArgs[4].val = intClient;1019buffer = simpleUPnPcommand(controlURL, servicetype,1020"AddPinhole", AddPinholeArgs, &bufsize);1021if(!buffer)1022return UPNPCOMMAND_HTTP_ERROR;1023ParseNameValue(buffer, bufsize, &pdata);1024free(buffer);1025p = GetValueFromNameValueList(&pdata, "UniqueID");1026if(p)1027{1028strncpy(uniqueID, p, 8);1029uniqueID[7] = '\0';1030}1031resVal = GetValueFromNameValueList(&pdata, "errorCode");1032if(resVal)1033{1034/*printf("AddPortMapping errorCode = '%s'\n", resVal);*/1035if(sscanf(resVal, "%d", &ret) != 1)1036ret = UPNPCOMMAND_UNKNOWN_ERROR;1037}1038else1039{1040ret = UPNPCOMMAND_SUCCESS;1041}1042ClearNameValueList(&pdata);1043return ret;1044}10451046MINIUPNP_LIBSPEC int1047UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,1048const char * uniqueID,1049const char * leaseTime)1050{1051struct UPNParg UpdatePinholeArgs[] = {1052{"UniqueID", uniqueID},1053{"NewLeaseTime", leaseTime},1054{NULL, NULL}1055};1056char * buffer;1057int bufsize;1058struct NameValueParserData pdata;1059const char * resVal;1060int ret;10611062if(!uniqueID || !leaseTime)1063return UPNPCOMMAND_INVALID_ARGS;10641065buffer = simpleUPnPcommand(controlURL, servicetype,1066"UpdatePinhole", UpdatePinholeArgs, &bufsize);1067if(!buffer)1068return UPNPCOMMAND_HTTP_ERROR;1069ParseNameValue(buffer, bufsize, &pdata);1070free(buffer);1071resVal = GetValueFromNameValueList(&pdata, "errorCode");1072if(resVal)1073{1074/*printf("AddPortMapping errorCode = '%s'\n", resVal); */1075if(sscanf(resVal, "%d", &ret) != 1)1076ret = UPNPCOMMAND_UNKNOWN_ERROR;1077}1078else1079{1080ret = UPNPCOMMAND_SUCCESS;1081}1082ClearNameValueList(&pdata);1083return ret;1084}10851086MINIUPNP_LIBSPEC int1087UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID)1088{1089/*struct NameValueParserData pdata;*/1090struct UPNParg DeletePinholeArgs[] = {1091{"UniqueID", uniqueID},1092{NULL, NULL}1093};1094char * buffer;1095int bufsize;1096struct NameValueParserData pdata;1097const char * resVal;1098int ret;10991100if(!uniqueID)1101return UPNPCOMMAND_INVALID_ARGS;11021103buffer = simpleUPnPcommand(controlURL, servicetype,1104"DeletePinhole", DeletePinholeArgs, &bufsize);1105if(!buffer)1106return UPNPCOMMAND_HTTP_ERROR;1107/*DisplayNameValueList(buffer, bufsize);*/1108ParseNameValue(buffer, bufsize, &pdata);1109free(buffer);1110resVal = GetValueFromNameValueList(&pdata, "errorCode");1111if(resVal)1112{1113if(sscanf(resVal, "%d", &ret) != 1)1114ret = UPNPCOMMAND_UNKNOWN_ERROR;1115}1116else1117{1118ret = UPNPCOMMAND_SUCCESS;1119}1120ClearNameValueList(&pdata);1121return ret;1122}11231124MINIUPNP_LIBSPEC int1125UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,1126const char * uniqueID, int * isWorking)1127{1128struct NameValueParserData pdata;1129struct UPNParg CheckPinholeWorkingArgs[] = {1130{"UniqueID", uniqueID},1131{NULL, NULL}1132};1133char * buffer;1134int bufsize;1135char * p;1136int ret = UPNPCOMMAND_UNKNOWN_ERROR;11371138if(!uniqueID)1139return UPNPCOMMAND_INVALID_ARGS;11401141buffer = simpleUPnPcommand(controlURL, servicetype,1142"CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);1143if(!buffer)1144{1145return UPNPCOMMAND_HTTP_ERROR;1146}1147ParseNameValue(buffer, bufsize, &pdata);1148free(buffer);11491150p = GetValueFromNameValueList(&pdata, "IsWorking");1151if(p)1152{1153*isWorking=my_atoui(p);1154ret = UPNPCOMMAND_SUCCESS;1155}1156else1157*isWorking = 0;11581159p = GetValueFromNameValueList(&pdata, "errorCode");1160if(p)1161{1162if(sscanf(p, "%d", &ret) != 1)1163ret = UPNPCOMMAND_UNKNOWN_ERROR;1164}11651166ClearNameValueList(&pdata);1167return ret;1168}11691170MINIUPNP_LIBSPEC int1171UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,1172const char * uniqueID, int * packets)1173{1174struct NameValueParserData pdata;1175struct UPNParg GetPinholePacketsArgs[] = {1176{"UniqueID", uniqueID},1177{NULL, NULL}1178};1179char * buffer;1180int bufsize;1181char * p;1182int ret = UPNPCOMMAND_UNKNOWN_ERROR;11831184if(!uniqueID)1185return UPNPCOMMAND_INVALID_ARGS;11861187buffer = simpleUPnPcommand(controlURL, servicetype,1188"GetPinholePackets", GetPinholePacketsArgs, &bufsize);1189if(!buffer)1190return UPNPCOMMAND_HTTP_ERROR;1191ParseNameValue(buffer, bufsize, &pdata);1192free(buffer);11931194p = GetValueFromNameValueList(&pdata, "PinholePackets");1195if(p)1196{1197*packets=my_atoui(p);1198ret = UPNPCOMMAND_SUCCESS;1199}12001201p = GetValueFromNameValueList(&pdata, "errorCode");1202if(p)1203{1204if(sscanf(p, "%d", &ret) != 1)1205ret = UPNPCOMMAND_UNKNOWN_ERROR;1206}12071208ClearNameValueList(&pdata);1209return ret;1210}121112121213