miniupnp/miniupnpc/upnpcommands.c
Mike Gelfand 2e4011ce33 Rename LIBSPEC macro to resolve natpmp/miniupnp conflict
Same macro name is used in both natpmp and miniupnp libraries so it's
impossble to link one statically and another dynamically. This patch
renames the macro to have library-specific name.
2014-06-01 13:35:13 +03:00

1212 lines
34 KiB
C

/* $Id: upnpcommands.c,v 1.42 2014/01/31 13:18:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "upnpcommands.h"
#include "miniupnpc.h"
#include "portlistingparse.h"
static UNSIGNED_INTEGER
my_atoui(const char * s)
{
return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;
}
/*
* */
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
return r;
}
/*
* */
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
return r;
}
/*
* */
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
return r;
}
/*
* */
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
return r;
}
/* UPNP_GetStatusInfo() call the corresponding UPNP method
* returns the current status and uptime */
MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
unsigned int * uptime,
char * lastconnerror)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char * p;
char * up;
char * err;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!status && !uptime)
return UPNPCOMMAND_INVALID_ARGS;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetStatusInfo", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
up = GetValueFromNameValueList(&pdata, "NewUptime");
p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
if(p && up)
ret = UPNPCOMMAND_SUCCESS;
if(status) {
if(p){
strncpy(status, p, 64 );
status[63] = '\0';
}else
status[0]= '\0';
}
if(uptime) {
if(up)
sscanf(up,"%u",uptime);
else
uptime = 0;
}
if(lastconnerror) {
if(err) {
strncpy(lastconnerror, err, 64 );
lastconnerror[63] = '\0';
} else
lastconnerror[0] = '\0';
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
* returns the connection type */
MINIUPNP_LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype,
char * connectionType)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!connectionType)
return UPNPCOMMAND_INVALID_ARGS;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetConnectionTypeInfo", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewConnectionType");
/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
/* PossibleConnectionTypes will have several values.... */
if(p) {
strncpy(connectionType, p, 64 );
connectionType[63] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else
connectionType[0] = '\0';
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
* Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
const char * servicetype,
unsigned int * bitrateDown,
unsigned int * bitrateUp)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
char * down;
char * up;
char * p;
if(!bitrateDown && !bitrateUp)
return UPNPCOMMAND_INVALID_ARGS;
/* shouldn't we use GetCommonLinkProperties ? */
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetCommonLinkProperties", 0, &bufsize))) {
/*"GetLinkLayerMaxBitRates", 0, &bufsize);*/
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/
if(down && up)
ret = UPNPCOMMAND_SUCCESS;
if(bitrateDown) {
if(down)
sscanf(down,"%u",bitrateDown);
else
*bitrateDown = 0;
}
if(bitrateUp) {
if(up)
sscanf(up,"%u",bitrateUp);
else
*bitrateUp = 0;
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
* if the third arg is not null the value is copied to it.
* at least 16 bytes must be available
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
*
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
*/
MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype,
char * extIpAdd)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!extIpAdd || !controlURL || !servicetype)
return UPNPCOMMAND_INVALID_ARGS;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetExternalIPAddress", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
if(p) {
strncpy(extIpAdd, p, 16 );
extIpAdd[15] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else
extIpAdd[0] = '\0';
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration)
{
struct UPNParg * AddPortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!inPort || !inClient || !proto || !extPort)
return UPNPCOMMAND_INVALID_ARGS;
AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
AddPortMappingArgs[0].elt = "NewRemoteHost";
AddPortMappingArgs[0].val = remoteHost;
AddPortMappingArgs[1].elt = "NewExternalPort";
AddPortMappingArgs[1].val = extPort;
AddPortMappingArgs[2].elt = "NewProtocol";
AddPortMappingArgs[2].val = proto;
AddPortMappingArgs[3].elt = "NewInternalPort";
AddPortMappingArgs[3].val = inPort;
AddPortMappingArgs[4].elt = "NewInternalClient";
AddPortMappingArgs[4].val = inClient;
AddPortMappingArgs[5].elt = "NewEnabled";
AddPortMappingArgs[5].val = "1";
AddPortMappingArgs[6].elt = "NewPortMappingDescription";
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPortMapping", AddPortMappingArgs,
&bufsize))) {
free(AddPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
/*buffer[bufsize] = '\0';*/
/*puts(buffer);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(AddPortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration,
char * reservedPort)
{
struct UPNParg * AddPortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!inPort || !inClient || !proto || !extPort)
return UPNPCOMMAND_INVALID_ARGS;
AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
AddPortMappingArgs[0].elt = "NewRemoteHost";
AddPortMappingArgs[0].val = remoteHost;
AddPortMappingArgs[1].elt = "NewExternalPort";
AddPortMappingArgs[1].val = extPort;
AddPortMappingArgs[2].elt = "NewProtocol";
AddPortMappingArgs[2].val = proto;
AddPortMappingArgs[3].elt = "NewInternalPort";
AddPortMappingArgs[3].val = inPort;
AddPortMappingArgs[4].elt = "NewInternalClient";
AddPortMappingArgs[4].val = inClient;
AddPortMappingArgs[5].elt = "NewEnabled";
AddPortMappingArgs[5].val = "1";
AddPortMappingArgs[6].elt = "NewPortMappingDescription";
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddAnyPortMapping", AddPortMappingArgs,
&bufsize))) {
free(AddPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
char *p;
p = GetValueFromNameValueList(&pdata, "NewReservedPort");
if(p) {
strncpy(reservedPort, p, 6);
reservedPort[5] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else {
ret = UPNPCOMMAND_INVALID_RESPONSE;
}
}
ClearNameValueList(&pdata);
free(AddPortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost)
{
/*struct NameValueParserData pdata;*/
struct UPNParg * DeletePortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!extPort || !proto)
return UPNPCOMMAND_INVALID_ARGS;
DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
DeletePortMappingArgs[0].elt = "NewRemoteHost";
DeletePortMappingArgs[0].val = remoteHost;
DeletePortMappingArgs[1].elt = "NewExternalPort";
DeletePortMappingArgs[1].val = extPort;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, &bufsize))) {
free(DeletePortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
const char * extPortStart, const char * extPortEnd,
const char * proto,
const char * manage)
{
struct UPNParg * DeletePortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!extPortStart || !extPortEnd || !proto || !manage)
return UPNPCOMMAND_INVALID_ARGS;
DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg));
DeletePortMappingArgs[0].elt = "NewStartPort";
DeletePortMappingArgs[0].val = extPortStart;
DeletePortMappingArgs[1].elt = "NewEndPort";
DeletePortMappingArgs[1].val = extPortEnd;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
DeletePortMappingArgs[3].elt = "NewManage";
DeletePortMappingArgs[3].val = manage;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMappingRange",
DeletePortMappingArgs, &bufsize))) {
free(DeletePortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * index,
char * extPort,
char * intClient,
char * intPort,
char * protocol,
char * desc,
char * enabled,
char * rHost,
char * duration)
{
struct NameValueParserData pdata;
struct UPNParg * GetPortMappingArgs;
char * buffer;
int bufsize;
char * p;
int r = UPNPCOMMAND_UNKNOWN_ERROR;
if(!index)
return UPNPCOMMAND_INVALID_ARGS;
intClient[0] = '\0';
intPort[0] = '\0';
GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
if(p && rHost)
{
strncpy(rHost, p, 64);
rHost[63] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewExternalPort");
if(p && extPort)
{
strncpy(extPort, p, 6);
extPort[5] = '\0';
r = UPNPCOMMAND_SUCCESS;
}
p = GetValueFromNameValueList(&pdata, "NewProtocol");
if(p && protocol)
{
strncpy(protocol, p, 4);
protocol[3] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewInternalClient");
if(p && intClient)
{
strncpy(intClient, p, 16);
intClient[15] = '\0';
r = 0;
}
p = GetValueFromNameValueList(&pdata, "NewInternalPort");
if(p && intPort)
{
strncpy(intPort, p, 6);
intPort[5] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewEnabled");
if(p && enabled)
{
strncpy(enabled, p, 4);
enabled[3] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
if(p && desc)
{
strncpy(desc, p, 80);
desc[79] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
if(p && duration)
{
strncpy(duration, p, 16);
duration[15] = '\0';
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
r = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &r);
}
ClearNameValueList(&pdata);
free(GetPortMappingArgs);
return r;
}
MINIUPNP_LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
const char * servicetype,
unsigned int * numEntries)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char* p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPortMappingNumberOfEntries", 0,
&bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
#ifdef DEBUG
DisplayNameValueList(buffer, bufsize);
#endif
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
if(numEntries && p) {
*numEntries = 0;
sscanf(p, "%u", numEntries);
ret = UPNPCOMMAND_SUCCESS;
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
* the result is returned in the intClient and intPort strings
* please provide 16 and 6 bytes of data */
MINIUPNP_LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
char * enabled,
char * leaseDuration)
{
struct NameValueParserData pdata;
struct UPNParg * GetPortMappingArgs;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!intPort || !intClient || !extPort || !proto)
return UPNPCOMMAND_INVALID_ARGS;
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewRemoteHost";
GetPortMappingArgs[0].val = remoteHost;
GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
GetPortMappingArgs[2].val = proto;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewInternalClient");
if(p) {
strncpy(intClient, p, 16);
intClient[15] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else
intClient[0] = '\0';
p = GetValueFromNameValueList(&pdata, "NewInternalPort");
if(p) {
strncpy(intPort, p, 6);
intPort[5] = '\0';
} else
intPort[0] = '\0';
p = GetValueFromNameValueList(&pdata, "NewEnabled");
if(p && enabled) {
strncpy(enabled, p, 4);
enabled[3] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
if(p && desc) {
strncpy(desc, p, 80);
desc[79] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
if(p && leaseDuration)
{
strncpy(leaseDuration, p, 16);
leaseDuration[15] = '\0';
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
free(GetPortMappingArgs);
return ret;
}
/* UPNP_GetListOfPortMappings()
*
* Possible UPNP Error codes :
* 606 Action not Authorized
* 730 PortMappingNotFound - no port mapping is found in the specified range.
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
const char * endPort,
const char * protocol,
const char * numberOfPorts,
struct PortMappingParserData * data)
{
struct NameValueParserData pdata;
struct UPNParg * GetListOfPortMappingsArgs;
const char * p;
char * buffer;
int bufsize;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!startPort || !endPort || !protocol)
return UPNPCOMMAND_INVALID_ARGS;
GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg));
GetListOfPortMappingsArgs[0].elt = "NewStartPort";
GetListOfPortMappingsArgs[0].val = startPort;
GetListOfPortMappingsArgs[1].elt = "NewEndPort";
GetListOfPortMappingsArgs[1].val = endPort;
GetListOfPortMappingsArgs[2].elt = "NewProtocol";
GetListOfPortMappingsArgs[2].val = protocol;
GetListOfPortMappingsArgs[3].elt = "NewManage";
GetListOfPortMappingsArgs[3].val = "1";
GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts";
GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetListOfPortMappings",
GetListOfPortMappingsArgs, &bufsize))) {
free(GetListOfPortMappingsArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
free(GetListOfPortMappingsArgs);
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/
/*if(p) {
printf("NewPortListing : %s\n", p);
}*/
/*printf("NewPortListing(%d chars) : %s\n",
pdata.portListingLength, pdata.portListing);*/
if(pdata.portListing)
{
/*struct PortMapping * pm;
int i = 0;*/
ParsePortListing(pdata.portListing, pdata.portListingLength,
data);
ret = UPNPCOMMAND_SUCCESS;
/*
for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next)
{
printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n",
i, pm->protocol, pm->externalPort, pm->internalClient,
pm->internalPort,
pm->description, pm->remoteHost);
i++;
}
*/
/*FreePortListing(&data);*/
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
/*printf("%.*s", bufsize, buffer);*/
return ret;
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * inboundPinholeAllowed)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled || !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetFirewallStatus", 0, &bufsize);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
fe = GetValueFromNameValueList(&pdata, "FirewallEnabled");
ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed");
if(ipa && fe)
ret = UPNPCOMMAND_SUCCESS;
if(fe)
*firewallEnabled = my_atoui(fe);
/*else
*firewallEnabled = 0;*/
if(ipa)
*inboundPinholeAllowed = my_atoui(ipa);
/*else
*inboundPinholeAllowed = 0;*/
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
int * opTimeout)
{
struct UPNParg * GetOutboundPinholeTimeoutArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
char * p;
int ret;
if(!intPort || !intClient || !proto || !remotePort || !remoteHost)
return UPNPCOMMAND_INVALID_ARGS;
GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg));
GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost";
GetOutboundPinholeTimeoutArgs[0].val = remoteHost;
GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort";
GetOutboundPinholeTimeoutArgs[1].val = remotePort;
GetOutboundPinholeTimeoutArgs[2].elt = "Protocol";
GetOutboundPinholeTimeoutArgs[2].val = proto;
GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort";
GetOutboundPinholeTimeoutArgs[3].val = intPort;
GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient";
GetOutboundPinholeTimeoutArgs[4].val = intClient;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");
if(p)
*opTimeout = my_atoui(p);
}
ClearNameValueList(&pdata);
free(GetOutboundPinholeTimeoutArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
const char * leaseTime,
char * uniqueID)
{
struct UPNParg * AddPinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
char * p;
int ret;
if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime)
return UPNPCOMMAND_INVALID_ARGS;
AddPinholeArgs = calloc(7, sizeof(struct UPNParg));
/* RemoteHost can be wilcarded */
if(strncmp(remoteHost, "empty", 5)==0)
{
AddPinholeArgs[0].elt = "RemoteHost";
AddPinholeArgs[0].val = "";
}
else
{
AddPinholeArgs[0].elt = "RemoteHost";
AddPinholeArgs[0].val = remoteHost;
}
AddPinholeArgs[1].elt = "RemotePort";
AddPinholeArgs[1].val = remotePort;
AddPinholeArgs[2].elt = "Protocol";
AddPinholeArgs[2].val = proto;
AddPinholeArgs[3].elt = "InternalPort";
AddPinholeArgs[3].val = intPort;
if(strncmp(intClient, "empty", 5)==0)
{
AddPinholeArgs[4].elt = "InternalClient";
AddPinholeArgs[4].val = "";
}
else
{
AddPinholeArgs[4].elt = "InternalClient";
AddPinholeArgs[4].val = intClient;
}
AddPinholeArgs[5].elt = "LeaseTime";
AddPinholeArgs[5].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPinhole", AddPinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "UniqueID");
if(p)
{
strncpy(uniqueID, p, 8);
uniqueID[7] = '\0';
}
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
/*printf("AddPortMapping errorCode = '%s'\n", resVal);*/
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(AddPinholeArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime)
{
struct UPNParg * UpdatePinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!uniqueID || !leaseTime)
return UPNPCOMMAND_INVALID_ARGS;
UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg));
UpdatePinholeArgs[0].elt = "UniqueID";
UpdatePinholeArgs[0].val = uniqueID;
UpdatePinholeArgs[1].elt = "NewLeaseTime";
UpdatePinholeArgs[1].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"UpdatePinhole", UpdatePinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(UpdatePinholeArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID)
{
/*struct NameValueParserData pdata;*/
struct UPNParg * DeletePinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
DeletePinholeArgs = calloc(2, sizeof(struct UPNParg));
DeletePinholeArgs[0].elt = "UniqueID";
DeletePinholeArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePinhole", DeletePinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePinholeArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking)
{
struct NameValueParserData pdata;
struct UPNParg * CheckPinholeWorkingArgs;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg));
CheckPinholeWorkingArgs[0].elt = "UniqueID";
CheckPinholeWorkingArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "IsWorking");
if(p)
{
*isWorking=my_atoui(p);
ret = UPNPCOMMAND_SUCCESS;
}
else
*isWorking = 0;
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
free(CheckPinholeWorkingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets)
{
struct NameValueParserData pdata;
struct UPNParg * GetPinholePacketsArgs;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg));
GetPinholePacketsArgs[0].elt = "UniqueID";
GetPinholePacketsArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPinholePackets", GetPinholePacketsArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "PinholePackets");
if(p)
{
*packets=my_atoui(p);
ret = UPNPCOMMAND_SUCCESS;
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
free(GetPinholePacketsArgs);
return ret;
}