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
17static UNSIGNED_INTEGER
18my_atoui(const char * s)
19{
20 return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;
21}
22
23/*
24 * */
25MINIUPNP_LIBSPEC UNSIGNED_INTEGER
26UPNP_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 * */
49MINIUPNP_LIBSPEC UNSIGNED_INTEGER
50UPNP_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 * */
73MINIUPNP_LIBSPEC UNSIGNED_INTEGER
74UPNP_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 * */
97MINIUPNP_LIBSPEC UNSIGNED_INTEGER
98UPNP_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 */
121MINIUPNP_LIBSPEC int
122UPNP_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 */
186MINIUPNP_LIBSPEC int
187UPNP_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 */
229MINIUPNP_LIBSPEC int
230UPNP_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 */
298MINIUPNP_LIBSPEC int
299UPNP_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
338MINIUPNP_LIBSPEC int
339UPNP_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
401MINIUPNP_LIBSPEC int
402UPNP_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
470MINIUPNP_LIBSPEC int
471UPNP_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
516MINIUPNP_LIBSPEC int
517UPNP_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
564MINIUPNP_LIBSPEC int
565UPNP_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
661MINIUPNP_LIBSPEC int
662UPNP_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 */
702MINIUPNP_LIBSPEC int
703UPNP_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 */
796MINIUPNP_LIBSPEC int
797UPNP_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 */
880MINIUPNP_LIBSPEC int
881UPNP_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
924MINIUPNP_LIBSPEC int
925UPNP_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
980MINIUPNP_LIBSPEC int
981UPNP_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
1061MINIUPNP_LIBSPEC int
1062UPNP_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
1105MINIUPNP_LIBSPEC int
1106UPNP_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
1146MINIUPNP_LIBSPEC int
1147UPNP_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
1195MINIUPNP_LIBSPEC int
1196UPNP_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