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