PageRenderTime 291ms CodeModel.GetById 61ms app.highlight 182ms RepoModel.GetById 39ms app.codeStats 0ms

/thirdparty/libportfwd/third-party/miniupnpc-1.6/upnpcommands.c

http://github.com/tomahawk-player/tomahawk
C | 1097 lines | 910 code | 86 blank | 101 comment | 133 complexity | 79ca76a1f481acd0070fdfe55c0c4c2c MD5 | raw file
   1/* $Id: upnpcommands.c,v 1.37 2011/06/04 15:56:23 nanard Exp $ */
   2/* Project : miniupnp
   3 * Author : Thomas Bernard
   4 * Copyright (c) 2005-2011 Thomas Bernard
   5 * This software is subject to the conditions detailed in the
   6 * 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
  15static UNSIGNED_INTEGER
  16my_atoui(const char * s)
  17{
  18	return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;
  19}
  20
  21/*
  22 * */
  23LIBSPEC UNSIGNED_INTEGER
  24UPNP_GetTotalBytesSent(const char * controlURL,
  25					const char * servicetype)
  26{
  27	struct NameValueParserData pdata;
  28	char * buffer;
  29	int bufsize;
  30	unsigned int r = 0;
  31	char * p;
  32	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
  33	                                "GetTotalBytesSent", 0, &bufsize))) {
  34		return UPNPCOMMAND_HTTP_ERROR;
  35	}
  36	ParseNameValue(buffer, bufsize, &pdata);
  37	/*DisplayNameValueList(buffer, bufsize);*/
  38	free(buffer); buffer = NULL;
  39	p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
  40	r = my_atoui(p);
  41	ClearNameValueList(&pdata);
  42	return r;
  43}
  44
  45/*
  46 * */
  47LIBSPEC UNSIGNED_INTEGER
  48UPNP_GetTotalBytesReceived(const char * controlURL,
  49						const char * servicetype)
  50{
  51	struct NameValueParserData pdata;
  52	char * buffer;
  53	int bufsize;
  54	unsigned int r = 0;
  55	char * p;
  56	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
  57	                                "GetTotalBytesReceived", 0, &bufsize))) {
  58		return UPNPCOMMAND_HTTP_ERROR;
  59	}
  60	ParseNameValue(buffer, bufsize, &pdata);
  61	/*DisplayNameValueList(buffer, bufsize);*/
  62	free(buffer); buffer = NULL;
  63	p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
  64	r = my_atoui(p);
  65	ClearNameValueList(&pdata);
  66	return r;
  67}
  68
  69/*
  70 * */
  71LIBSPEC UNSIGNED_INTEGER
  72UPNP_GetTotalPacketsSent(const char * controlURL,
  73						const char * servicetype)
  74{
  75	struct NameValueParserData pdata;
  76	char * buffer;
  77	int bufsize;
  78	unsigned int r = 0;
  79	char * p;
  80	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
  81	                                "GetTotalPacketsSent", 0, &bufsize))) {
  82		return UPNPCOMMAND_HTTP_ERROR;
  83	}
  84	ParseNameValue(buffer, bufsize, &pdata);
  85	/*DisplayNameValueList(buffer, bufsize);*/
  86	free(buffer); buffer = NULL;
  87	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
  88	r = my_atoui(p);
  89	ClearNameValueList(&pdata);
  90	return r;
  91}
  92
  93/*
  94 * */
  95LIBSPEC UNSIGNED_INTEGER
  96UPNP_GetTotalPacketsReceived(const char * controlURL,
  97						const char * servicetype)
  98{
  99	struct NameValueParserData pdata;
 100	char * buffer;
 101	int bufsize;
 102	unsigned int r = 0;
 103	char * p;
 104	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 105	                                "GetTotalPacketsReceived", 0, &bufsize))) {
 106		return UPNPCOMMAND_HTTP_ERROR;
 107	}
 108	ParseNameValue(buffer, bufsize, &pdata);
 109	/*DisplayNameValueList(buffer, bufsize);*/
 110	free(buffer); buffer = NULL;
 111	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
 112	r = my_atoui(p);
 113	ClearNameValueList(&pdata);
 114	return r;
 115}
 116
 117/* UPNP_GetStatusInfo() call the corresponding UPNP method
 118 * returns the current status and uptime */
 119LIBSPEC int
 120UPNP_GetStatusInfo(const char * controlURL,
 121				const char * servicetype,
 122				char * status, 
 123				unsigned int * uptime,
 124				char * lastconnerror)
 125{
 126	struct NameValueParserData pdata;
 127	char * buffer;
 128	int bufsize;
 129	char * p;
 130	char * up;
 131	char * err;
 132	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 133
 134	if(!status && !uptime)
 135		return UPNPCOMMAND_INVALID_ARGS;
 136
 137	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 138	                                "GetStatusInfo", 0, &bufsize))) {
 139		return UPNPCOMMAND_HTTP_ERROR;
 140	}
 141	ParseNameValue(buffer, bufsize, &pdata);
 142	/*DisplayNameValueList(buffer, bufsize);*/
 143	free(buffer); buffer = NULL;
 144	up = GetValueFromNameValueList(&pdata, "NewUptime");
 145	p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
 146	err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
 147	if(p && up)
 148	  ret = UPNPCOMMAND_SUCCESS;
 149
 150	if(status) {
 151		if(p){
 152			strncpy(status, p, 64 );
 153			status[63] = '\0';
 154		}else
 155			status[0]= '\0';
 156	}
 157
 158	if(uptime) {
 159		if(up)
 160			sscanf(up,"%u",uptime);
 161		else
 162			uptime = 0;
 163	}
 164
 165	if(lastconnerror) {
 166		if(err) {
 167			strncpy(lastconnerror, err, 64 );
 168			lastconnerror[63] = '\0';
 169		} else
 170			lastconnerror[0] = '\0';
 171	}
 172
 173	p = GetValueFromNameValueList(&pdata, "errorCode");
 174	if(p) {
 175		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 176		sscanf(p, "%d", &ret);
 177	}
 178	ClearNameValueList(&pdata);
 179	return ret;
 180}
 181
 182/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
 183 * returns the connection type */
 184LIBSPEC int
 185UPNP_GetConnectionTypeInfo(const char * controlURL,
 186                           const char * servicetype,
 187                           char * connectionType)
 188{
 189	struct NameValueParserData pdata;
 190	char * buffer;
 191	int bufsize;
 192	char * p;
 193	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 194
 195	if(!connectionType)
 196		return UPNPCOMMAND_INVALID_ARGS;
 197
 198	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 199	                                "GetConnectionTypeInfo", 0, &bufsize))) {
 200		return UPNPCOMMAND_HTTP_ERROR;
 201	}
 202	ParseNameValue(buffer, bufsize, &pdata);
 203	free(buffer); buffer = NULL;
 204	p = GetValueFromNameValueList(&pdata, "NewConnectionType");
 205	/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
 206	/* PossibleConnectionTypes will have several values.... */
 207	if(p) {
 208		strncpy(connectionType, p, 64 );
 209		connectionType[63] = '\0';
 210		ret = UPNPCOMMAND_SUCCESS;
 211	} else
 212		connectionType[0] = '\0';
 213	p = GetValueFromNameValueList(&pdata, "errorCode");
 214	if(p) {
 215		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 216		sscanf(p, "%d", &ret);
 217	}
 218	ClearNameValueList(&pdata);
 219	return ret;
 220}
 221
 222/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
 223 * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
 224 * One of the values can be null 
 225 * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only 
 226 * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
 227LIBSPEC int
 228UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
 229                             const char * servicetype,
 230                             unsigned int * bitrateDown,
 231                             unsigned int * bitrateUp)
 232{
 233	struct NameValueParserData pdata;
 234	char * buffer;
 235	int bufsize;
 236	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 237	char * down;
 238	char * up;
 239	char * p;
 240
 241	if(!bitrateDown && !bitrateUp)
 242		return UPNPCOMMAND_INVALID_ARGS;
 243
 244	/* shouldn't we use GetCommonLinkProperties ? */
 245	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 246	                                "GetCommonLinkProperties", 0, &bufsize))) {
 247	                              /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/
 248		return UPNPCOMMAND_HTTP_ERROR;
 249	}
 250	/*DisplayNameValueList(buffer, bufsize);*/
 251	ParseNameValue(buffer, bufsize, &pdata);
 252	free(buffer); buffer = NULL;
 253	/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
 254	/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
 255	down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
 256	up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
 257	/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
 258	/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/
 259	if(down && up)
 260		ret = UPNPCOMMAND_SUCCESS;
 261
 262	if(bitrateDown) {
 263		if(down)
 264			sscanf(down,"%u",bitrateDown);
 265		else
 266			*bitrateDown = 0;
 267	}
 268
 269	if(bitrateUp) {
 270		if(up)
 271			sscanf(up,"%u",bitrateUp);
 272		else
 273			*bitrateUp = 0;
 274	}
 275	p = GetValueFromNameValueList(&pdata, "errorCode");
 276	if(p) {
 277		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 278		sscanf(p, "%d", &ret);
 279	}
 280	ClearNameValueList(&pdata);
 281	return ret;
 282}
 283
 284
 285/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
 286 * if the third arg is not null the value is copied to it.
 287 * at least 16 bytes must be available
 288 * 
 289 * Return values :
 290 * 0 : SUCCESS
 291 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
 292 *
 293 * 402 Invalid Args - See UPnP Device Architecture section on Control.
 294 * 501 Action Failed - See UPnP Device Architecture section on Control.
 295 */
 296LIBSPEC int
 297UPNP_GetExternalIPAddress(const char * controlURL,
 298                          const char * servicetype,
 299                          char * extIpAdd)
 300{
 301	struct NameValueParserData pdata;
 302	char * buffer;
 303	int bufsize;
 304	char * p;
 305	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 306
 307	if(!extIpAdd || !controlURL || !servicetype)
 308		return UPNPCOMMAND_INVALID_ARGS;
 309
 310	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 311	                                "GetExternalIPAddress", 0, &bufsize))) {
 312		return UPNPCOMMAND_HTTP_ERROR;
 313	}
 314	/*DisplayNameValueList(buffer, bufsize);*/
 315	ParseNameValue(buffer, bufsize, &pdata);
 316	free(buffer); buffer = NULL;
 317	/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
 318	p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
 319	if(p) {
 320		strncpy(extIpAdd, p, 16 );
 321		extIpAdd[15] = '\0';
 322		ret = UPNPCOMMAND_SUCCESS;
 323	} else
 324		extIpAdd[0] = '\0';
 325
 326	p = GetValueFromNameValueList(&pdata, "errorCode");
 327	if(p) {
 328		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 329		sscanf(p, "%d", &ret);
 330	}
 331
 332	ClearNameValueList(&pdata);
 333	return ret;
 334}
 335
 336LIBSPEC int
 337UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
 338                    const char * extPort,
 339					const char * inPort,
 340					const char * inClient,
 341					const char * desc,
 342					const char * proto,
 343                    const char * remoteHost,
 344                    const char * leaseDuration)
 345{
 346	struct UPNParg * AddPortMappingArgs;
 347	char * buffer;
 348	int bufsize;
 349	struct NameValueParserData pdata;
 350	const char * resVal;
 351	int ret;
 352
 353	if(!inPort || !inClient || !proto || !extPort)
 354		return UPNPCOMMAND_INVALID_ARGS;
 355
 356	AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
 357	AddPortMappingArgs[0].elt = "NewRemoteHost";
 358	AddPortMappingArgs[0].val = remoteHost;
 359	AddPortMappingArgs[1].elt = "NewExternalPort";
 360	AddPortMappingArgs[1].val = extPort;
 361	AddPortMappingArgs[2].elt = "NewProtocol";
 362	AddPortMappingArgs[2].val = proto;
 363	AddPortMappingArgs[3].elt = "NewInternalPort";
 364	AddPortMappingArgs[3].val = inPort;
 365	AddPortMappingArgs[4].elt = "NewInternalClient";
 366	AddPortMappingArgs[4].val = inClient;
 367	AddPortMappingArgs[5].elt = "NewEnabled";
 368	AddPortMappingArgs[5].val = "1";
 369	AddPortMappingArgs[6].elt = "NewPortMappingDescription";
 370	AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
 371	AddPortMappingArgs[7].elt = "NewLeaseDuration";
 372	AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
 373	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 374	                                "AddPortMapping", AddPortMappingArgs,
 375	                                &bufsize))) {
 376		free(AddPortMappingArgs);
 377		return UPNPCOMMAND_HTTP_ERROR;
 378	}
 379	/*DisplayNameValueList(buffer, bufsize);*/
 380	/*buffer[bufsize] = '\0';*/
 381	/*puts(buffer);*/
 382	ParseNameValue(buffer, bufsize, &pdata);
 383	free(buffer); buffer = NULL;
 384	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 385	if(resVal) {
 386		/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
 387		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 388		sscanf(resVal, "%d", &ret);
 389	} else {
 390		ret = UPNPCOMMAND_SUCCESS;
 391	}
 392	ClearNameValueList(&pdata);
 393	free(AddPortMappingArgs);
 394	return ret;
 395}
 396
 397LIBSPEC int
 398UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
 399                       const char * extPort, const char * proto,
 400                       const char * remoteHost)
 401{
 402	/*struct NameValueParserData pdata;*/
 403	struct UPNParg * DeletePortMappingArgs;
 404	char * buffer;
 405	int bufsize;
 406	struct NameValueParserData pdata;
 407	const char * resVal;
 408	int ret;
 409
 410	if(!extPort || !proto)
 411		return UPNPCOMMAND_INVALID_ARGS;
 412
 413	DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
 414	DeletePortMappingArgs[0].elt = "NewRemoteHost";
 415	DeletePortMappingArgs[0].val = remoteHost;
 416	DeletePortMappingArgs[1].elt = "NewExternalPort";
 417	DeletePortMappingArgs[1].val = extPort;
 418	DeletePortMappingArgs[2].elt = "NewProtocol";
 419	DeletePortMappingArgs[2].val = proto;
 420	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 421	                               "DeletePortMapping",
 422	                               DeletePortMappingArgs, &bufsize))) {
 423		free(DeletePortMappingArgs);
 424		return UPNPCOMMAND_HTTP_ERROR;
 425	}
 426	/*DisplayNameValueList(buffer, bufsize);*/
 427	ParseNameValue(buffer, bufsize, &pdata);
 428	free(buffer); buffer = NULL;
 429	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 430	if(resVal) {
 431		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 432		sscanf(resVal, "%d", &ret);
 433	} else {
 434		ret = UPNPCOMMAND_SUCCESS;
 435	}
 436	ClearNameValueList(&pdata);
 437	free(DeletePortMappingArgs);
 438	return ret;
 439}
 440
 441LIBSPEC int
 442UPNP_GetGenericPortMappingEntry(const char * controlURL,
 443                                const char * servicetype,
 444							 const char * index,
 445							 char * extPort,
 446							 char * intClient,
 447							 char * intPort,
 448							 char * protocol,
 449							 char * desc,
 450							 char * enabled,
 451							 char * rHost,
 452							 char * duration)
 453{
 454	struct NameValueParserData pdata;
 455	struct UPNParg * GetPortMappingArgs;
 456	char * buffer;
 457	int bufsize;
 458	char * p;
 459	int r = UPNPCOMMAND_UNKNOWN_ERROR;
 460	if(!index)
 461		return UPNPCOMMAND_INVALID_ARGS;
 462	intClient[0] = '\0';
 463	intPort[0] = '\0';
 464	GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
 465	GetPortMappingArgs[0].elt = "NewPortMappingIndex";
 466	GetPortMappingArgs[0].val = index;
 467	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 468	                               "GetGenericPortMappingEntry",
 469	                               GetPortMappingArgs, &bufsize))) {
 470		free(GetPortMappingArgs);
 471		return UPNPCOMMAND_HTTP_ERROR;
 472	}
 473	ParseNameValue(buffer, bufsize, &pdata);
 474	free(buffer); buffer = NULL;
 475
 476	p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
 477	if(p && rHost)
 478	{
 479		strncpy(rHost, p, 64);
 480		rHost[63] = '\0';
 481	}
 482	p = GetValueFromNameValueList(&pdata, "NewExternalPort");
 483	if(p && extPort)
 484	{
 485		strncpy(extPort, p, 6);
 486		extPort[5] = '\0';
 487		r = UPNPCOMMAND_SUCCESS;
 488	}
 489	p = GetValueFromNameValueList(&pdata, "NewProtocol");
 490	if(p && protocol)
 491	{
 492		strncpy(protocol, p, 4);
 493		protocol[3] = '\0';
 494	}
 495	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
 496	if(p && intClient)
 497	{
 498		strncpy(intClient, p, 16);
 499		intClient[15] = '\0';
 500		r = 0;
 501	}
 502	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
 503	if(p && intPort)
 504	{
 505		strncpy(intPort, p, 6);
 506		intPort[5] = '\0';
 507	}
 508	p = GetValueFromNameValueList(&pdata, "NewEnabled");
 509	if(p && enabled)
 510	{
 511		strncpy(enabled, p, 4);
 512		enabled[3] = '\0';
 513	}
 514	p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
 515	if(p && desc)
 516	{
 517		strncpy(desc, p, 80);
 518		desc[79] = '\0';
 519	}
 520	p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
 521	if(p && duration)
 522	{
 523		strncpy(duration, p, 16);
 524		duration[15] = '\0';
 525	}
 526	p = GetValueFromNameValueList(&pdata, "errorCode");
 527	if(p) {
 528		r = UPNPCOMMAND_UNKNOWN_ERROR;
 529		sscanf(p, "%d", &r);
 530	}
 531	ClearNameValueList(&pdata);
 532	free(GetPortMappingArgs);
 533	return r;
 534}
 535
 536LIBSPEC int
 537UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
 538                                   const char * servicetype,
 539                                   unsigned int * numEntries)
 540{
 541 	struct NameValueParserData pdata;
 542 	char * buffer;
 543 	int bufsize;
 544 	char* p;
 545	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 546 	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 547	                                "GetPortMappingNumberOfEntries", 0,
 548	                                &bufsize))) {
 549		return UPNPCOMMAND_HTTP_ERROR;
 550	}
 551#ifdef DEBUG
 552	DisplayNameValueList(buffer, bufsize);
 553#endif
 554 	ParseNameValue(buffer, bufsize, &pdata);
 555	free(buffer); buffer = NULL;
 556
 557 	p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
 558 	if(numEntries && p) {
 559		*numEntries = 0;
 560 		sscanf(p, "%u", numEntries);
 561		ret = UPNPCOMMAND_SUCCESS;
 562 	}
 563
 564	p = GetValueFromNameValueList(&pdata, "errorCode");
 565	if(p) {
 566		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 567		sscanf(p, "%d", &ret);
 568	}
 569
 570 	ClearNameValueList(&pdata);
 571	return ret;
 572}
 573
 574/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
 575 * the result is returned in the intClient and intPort strings
 576 * please provide 16 and 6 bytes of data */
 577LIBSPEC int
 578UPNP_GetSpecificPortMappingEntry(const char * controlURL,
 579                                 const char * servicetype,
 580                                 const char * extPort,
 581							     const char * proto,
 582                                 char * intClient,
 583                                 char * intPort,
 584                                 char * desc,
 585                                 char * enabled,
 586                                 char * leaseDuration)
 587{
 588	struct NameValueParserData pdata;
 589	struct UPNParg * GetPortMappingArgs;
 590	char * buffer;
 591	int bufsize;
 592	char * p;
 593	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 594
 595	if(!intPort || !intClient || !extPort || !proto)
 596		return UPNPCOMMAND_INVALID_ARGS;
 597
 598	GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
 599	GetPortMappingArgs[0].elt = "NewRemoteHost";
 600	/* TODO : add remote host ? */
 601	GetPortMappingArgs[1].elt = "NewExternalPort";
 602	GetPortMappingArgs[1].val = extPort;
 603	GetPortMappingArgs[2].elt = "NewProtocol";
 604	GetPortMappingArgs[2].val = proto;
 605	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 606	                                "GetSpecificPortMappingEntry",
 607	                                GetPortMappingArgs, &bufsize))) {
 608		free(GetPortMappingArgs);
 609		return UPNPCOMMAND_HTTP_ERROR;
 610	}
 611	/*DisplayNameValueList(buffer, bufsize);*/
 612	ParseNameValue(buffer, bufsize, &pdata);
 613	free(buffer); buffer = NULL;
 614
 615	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
 616	if(p) {
 617		strncpy(intClient, p, 16);
 618		intClient[15] = '\0';
 619		ret = UPNPCOMMAND_SUCCESS;
 620	} else
 621		intClient[0] = '\0';
 622
 623	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
 624	if(p) {
 625		strncpy(intPort, p, 6);
 626		intPort[5] = '\0';
 627	} else
 628		intPort[0] = '\0';
 629
 630	p = GetValueFromNameValueList(&pdata, "NewEnabled");
 631	if(p && enabled) {
 632		strncpy(enabled, p, 4);
 633		enabled[3] = '\0';
 634	}
 635
 636	p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
 637	if(p && desc) {
 638		strncpy(desc, p, 80);
 639		desc[79] = '\0';
 640	}
 641
 642	p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
 643	if(p && leaseDuration)
 644	{
 645		strncpy(leaseDuration, p, 16);
 646		leaseDuration[15] = '\0';
 647	}
 648
 649	p = GetValueFromNameValueList(&pdata, "errorCode");
 650	if(p) {
 651		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 652		sscanf(p, "%d", &ret);
 653	}
 654
 655	ClearNameValueList(&pdata);
 656	free(GetPortMappingArgs);
 657	return ret;
 658}
 659
 660/* UPNP_GetListOfPortMappings()
 661 *
 662 * Possible UPNP Error codes :
 663 * 606 Action not Authorized
 664 * 730 PortMappingNotFound - no port mapping is found in the specified range.
 665 * 733 InconsistantParameters - NewStartPort and NewEndPort values are not
 666 *                              consistent.
 667 */
 668LIBSPEC int
 669UPNP_GetListOfPortMappings(const char * controlURL,
 670                           const char * servicetype,
 671                           const char * startPort,
 672                           const char * endPort,
 673                           const char * protocol,
 674                           const char * numberOfPorts,
 675                           struct PortMappingParserData * data)
 676{
 677	struct NameValueParserData pdata;
 678	struct UPNParg * GetListOfPortMappingsArgs;
 679	const char * p;
 680	char * buffer;
 681	int bufsize;
 682	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 683
 684	if(!startPort || !endPort || !protocol)
 685		return UPNPCOMMAND_INVALID_ARGS;
 686
 687	GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg));
 688	GetListOfPortMappingsArgs[0].elt = "NewStartPort";
 689	GetListOfPortMappingsArgs[0].val = startPort;
 690	GetListOfPortMappingsArgs[1].elt = "NewEndPort";
 691	GetListOfPortMappingsArgs[1].val = endPort;
 692	GetListOfPortMappingsArgs[2].elt = "NewProtocol";
 693	GetListOfPortMappingsArgs[2].val = protocol;
 694	GetListOfPortMappingsArgs[3].elt = "NewManage";
 695	GetListOfPortMappingsArgs[3].val = "1";
 696	GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts";
 697	GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000";
 698
 699	if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 700	                                "GetListOfPortMappings",
 701	                                GetListOfPortMappingsArgs, &bufsize))) {
 702		free(GetListOfPortMappingsArgs);
 703		return UPNPCOMMAND_HTTP_ERROR;
 704	}
 705	free(GetListOfPortMappingsArgs);
 706
 707	/*DisplayNameValueList(buffer, bufsize);*/
 708	ParseNameValue(buffer, bufsize, &pdata);
 709	free(buffer); buffer = NULL;
 710
 711	/*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/
 712	/*if(p) {
 713		printf("NewPortListing : %s\n", p);
 714	}*/
 715	/*printf("NewPortListing(%d chars) : %s\n",
 716	       pdata.portListingLength, pdata.portListing);*/
 717	if(pdata.portListing)
 718	{
 719		/*struct PortMapping * pm;
 720		int i = 0;*/
 721		ParsePortListing(pdata.portListing, pdata.portListingLength,
 722		                 data);
 723		ret = UPNPCOMMAND_SUCCESS;
 724		/*
 725		for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next)
 726		{
 727			printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n",
 728			       i, pm->protocol, pm->externalPort, pm->internalClient,
 729			       pm->internalPort,
 730			       pm->description, pm->remoteHost);
 731			i++;
 732		}
 733		*/
 734		/*FreePortListing(&data);*/
 735	}
 736
 737	p = GetValueFromNameValueList(&pdata, "errorCode");
 738	if(p) {
 739		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 740		sscanf(p, "%d", &ret);
 741	}
 742	ClearNameValueList(&pdata);
 743
 744	//printf("%.*s", bufsize, buffer);
 745
 746	return ret;
 747}
 748
 749/* IGD:2, functions for service WANIPv6FirewallControl:1 */ 
 750LIBSPEC int
 751UPNP_GetFirewallStatus(const char * controlURL,
 752				const char * servicetype,
 753				int * firewallEnabled, 
 754				int * inboundPinholeAllowed)
 755{
 756	struct NameValueParserData pdata;
 757	char * buffer;
 758	int bufsize;
 759	char * fe, *ipa, *p;
 760	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
 761
 762	if(!firewallEnabled && !inboundPinholeAllowed)
 763		return UPNPCOMMAND_INVALID_ARGS;
 764
 765	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 766	                           "GetFirewallStatus", 0, &bufsize);
 767	if(!buffer) {
 768		return UPNPCOMMAND_HTTP_ERROR;
 769	}
 770	ParseNameValue(buffer, bufsize, &pdata);
 771	free(buffer); buffer = NULL;
 772	fe = GetValueFromNameValueList(&pdata, "FirewallEnabled");
 773	ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed");
 774	if(ipa && fe)
 775		ret = UPNPCOMMAND_SUCCESS;
 776	if(fe)
 777		*firewallEnabled = my_atoui(fe);
 778	/*else
 779		*firewallEnabled = 0;*/
 780	if(ipa)
 781		*inboundPinholeAllowed = my_atoui(ipa);
 782	/*else
 783		*inboundPinholeAllowed = 0;*/
 784	p = GetValueFromNameValueList(&pdata, "errorCode");
 785	if(p)
 786	{
 787		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 788		sscanf(p, "%d", &ret);
 789	}
 790	ClearNameValueList(&pdata);
 791	return ret;
 792}
 793
 794LIBSPEC int
 795UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
 796                    const char * remoteHost,
 797                    const char * remotePort,
 798                    const char * intClient,
 799                    const char * intPort,
 800                    const char * proto,
 801                    int * opTimeout)
 802{
 803	struct UPNParg * GetOutboundPinholeTimeoutArgs;
 804	char * buffer;
 805	int bufsize;
 806	struct NameValueParserData pdata;
 807	const char * resVal;
 808	char * p;
 809	int ret;
 810
 811	if(!intPort || !intClient || !proto || !remotePort || !remoteHost)
 812		return UPNPCOMMAND_INVALID_ARGS;
 813
 814	GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg));
 815	GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost";
 816	GetOutboundPinholeTimeoutArgs[0].val = remoteHost;
 817	GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort";
 818	GetOutboundPinholeTimeoutArgs[1].val = remotePort;
 819	GetOutboundPinholeTimeoutArgs[2].elt = "Protocol";
 820	GetOutboundPinholeTimeoutArgs[2].val = proto;
 821	GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort";
 822	GetOutboundPinholeTimeoutArgs[3].val = intPort;
 823	GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient";
 824	GetOutboundPinholeTimeoutArgs[4].val = intClient;
 825	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 826	                           "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);
 827	if(!buffer)
 828		return UPNPCOMMAND_HTTP_ERROR;
 829	ParseNameValue(buffer, bufsize, &pdata);
 830	free(buffer); buffer = NULL;
 831	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 832	if(resVal)
 833	{
 834		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 835		sscanf(resVal, "%d", &ret);
 836	}
 837	else
 838	{
 839		ret = UPNPCOMMAND_SUCCESS;
 840		p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");
 841		if(p)
 842			*opTimeout = my_atoui(p);
 843	}
 844	ClearNameValueList(&pdata);
 845	free(GetOutboundPinholeTimeoutArgs);
 846	return ret;
 847}
 848
 849LIBSPEC int
 850UPNP_AddPinhole(const char * controlURL, const char * servicetype,
 851                    const char * remoteHost,
 852                    const char * remotePort,
 853                    const char * intClient,
 854                    const char * intPort,
 855                    const char * proto,
 856                    const char * leaseTime,
 857                    char * uniqueID)
 858{
 859	struct UPNParg * AddPinholeArgs;
 860	char * buffer;
 861	int bufsize;
 862	struct NameValueParserData pdata;
 863	const char * resVal;
 864	char * p;
 865	int ret;
 866
 867	if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime)
 868		return UPNPCOMMAND_INVALID_ARGS;
 869
 870	AddPinholeArgs = calloc(7, sizeof(struct UPNParg));
 871	// RemoteHost can be wilcarded
 872	if(strncmp(remoteHost, "empty", 5)==0)
 873	{
 874		AddPinholeArgs[0].elt = "RemoteHost";
 875		AddPinholeArgs[0].val = "";
 876	}
 877	else
 878	{
 879		AddPinholeArgs[0].elt = "RemoteHost";
 880		AddPinholeArgs[0].val = remoteHost;
 881	}
 882	AddPinholeArgs[1].elt = "RemotePort";
 883	AddPinholeArgs[1].val = remotePort;
 884	AddPinholeArgs[2].elt = "Protocol";
 885	AddPinholeArgs[2].val = proto;
 886	AddPinholeArgs[3].elt = "InternalPort";
 887	AddPinholeArgs[3].val = intPort;
 888	if(strncmp(intClient, "empty", 5)==0)
 889	{
 890		AddPinholeArgs[4].elt = "InternalClient";
 891		AddPinholeArgs[4].val = "";
 892	}
 893	else
 894	{
 895		AddPinholeArgs[4].elt = "InternalClient";
 896		AddPinholeArgs[4].val = intClient;
 897	}
 898	AddPinholeArgs[5].elt = "LeaseTime";
 899	AddPinholeArgs[5].val = leaseTime;
 900	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 901	                           "AddPinhole", AddPinholeArgs, &bufsize);
 902	if(!buffer)
 903		return UPNPCOMMAND_HTTP_ERROR;
 904	ParseNameValue(buffer, bufsize, &pdata);
 905	free(buffer); buffer = NULL;
 906	p = GetValueFromNameValueList(&pdata, "UniqueID");
 907	if(p)
 908	{
 909		strncpy(uniqueID, p, 8);
 910		uniqueID[7] = '\0';
 911	}
 912	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 913	if(resVal)
 914	{
 915		//printf("AddPortMapping errorCode = '%s'\n", resVal); 
 916		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 917		sscanf(resVal, "%d", &ret);
 918	}
 919	else
 920	{
 921		ret = UPNPCOMMAND_SUCCESS;
 922	}
 923	ClearNameValueList(&pdata);
 924	free(AddPinholeArgs);
 925	return ret;
 926}
 927
 928LIBSPEC int
 929UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
 930                    const char * uniqueID,
 931                    const char * leaseTime)
 932{
 933	struct UPNParg * UpdatePinholeArgs;
 934	char * buffer;
 935	int bufsize;
 936	struct NameValueParserData pdata;
 937	const char * resVal;
 938	int ret;
 939
 940	if(!uniqueID || !leaseTime)
 941		return UPNPCOMMAND_INVALID_ARGS;
 942
 943	UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg));
 944	UpdatePinholeArgs[0].elt = "UniqueID";
 945	UpdatePinholeArgs[0].val = uniqueID;
 946	UpdatePinholeArgs[1].elt = "NewLeaseTime";
 947	UpdatePinholeArgs[1].val = leaseTime;
 948	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 949	                           "UpdatePinhole", UpdatePinholeArgs, &bufsize);
 950	if(!buffer)
 951		return UPNPCOMMAND_HTTP_ERROR;
 952	ParseNameValue(buffer, bufsize, &pdata);
 953	free(buffer); buffer = NULL;
 954	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 955	if(resVal)
 956	{
 957		/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
 958		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 959		sscanf(resVal, "%d", &ret);
 960	}
 961	else
 962	{
 963		ret = UPNPCOMMAND_SUCCESS;
 964	}
 965	ClearNameValueList(&pdata);
 966	free(UpdatePinholeArgs);
 967	return ret;
 968}
 969
 970LIBSPEC int
 971UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID)
 972{
 973	/*struct NameValueParserData pdata;*/
 974	struct UPNParg * DeletePinholeArgs;
 975	char * buffer;
 976	int bufsize;
 977	struct NameValueParserData pdata;
 978	const char * resVal;
 979	int ret;
 980
 981	if(!uniqueID)
 982		return UPNPCOMMAND_INVALID_ARGS;
 983
 984	DeletePinholeArgs = calloc(2, sizeof(struct UPNParg));
 985	DeletePinholeArgs[0].elt = "UniqueID";
 986	DeletePinholeArgs[0].val = uniqueID;
 987	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
 988	                           "DeletePinhole", DeletePinholeArgs, &bufsize);
 989	if(!buffer)
 990		return UPNPCOMMAND_HTTP_ERROR;
 991	/*DisplayNameValueList(buffer, bufsize);*/
 992	ParseNameValue(buffer, bufsize, &pdata);
 993	free(buffer); buffer = NULL;
 994	resVal = GetValueFromNameValueList(&pdata, "errorCode");
 995	if(resVal)
 996	{
 997		ret = UPNPCOMMAND_UNKNOWN_ERROR;
 998		sscanf(resVal, "%d", &ret);
 999	}
