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