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