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