• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/third-party/miniupnp/
1/* $Id: upnpcommands.c,v 1.39 2012/04/09 12:49:27 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
1098