mupnp 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,569 @@
1
+ /* $Id: upnpcommands.c,v 1.19 2008/02/18 13:27:23 nanard Exp $ */
2
+ /* Project : miniupnp
3
+ * Author : Thomas Bernard
4
+ * Copyright (c) 2005 Thomas Bernard
5
+ * This software is subject to the conditions detailed in the
6
+ * LICENCE file provided in this distribution.
7
+ * */
8
+ #include <stdlib.h>
9
+ #include <stdio.h>
10
+ #include <string.h>
11
+ #include "upnpcommands.h"
12
+ #include "miniupnpc.h"
13
+
14
+ static unsigned int
15
+ my_atoui(const char * s)
16
+ {
17
+ return s ? ((unsigned int)strtoul(s, NULL, 0)) : 0;
18
+ }
19
+
20
+ /*
21
+ * */
22
+ unsigned int
23
+ UPNP_GetTotalBytesSent(const char * controlURL,
24
+ const char * servicetype)
25
+ {
26
+ struct NameValueParserData pdata;
27
+ char buffer[4096];
28
+ int bufsize = 4096;
29
+ unsigned int r = 0;
30
+ char * p;
31
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize);
32
+ ParseNameValue(buffer, bufsize, &pdata);
33
+ /*DisplayNameValueList(buffer, bufsize);*/
34
+ p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
35
+ r = my_atoui(p);
36
+ ClearNameValueList(&pdata);
37
+ return r;
38
+ }
39
+
40
+ /*
41
+ * */
42
+ unsigned int
43
+ UPNP_GetTotalBytesReceived(const char * controlURL,
44
+ const char * servicetype)
45
+ {
46
+ struct NameValueParserData pdata;
47
+ char buffer[4096];
48
+ int bufsize = 4096;
49
+ unsigned int r = 0;
50
+ char * p;
51
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize);
52
+ ParseNameValue(buffer, bufsize, &pdata);
53
+ /*DisplayNameValueList(buffer, bufsize);*/
54
+ p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
55
+ r = my_atoui(p);
56
+ ClearNameValueList(&pdata);
57
+ return r;
58
+ }
59
+
60
+ /*
61
+ * */
62
+ unsigned int
63
+ UPNP_GetTotalPacketsSent(const char * controlURL,
64
+ const char * servicetype)
65
+ {
66
+ struct NameValueParserData pdata;
67
+ char buffer[4096];
68
+ int bufsize = 4096;
69
+ unsigned int r = 0;
70
+ char * p;
71
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize);
72
+ ParseNameValue(buffer, bufsize, &pdata);
73
+ /*DisplayNameValueList(buffer, bufsize);*/
74
+ p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
75
+ r = my_atoui(p);
76
+ ClearNameValueList(&pdata);
77
+ return r;
78
+ }
79
+
80
+ /*
81
+ * */
82
+ unsigned int
83
+ UPNP_GetTotalPacketsReceived(const char * controlURL,
84
+ const char * servicetype)
85
+ {
86
+ struct NameValueParserData pdata;
87
+ char buffer[4096];
88
+ int bufsize = 4096;
89
+ unsigned int r = 0;
90
+ char * p;
91
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize);
92
+ ParseNameValue(buffer, bufsize, &pdata);
93
+ /*DisplayNameValueList(buffer, bufsize);*/
94
+ p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
95
+ r = my_atoui(p);
96
+ ClearNameValueList(&pdata);
97
+ return r;
98
+ }
99
+
100
+ /* UPNP_GetStatusInfo() call the corresponding UPNP method
101
+ * returns the current status and uptime */
102
+ int UPNP_GetStatusInfo(const char * controlURL,
103
+ const char * servicetype,
104
+ char * status,
105
+ unsigned int * uptime,
106
+ char * lastconnerror)
107
+ {
108
+ struct NameValueParserData pdata;
109
+ char buffer[4096];
110
+ int bufsize = 4096;
111
+ char * p;
112
+ char * up;
113
+ char * err;
114
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
115
+
116
+ if(!status && !uptime)
117
+ return UPNPCOMMAND_INVALID_ARGS;
118
+
119
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize);
120
+ ParseNameValue(buffer, bufsize, &pdata);
121
+ /*DisplayNameValueList(buffer, bufsize);*/
122
+ up = GetValueFromNameValueList(&pdata, "NewUptime");
123
+ p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
124
+ err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
125
+ if(p && up)
126
+ ret = UPNPCOMMAND_SUCCESS;
127
+
128
+ if(status) {
129
+ if(p){
130
+ strncpy(status, p, 64 );
131
+ status[63] = '\0';
132
+ }else
133
+ status[0]= '\0';
134
+ }
135
+
136
+ if(uptime) {
137
+ if(up)
138
+ sscanf(up,"%u",uptime);
139
+ else
140
+ uptime = 0;
141
+ }
142
+
143
+ if(lastconnerror) {
144
+ if(err) {
145
+ strncpy(lastconnerror, err, 64 );
146
+ lastconnerror[63] = '\0';
147
+ } else
148
+ lastconnerror[0] = '\0';
149
+ }
150
+
151
+ p = GetValueFromNameValueList(&pdata, "errorCode");
152
+ if(p) {
153
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
154
+ sscanf(p, "%d", &ret);
155
+ }
156
+ ClearNameValueList(&pdata);
157
+ return ret;
158
+ }
159
+
160
+ /* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
161
+ * returns the connection type */
162
+ int UPNP_GetConnectionTypeInfo(const char * controlURL,
163
+ const char * servicetype,
164
+ char * connectionType)
165
+ {
166
+ struct NameValueParserData pdata;
167
+ char buffer[4096];
168
+ int bufsize = 4096;
169
+ char * p;
170
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
171
+
172
+ if(!connectionType)
173
+ return UPNPCOMMAND_INVALID_ARGS;
174
+
175
+ simpleUPnPcommand(-1, controlURL, servicetype,
176
+ "GetConnectionTypeInfo", 0, buffer, &bufsize);
177
+ ParseNameValue(buffer, bufsize, &pdata);
178
+ p = GetValueFromNameValueList(&pdata, "NewConnectionType");
179
+ /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
180
+ /* PossibleConnectionTypes will have several values.... */
181
+ if(p) {
182
+ strncpy(connectionType, p, 64 );
183
+ connectionType[63] = '\0';
184
+ ret = UPNPCOMMAND_SUCCESS;
185
+ } else
186
+ connectionType[0] = '\0';
187
+ p = GetValueFromNameValueList(&pdata, "errorCode");
188
+ if(p) {
189
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
190
+ sscanf(p, "%d", &ret);
191
+ }
192
+ ClearNameValueList(&pdata);
193
+ return ret;
194
+ }
195
+
196
+ /* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
197
+ * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
198
+ * One of the values can be null
199
+ * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
200
+ * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
201
+ int UPNP_GetLinkLayerMaxBitRates(const char * controlURL, const char * servicetype, unsigned int * bitrateDown, unsigned int* bitrateUp)
202
+ {
203
+ struct NameValueParserData pdata;
204
+ char buffer[4096];
205
+ int bufsize = 4096;
206
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
207
+ char * down;
208
+ char * up;
209
+ char * p;
210
+
211
+ if(!bitrateDown && !bitrateUp)
212
+ return UPNPCOMMAND_INVALID_ARGS;
213
+
214
+ /* shouldn't we use GetCommonLinkProperties ? */
215
+ simpleUPnPcommand(-1, controlURL, servicetype,
216
+ "GetCommonLinkProperties", 0, buffer, &bufsize);
217
+ /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
218
+ /*DisplayNameValueList(buffer, bufsize);*/
219
+ ParseNameValue(buffer, bufsize, &pdata);
220
+ /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
221
+ /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
222
+ down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
223
+ up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
224
+ /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
225
+ /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/
226
+ if(down && up)
227
+ ret = UPNPCOMMAND_SUCCESS;
228
+
229
+ if(bitrateDown)
230
+ {
231
+ if(down)
232
+ sscanf(down,"%u",bitrateDown);
233
+ else
234
+ *bitrateDown = 0;
235
+ }
236
+
237
+ if(bitrateUp)
238
+ {
239
+ if(up)
240
+ sscanf(up,"%u",bitrateUp);
241
+ else
242
+ *bitrateUp = 0;
243
+ }
244
+ p = GetValueFromNameValueList(&pdata, "errorCode");
245
+ if(p) {
246
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
247
+ sscanf(p, "%d", &ret);
248
+ }
249
+ ClearNameValueList(&pdata);
250
+ return ret;
251
+ }
252
+
253
+
254
+ /* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
255
+ * if the third arg is not null the value is copied to it.
256
+ * at least 16 bytes must be available
257
+ *
258
+ * Return values :
259
+ * 0 : SUCCESS
260
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
261
+ *
262
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
263
+ * 501 Action Failed - See UPnP Device Architecture section on Control.
264
+ */
265
+ int UPNP_GetExternalIPAddress(const char * controlURL,
266
+ const char * servicetype,
267
+ char * extIpAdd)
268
+ {
269
+ struct NameValueParserData pdata;
270
+ char buffer[4096];
271
+ int bufsize = 4096;
272
+ char * p;
273
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
274
+
275
+ if(!extIpAdd || !controlURL || !servicetype)
276
+ return UPNPCOMMAND_INVALID_ARGS;
277
+
278
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize);
279
+ /*DisplayNameValueList(buffer, bufsize);*/
280
+ ParseNameValue(buffer, bufsize, &pdata);
281
+ /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
282
+ p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
283
+ if(p) {
284
+ strncpy(extIpAdd, p, 16 );
285
+ extIpAdd[15] = '\0';
286
+ ret = UPNPCOMMAND_SUCCESS;
287
+ } else
288
+ extIpAdd[0] = '\0';
289
+
290
+ p = GetValueFromNameValueList(&pdata, "errorCode");
291
+ if(p) {
292
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
293
+ sscanf(p, "%d", &ret);
294
+ }
295
+
296
+ ClearNameValueList(&pdata);
297
+ return ret;
298
+ }
299
+
300
+ int
301
+ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
302
+ const char * extPort,
303
+ const char * inPort,
304
+ const char * inClient,
305
+ const char * desc,
306
+ const char * proto)
307
+ {
308
+ struct UPNParg * AddPortMappingArgs;
309
+ char buffer[4096];
310
+ int bufsize = 4096;
311
+ struct NameValueParserData pdata;
312
+ const char * resVal;
313
+ int ret;
314
+
315
+ if(!inPort || !inClient || !proto || !extPort)
316
+ return UPNPCOMMAND_INVALID_ARGS;
317
+
318
+ AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
319
+ AddPortMappingArgs[0].elt = "NewRemoteHost";
320
+ AddPortMappingArgs[1].elt = "NewExternalPort";
321
+ AddPortMappingArgs[1].val = extPort;
322
+ AddPortMappingArgs[2].elt = "NewProtocol";
323
+ AddPortMappingArgs[2].val = proto;
324
+ AddPortMappingArgs[3].elt = "NewInternalPort";
325
+ AddPortMappingArgs[3].val = inPort;
326
+ AddPortMappingArgs[4].elt = "NewInternalClient";
327
+ AddPortMappingArgs[4].val = inClient;
328
+ AddPortMappingArgs[5].elt = "NewEnabled";
329
+ AddPortMappingArgs[5].val = "1";
330
+ AddPortMappingArgs[6].elt = "NewPortMappingDescription";
331
+ AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
332
+ AddPortMappingArgs[7].elt = "NewLeaseDuration";
333
+ AddPortMappingArgs[7].val = "0";
334
+ simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize);
335
+ /*DisplayNameValueList(buffer, bufsize);*/
336
+ /*buffer[bufsize] = '\0';*/
337
+ /*puts(buffer);*/
338
+ ParseNameValue(buffer, bufsize, &pdata);
339
+ resVal = GetValueFromNameValueList(&pdata, "errorCode");
340
+ if(resVal) {
341
+ /*printf("AddPortMapping errorCode = '%s'\n", resVal); */
342
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
343
+ sscanf(resVal, "%d", &ret);
344
+ } else {
345
+ ret = UPNPCOMMAND_SUCCESS;
346
+ }
347
+ ClearNameValueList(&pdata);
348
+ free(AddPortMappingArgs);
349
+ return ret;
350
+ }
351
+
352
+ int
353
+ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
354
+ const char * extPort, const char * proto)
355
+ {
356
+ /*struct NameValueParserData pdata;*/
357
+ struct UPNParg * DeletePortMappingArgs;
358
+ char buffer[4096];
359
+ int bufsize = 4096;
360
+ struct NameValueParserData pdata;
361
+ const char * resVal;
362
+ int ret;
363
+
364
+ if(!extPort || !proto)
365
+ return UPNPCOMMAND_INVALID_ARGS;
366
+
367
+ DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
368
+ DeletePortMappingArgs[0].elt = "NewRemoteHost";
369
+ DeletePortMappingArgs[1].elt = "NewExternalPort";
370
+ DeletePortMappingArgs[1].val = extPort;
371
+ DeletePortMappingArgs[2].elt = "NewProtocol";
372
+ DeletePortMappingArgs[2].val = proto;
373
+ simpleUPnPcommand(-1, controlURL, servicetype,
374
+ "DeletePortMapping",
375
+ DeletePortMappingArgs, buffer, &bufsize);
376
+ /*DisplayNameValueList(buffer, bufsize);*/
377
+ ParseNameValue(buffer, bufsize, &pdata);
378
+ resVal = GetValueFromNameValueList(&pdata, "errorCode");
379
+ if(resVal) {
380
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
381
+ sscanf(resVal, "%d", &ret);
382
+ } else {
383
+ ret = UPNPCOMMAND_SUCCESS;
384
+ }
385
+ ClearNameValueList(&pdata);
386
+ free(DeletePortMappingArgs);
387
+ return ret;
388
+ }
389
+
390
+ int UPNP_GetGenericPortMappingEntry(const char * controlURL,
391
+ const char * servicetype,
392
+ const char * index,
393
+ char * extPort,
394
+ char * intClient,
395
+ char * intPort,
396
+ char * protocol,
397
+ char * desc,
398
+ char * enabled,
399
+ char * rHost,
400
+ char * duration)
401
+ {
402
+ struct NameValueParserData pdata;
403
+ struct UPNParg * GetPortMappingArgs;
404
+ char buffer[4096];
405
+ int bufsize = 4096;
406
+ char * p;
407
+ int r = UPNPCOMMAND_UNKNOWN_ERROR;
408
+ if(!index)
409
+ return UPNPCOMMAND_INVALID_ARGS;
410
+ intClient[0] = '\0';
411
+ intPort[0] = '\0';
412
+ GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
413
+ GetPortMappingArgs[0].elt = "NewPortMappingIndex";
414
+ GetPortMappingArgs[0].val = index;
415
+ simpleUPnPcommand(-1, controlURL, servicetype,
416
+ "GetGenericPortMappingEntry",
417
+ GetPortMappingArgs, buffer, &bufsize);
418
+ ParseNameValue(buffer, bufsize, &pdata);
419
+ p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
420
+ if(p && rHost)
421
+ {
422
+ strncpy(rHost, p, 64);
423
+ rHost[63] = '\0';
424
+ }
425
+ p = GetValueFromNameValueList(&pdata, "NewExternalPort");
426
+ if(p && extPort)
427
+ {
428
+ strncpy(extPort, p, 6);
429
+ extPort[5] = '\0';
430
+ r = UPNPCOMMAND_SUCCESS;
431
+ }
432
+ p = GetValueFromNameValueList(&pdata, "NewProtocol");
433
+ if(p && protocol)
434
+ {
435
+ strncpy(protocol, p, 4);
436
+ protocol[3] = '\0';
437
+ }
438
+ p = GetValueFromNameValueList(&pdata, "NewInternalClient");
439
+ if(p && intClient)
440
+ {
441
+ strncpy(intClient, p, 16);
442
+ intClient[15] = '\0';
443
+ r = 0;
444
+ }
445
+ p = GetValueFromNameValueList(&pdata, "NewInternalPort");
446
+ if(p && intPort)
447
+ {
448
+ strncpy(intPort, p, 6);
449
+ intPort[5] = '\0';
450
+ }
451
+ p = GetValueFromNameValueList(&pdata, "NewEnabled");
452
+ if(p && enabled)
453
+ {
454
+ strncpy(enabled, p, 4);
455
+ enabled[3] = '\0';
456
+ }
457
+ p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
458
+ if(p && desc)
459
+ {
460
+ strncpy(desc, p, 80);
461
+ desc[79] = '\0';
462
+ }
463
+ p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
464
+ if(p && duration)
465
+ {
466
+ strncpy(duration, p, 16);
467
+ duration[15] = '\0';
468
+ }
469
+ p = GetValueFromNameValueList(&pdata, "errorCode");
470
+ if(p) {
471
+ r = UPNPCOMMAND_UNKNOWN_ERROR;
472
+ sscanf(p, "%d", &r);
473
+ }
474
+ ClearNameValueList(&pdata);
475
+ free(GetPortMappingArgs);
476
+ return r;
477
+ }
478
+
479
+ int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries)
480
+ {
481
+ struct NameValueParserData pdata;
482
+ char buffer[4096];
483
+ int bufsize = 4096;
484
+ char* p;
485
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
486
+ simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
487
+ #ifndef NDEBUG
488
+ DisplayNameValueList(buffer, bufsize);
489
+ #endif
490
+ ParseNameValue(buffer, bufsize, &pdata);
491
+
492
+ p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
493
+ if(numEntries && p) {
494
+ *numEntries = 0;
495
+ sscanf(p, "%u", numEntries);
496
+ ret = UPNPCOMMAND_SUCCESS;
497
+ }
498
+
499
+ p = GetValueFromNameValueList(&pdata, "errorCode");
500
+ if(p) {
501
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
502
+ sscanf(p, "%d", &ret);
503
+ }
504
+
505
+ ClearNameValueList(&pdata);
506
+ return ret;
507
+ }
508
+
509
+ /* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
510
+ * the result is returned in the intClient and intPort strings
511
+ * please provide 16 and 6 bytes of data */
512
+ int
513
+ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
514
+ const char * servicetype,
515
+ const char * extPort,
516
+ const char * proto,
517
+ char * intClient,
518
+ char * intPort)
519
+ {
520
+ struct NameValueParserData pdata;
521
+ struct UPNParg * GetPortMappingArgs;
522
+ char buffer[4096];
523
+ int bufsize = 4096;
524
+ char * p;
525
+ int ret = UPNPCOMMAND_UNKNOWN_ERROR;
526
+
527
+ if(!intPort || !intClient || !extPort || !proto)
528
+ return UPNPCOMMAND_INVALID_ARGS;
529
+
530
+ GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
531
+ GetPortMappingArgs[0].elt = "NewRemoteHost";
532
+ GetPortMappingArgs[1].elt = "NewExternalPort";
533
+ GetPortMappingArgs[1].val = extPort;
534
+ GetPortMappingArgs[2].elt = "NewProtocol";
535
+ GetPortMappingArgs[2].val = proto;
536
+ simpleUPnPcommand(-1, controlURL, servicetype,
537
+ "GetSpecificPortMappingEntry",
538
+ GetPortMappingArgs, buffer, &bufsize);
539
+ /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
540
+ /*DisplayNameValueList(buffer, bufsize);*/
541
+ ParseNameValue(buffer, bufsize, &pdata);
542
+
543
+ p = GetValueFromNameValueList(&pdata, "NewInternalClient");
544
+ if(p) {
545
+ strncpy(intClient, p, 16);
546
+ intClient[15] = '\0';
547
+ ret = UPNPCOMMAND_SUCCESS;
548
+ } else
549
+ intClient[0] = '\0';
550
+
551
+ p = GetValueFromNameValueList(&pdata, "NewInternalPort");
552
+ if(p) {
553
+ strncpy(intPort, p, 6);
554
+ intPort[5] = '\0';
555
+ } else
556
+ intPort[0] = '\0';
557
+
558
+ p = GetValueFromNameValueList(&pdata, "errorCode");
559
+ if(p) {
560
+ ret = UPNPCOMMAND_UNKNOWN_ERROR;
561
+ sscanf(p, "%d", &ret);
562
+ }
563
+
564
+ ClearNameValueList(&pdata);
565
+ free(GetPortMappingArgs);
566
+ return ret;
567
+ }
568
+
569
+