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