| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240 | /* $Id: upnpcommands.c,v 1.48 2017/04/21 10:22:40 nanard Exp $ *//* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2017 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_INTEGERmy_atoui(const char * s){	return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;}/* * */MINIUPNP_LIBSPEC UNSIGNED_INTEGERUPNP_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_INTEGERUPNP_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_INTEGERUPNP_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_INTEGERUPNP_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 intUPNP_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 intUPNP_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 intUPNP_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 intUPNP_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 intUPNP_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));	if(AddPortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	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";	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "AddPortMapping", AddPortMappingArgs,	                           &bufsize);	free(AddPortMappingArgs);	if(!buffer) {		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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(AddPortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	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";	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "AddAnyPortMapping", AddPortMappingArgs,	                           &bufsize);	free(AddPortMappingArgs);	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 {		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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(DeletePortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	DeletePortMappingArgs[0].elt = "NewRemoteHost";	DeletePortMappingArgs[0].val = remoteHost;	DeletePortMappingArgs[1].elt = "NewExternalPort";	DeletePortMappingArgs[1].val = extPort;	DeletePortMappingArgs[2].elt = "NewProtocol";	DeletePortMappingArgs[2].val = proto;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                          "DeletePortMapping",	                          DeletePortMappingArgs, &bufsize);	free(DeletePortMappingArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(DeletePortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	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;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "DeletePortMappingRange",	                           DeletePortMappingArgs, &bufsize);	free(DeletePortMappingArgs);	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;	}	ClearNameValueList(&pdata);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(GetPortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	GetPortMappingArgs[0].elt = "NewPortMappingIndex";	GetPortMappingArgs[0].val = index;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "GetGenericPortMappingEntry",	                           GetPortMappingArgs, &bufsize);	free(GetPortMappingArgs);	if(!buffer) {		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)	{		strncpy(intClient, p, 16);		intClient[15] = '\0';		r = 0;	}	p = GetValueFromNameValueList(&pdata, "NewInternalPort");	if(p)	{		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);	return r;}MINIUPNP_LIBSPEC intUPNP_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 intUPNP_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));	if(GetPortMappingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	GetPortMappingArgs[0].elt = "NewRemoteHost";	GetPortMappingArgs[0].val = remoteHost;	GetPortMappingArgs[1].elt = "NewExternalPort";	GetPortMappingArgs[1].val = extPort;	GetPortMappingArgs[2].elt = "NewProtocol";	GetPortMappingArgs[2].val = proto;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "GetSpecificPortMappingEntry",	                           GetPortMappingArgs, &bufsize);	free(GetPortMappingArgs);	if(!buffer) {		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);	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 intUPNP_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));	if(GetListOfPortMappingsArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	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";	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "GetListOfPortMappings",	                           GetListOfPortMappingsArgs, &bufsize);	free(GetListOfPortMappingsArgs);	if(!buffer) {		return UPNPCOMMAND_HTTP_ERROR;	}	/*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 intUPNP_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 intUPNP_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));	if(GetOutboundPinholeTimeoutArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	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);	free(GetOutboundPinholeTimeoutArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(AddPinholeArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	/* 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);	free(AddPinholeArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(UpdatePinholeArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	UpdatePinholeArgs[0].elt = "UniqueID";	UpdatePinholeArgs[0].val = uniqueID;	UpdatePinholeArgs[1].elt = "NewLeaseTime";	UpdatePinholeArgs[1].val = leaseTime;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "UpdatePinhole", UpdatePinholeArgs, &bufsize);	free(UpdatePinholeArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(DeletePinholeArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	DeletePinholeArgs[0].elt = "UniqueID";	DeletePinholeArgs[0].val = uniqueID;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "DeletePinhole", DeletePinholeArgs, &bufsize);	free(DeletePinholeArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(CheckPinholeWorkingArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	CheckPinholeWorkingArgs[0].elt = "UniqueID";	CheckPinholeWorkingArgs[0].val = uniqueID;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);	free(CheckPinholeWorkingArgs);	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);	return ret;}MINIUPNP_LIBSPEC intUPNP_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));	if(GetPinholePacketsArgs == NULL)		return UPNPCOMMAND_MEM_ALLOC_ERROR;	GetPinholePacketsArgs[0].elt = "UniqueID";	GetPinholePacketsArgs[0].val = uniqueID;	buffer = simpleUPnPcommand(-1, controlURL, servicetype,	                           "GetPinholePackets", GetPinholePacketsArgs, &bufsize);	free(GetPinholePacketsArgs);	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);	return ret;}
 |