1000	else
1001	{
1002		ret = UPNPCOMMAND_SUCCESS;
1003	}
1004	ClearNameValueList(&pdata);
1005	free(DeletePinholeArgs);
1006	return ret;
1007}
1008
1009LIBSPEC int
1010UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
1011                                 const char * uniqueID, int * isWorking)
1012{
1013	struct NameValueParserData pdata;
1014	struct UPNParg * CheckPinholeWorkingArgs;
1015	char * buffer;
1016	int bufsize;
1017	char * p;
1018	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
1019
1020	if(!uniqueID)
1021		return UPNPCOMMAND_INVALID_ARGS;
1022
1023	CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg));
1024	CheckPinholeWorkingArgs[0].elt = "UniqueID";
1025	CheckPinholeWorkingArgs[0].val = uniqueID;
1026	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
1027	                           "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);
1028	if(!buffer)
1029		return UPNPCOMMAND_HTTP_ERROR;
1030	ParseNameValue(buffer, bufsize, &pdata);
1031	free(buffer); buffer = NULL;
1032
1033	p = GetValueFromNameValueList(&pdata, "IsWorking");
1034	if(p)
1035	{
1036		*isWorking=my_atoui(p);
1037		ret = UPNPCOMMAND_SUCCESS;
1038	}
1039	else
1040		*isWorking = 0;
1041
1042	p = GetValueFromNameValueList(&pdata, "errorCode");
1043	if(p)
1044	{
1045		ret = UPNPCOMMAND_UNKNOWN_ERROR;
1046		sscanf(p, "%d", &ret);
1047	}
1048
1049	ClearNameValueList(&pdata);
1050	free(CheckPinholeWorkingArgs);
1051	return ret;
1052}
1053
1054LIBSPEC int
1055UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
1056                                 const char * uniqueID, int * packets)
1057{
1058	struct NameValueParserData pdata;
1059	struct UPNParg * GetPinholePacketsArgs;
1060	char * buffer;
1061	int bufsize;
1062	char * p;
1063	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
1064
1065	if(!uniqueID)
1066		return UPNPCOMMAND_INVALID_ARGS;
1067
1068	GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg));
1069	GetPinholePacketsArgs[0].elt = "UniqueID";
1070	GetPinholePacketsArgs[0].val = uniqueID;
1071	buffer = simpleUPnPcommand(-1, controlURL, servicetype,
1072	                           "GetPinholePackets", GetPinholePacketsArgs, &bufsize);
1073	if(!buffer)
1074		return UPNPCOMMAND_HTTP_ERROR;
1075	ParseNameValue(buffer, bufsize, &pdata);
1076	free(buffer); buffer = NULL;
1077
1078	p = GetValueFromNameValueList(&pdata, "PinholePackets");
1079	if(p)
1080	{
1081		*packets=my_atoui(p);
1082		ret = UPNPCOMMAND_SUCCESS;
1083	}
1084
1085	p = GetValueFromNameValueList(&pdata, "errorCode");
1086	if(p)
1087	{
1088		ret = UPNPCOMMAND_UNKNOWN_ERROR;
1089		sscanf(p, "%d", &ret);
1090	}
1091
1092	ClearNameValueList(&pdata);
1093	free(GetPinholePacketsArgs);
1094	return ret;
1095}
1096
1097