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