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