1/* $Id: upnpc.c,v 1.105 2014/11/01 10:37:32 nanard Exp $ */ 2/* Project : miniupnp 3 * Author : Thomas Bernard 4 * Copyright (c) 2005-2014 Thomas Bernard 5 * This software is subject to the conditions detailed in the 6 * LICENCE file provided in this distribution. */ 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <time.h> 12#ifdef _WIN32 13#include <winsock2.h> 14#define snprintf _snprintf 15#else 16/* for IPPROTO_TCP / IPPROTO_UDP */ 17#include <netinet/in.h> 18#endif 19#include "miniwget.h" 20#include "miniupnpc.h" 21#include "upnpcommands.h" 22#include "upnperrors.h" 23 24#include <shared.h> 25#include <sys/ipc.h> 26#include <sys/shm.h> 27#include <sys/sysinfo.h> 28#include <errno.h> 29 30#ifdef RTCONFIG_JFFS2USERICON 31#define JFFS_ICON_PATH "/jffs/usericon" 32#define UPNP_ICON_PATH "/tmp/upnpicon" 33 34typedef struct { 35 unsigned char ip_addr[255][4]; 36 unsigned char mac_addr[255][6]; 37 unsigned char user_define[255][16]; 38 unsigned char device_name[255][32]; 39 unsigned char apl_dev[255][16]; 40 int type[255]; 41 int http[255]; 42 int printer[255]; 43 int itune[255]; 44 int exist[255]; 45#ifdef RTCONFIG_BWDPI 46 char bwdpi_hostname[255][32]; 47 char bwdpi_devicetype[255][100]; 48#endif 49 int ip_mac_num; 50 int detail_info_num; 51} CLIENT_DETAIL_INFO_TABLE, *P_CLIENT_DETAIL_INFO_TABLE; 52 53//the crc32 of Windows related icon 54unsigned long default_icon_crc[] = { 55 0xeefa6488, 56 0x0798893a, 57 0xe06e1235, 58 0xb54fd1af, 59 0xc9c2b6c4, 60 0xbaa4c50b, 61 0xcec591e3, 62 0 63}; 64 65typedef struct IconFile { 66 char name[12]; 67 struct IconFile *next; 68}IconFile; 69 70struct IconFile *IconList = NULL; 71 72struct UPNPDevInfo IGDInfo; 73 74static char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 75 76int 77openvpn_base64_encode(const void *data, int size, char **str) { 78 char *s, *p; 79 int i; 80 int c; 81 const unsigned char *q; 82 83 if (size < 0) 84 return -1; 85 p = s = (char *) malloc(size * 4 / 3 + 4); 86 if (p == NULL) 87 return -1; 88 q = (const unsigned char *) data; 89 i = 0; 90 for (i = 0; i < size;) { 91 c = q[i++]; 92 c *= 256; 93 if (i < size) 94 c += q[i]; 95 i++; 96 c *= 256; 97 if (i < size) 98 c += q[i]; 99 i++; 100 p[0] = base64_chars[(c & 0x00fc0000) >> 18]; 101 p[1] = base64_chars[(c & 0x0003f000) >> 12]; 102 p[2] = base64_chars[(c & 0x00000fc0) >> 6]; 103 p[3] = base64_chars[(c & 0x0000003f) >> 0]; 104 if (i > size) 105 p[3] = '='; 106 if (i > size + 1) 107 p[2] = '='; 108 p += 4; 109 } 110 *p = 0; 111 *str = s; 112 113 return strlen(s); 114} 115 116int 117image_to_base64(char *file_path, char *client_mac) { 118 FILE * pFile; 119 long lSize; 120 char *buffer; 121 char *base64; 122 size_t result; 123 int i; 124 char client_mac_temp[15]; 125 memset(client_mac_temp, 0, sizeof(client_mac_temp)); 126 sprintf(client_mac_temp, client_mac); 127 128printf("Store %s to jffs -> %s!!!\n", file_path, client_mac); 129 int idex = 0; 130 while ( client_mac_temp[idex] != 0 ) { 131 if ( ( client_mac_temp[idex] >= 'a' ) && ( client_mac_temp[idex] <= 'z' ) ) { 132 client_mac_temp[idex] = client_mac_temp[idex] - 'a' + 'A'; 133 } 134 idex++; 135 } 136 137 pFile = fopen (file_path , "rb"); 138 if (pFile == NULL) { 139 printf("File error\n"); 140 i = 0; 141 return i; 142 } 143 144 fseek (pFile , 0 , SEEK_END); 145 lSize = ftell (pFile); 146 rewind (pFile); 147 148 buffer = (char*) malloc (sizeof(char)*lSize); 149 base64 = (char*) malloc (sizeof(char)*lSize); 150 151 if (buffer == NULL) { 152 printf("Memory error\n"); 153 i = 0; 154 return i; 155 } 156 157 result = fread (buffer,1,lSize,pFile); 158 if (result != lSize) { 159 printf("Reading error\n"); 160 i = 0; 161 return i; 162 } 163 164 if (openvpn_base64_encode (buffer, lSize, &base64) <= 0) { 165 printf("binary encode error \n"); 166 i = 0; 167 return i; 168 } 169 170 char image_base64[(strlen(base64) + 25)]; 171 memset(image_base64, 0, sizeof(image_base64)); 172 173 sprintf(image_base64, "data:image/jpeg;base64,"); 174 strcat(image_base64, base64); 175 176 fclose (pFile); 177 free (buffer); 178 free (base64); 179 180 char write_file_path[35]; 181 memset(write_file_path, 0, sizeof(write_file_path)); 182 183 if(!check_if_dir_exist("/jffs/usericon")) 184 system("mkdir /jffs/usericon"); 185 186 sprintf(write_file_path, "/jffs/usericon/%s.log", client_mac_temp); 187 188 if(!check_if_file_exist(write_file_path)) { 189 int str_len = strlen(image_base64); 190 int i; 191 FILE * pFile; 192 pFile = fopen (write_file_path , "w"); 193 194 if (pFile == NULL) { 195 printf("File error\n"); 196 i = 0; 197 return i; 198 } 199 200 for(i = 0; i < str_len; i++) { 201 fputc(image_base64[i], pFile); 202 } 203 fclose (pFile); 204 } 205 206 i = 1; 207 return i; 208} 209 210unsigned long get_icon_crc32(char *icon_path) 211{ 212 FILE *icon_fd; 213 unsigned long calc_crc = 0; 214 long iconlen; 215 char buf[4096] = {0}; 216 217 //printf("get icon crc32 open: %s\n", icon_path); 218 219 icon_fd = fopen(icon_path, "rb"); 220 221 if(icon_fd == NULL) { 222 printf("Get Icon Failed!!!\n"); 223 return -1; 224 } 225 226 fseek (icon_fd , 0 , SEEK_END); 227 iconlen = ftell (icon_fd); 228 rewind (icon_fd); 229 230 while(iconlen>0) 231 { 232 if (iconlen > sizeof(buf)) 233 { 234 fread(buf, 1, sizeof(buf), icon_fd); 235 calc_crc = crc_calc(calc_crc, (unsigned char*)buf, sizeof(buf)); 236 iconlen-=sizeof(buf); 237 } 238 else 239 { 240 fread(buf, 1, iconlen, icon_fd); 241 calc_crc = crc_calc(calc_crc, (unsigned char*)buf, iconlen); 242 iconlen=0; 243 } 244 } 245 246 return calc_crc; 247} 248 249void get_icon_files(void) 250{ 251 FILE *fp; 252 char *ico_ptr; 253 char buf[128]; 254 struct IconFile *NextIcon = NULL, *ShowIcon; 255 256 sprintf(buf, "ls -1 %s/*.log", JFFS_ICON_PATH); 257 258 fp = popen(buf, "r"); 259 if (fp == NULL) { 260 perror("popen"); 261 return; 262 } 263 264#ifdef DEBUG 265printf("======= Get Icon Files =========\n"); 266#endif 267 while(fgets(buf, sizeof(buf), fp)) 268 { 269 IconFile *CurIcon = (IconFile *)malloc(sizeof(IconFile)); 270 271 ico_ptr = buf; 272 ico_ptr+= strlen(JFFS_ICON_PATH)+1; 273 274 memcpy(CurIcon->name, ico_ptr, 12); 275 CurIcon->next = NULL; 276 277 if( IconList == NULL ) 278 IconList = CurIcon; 279 else 280 NextIcon->next = CurIcon; 281 NextIcon = CurIcon; 282 } 283 284 ShowIcon = IconList; 285 while(ShowIcon != NULL) 286 { 287#ifdef DEBUG 288 printf("%s->", ShowIcon->name); 289#endif 290 ShowIcon = ShowIcon->next; 291 } 292#ifdef DEBUG 293 printf("\n===================================\n"); 294#endif 295} 296 297void TransferUpnpIcon(P_CLIENT_DETAIL_INFO_TABLE nmp_client) 298{ 299 FILE *fp; 300 char *ico_ptr, *ico_end; 301 char ico_ip[16], ico_mac[13], nmp_client_ip[16]; 302 char buf[128]; 303 struct IconFile *icon = NULL; 304 unsigned long icon_crc32; 305 int i, default_icon=0; 306 307 sprintf(buf, "ls -1 %s/*.ico", UPNP_ICON_PATH); 308 309 fp = popen(buf, "r"); 310 if (fp == NULL) { 311 perror("popen"); 312 return; 313 } 314 315#ifdef DEBUG 316printf("======= Transfer UPnP Icon Files =========\n"); 317#endif 318 while(fgets(buf, sizeof(buf), fp)) 319 { 320 321 ico_ptr = buf; 322 ico_ptr += strlen(UPNP_ICON_PATH)+1; 323 ico_end = strstr(buf, ".ico"); 324 325 i = 0; 326 while(ico_ptr < ico_end) 327 ico_ip[i++] = *ico_ptr++; 328 ico_ip[i] = '\0'; 329 ico_end = ico_end+4; 330 *ico_end = '\0'; 331 icon_crc32 = get_icon_crc32(buf); 332 333 //default icon crc32 check 334 i = 0; 335 default_icon = 0; 336 while((default_icon_crc[i] !=0 )) { 337 if(default_icon_crc[i] == icon_crc32) { 338 #ifdef DEBUG 339 printf("GET DEFAULT ICON CRC!!! %s\n", buf); 340 #endif 341 default_icon = 1; 342 break; 343 } 344 i++; 345 } 346 347 if(!default_icon) { 348 i = 0; 349 while( (nmp_client->ip_addr[i][0] != 0) && (i < 255) ) { 350 sprintf(nmp_client_ip, "%d.%d.%d.%d", nmp_client->ip_addr[i][0], 351 nmp_client->ip_addr[i][1],nmp_client->ip_addr[i][2], 352 nmp_client->ip_addr[i][3]); 353 if(!strcmp(ico_ip, nmp_client_ip)) { 354 sprintf(ico_mac, "%02X%02X%02X%02X%02X%02X", 355 nmp_client->mac_addr[i][0], 356 nmp_client->mac_addr[i][1], 357 nmp_client->mac_addr[i][2], 358 nmp_client->mac_addr[i][3], 359 nmp_client->mac_addr[i][4], 360 nmp_client->mac_addr[i][5]); 361 /* Compare icon in /jffs/usericon */ 362 icon = IconList; 363 while( icon != NULL ) { 364 if( memcmp(icon->name, ico_mac, 12) == 0) { 365 break; 366 } 367 icon = icon->next; 368 } 369 370 if( icon == NULL ) { /* new icon store to /jffs/usericon */ 371 image_to_base64(buf, ico_mac); 372 373 } 374 break; 375 } 376 i++; 377 } 378 } 379 } 380} 381#endif 382 383/* protofix() checks if protocol is "UDP" or "TCP" 384 * returns NULL if not */ 385const char * protofix(const char * proto) 386{ 387 static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; 388 static const char proto_udp[4] = { 'U', 'D', 'P', 0}; 389 int i, b; 390 for(i=0, b=1; i<4; i++) 391 b = b && ( (proto[i] == proto_tcp[i]) 392 || (proto[i] == (proto_tcp[i] | 32)) ); 393 if(b) 394 return proto_tcp; 395 for(i=0, b=1; i<4; i++) 396 b = b && ( (proto[i] == proto_udp[i]) 397 || (proto[i] == (proto_udp[i] | 32)) ); 398 if(b) 399 return proto_udp; 400 return 0; 401} 402 403static void DisplayInfos(struct UPNPUrls * urls, 404 struct IGDdatas * data) 405{ 406 char externalIPAddress[40]; 407 char connectionType[64]; 408 char status[64]; 409 char lastconnerr[64]; 410 unsigned int uptime; 411 unsigned int brUp, brDown; 412 time_t timenow, timestarted; 413 int r; 414/* 415printf("===== DisplayInfos ====\n"); 416printf("controlURL: %s\n", urls->controlURL); 417printf("ipcondescURL: %s\n", urls->ipcondescURL); 418printf("rootdescURL: %s\n", urls->rootdescURL); 419printf("controlURL_CIF: %s\n", urls->controlURL_CIF); 420printf("controlURL_6FC: %s\n", urls->controlURL_6FC); 421printf("=======================\n"); 422*/ 423 if(UPNP_GetConnectionTypeInfo(urls->controlURL, 424 data->first.servicetype, 425 connectionType) != UPNPCOMMAND_SUCCESS) 426 printf("GetConnectionTypeInfo failed.\n"); 427 else 428 printf("Connection Type : %s\n", connectionType); 429 if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, 430 status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) 431 printf("GetStatusInfo failed.\n"); 432 else 433 printf("Status : %s, uptime=%us, LastConnectionError : %s\n", 434 status, uptime, lastconnerr); 435 timenow = time(NULL); 436 timestarted = timenow - uptime; 437 printf(" Time started : %s", ctime(×tarted)); 438 if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, 439 &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { 440 printf("GetLinkLayerMaxBitRates failed.\n"); 441 } else { 442 printf("MaxBitRateDown : %u bps", brDown); 443 if(brDown >= 1000000) { 444 printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); 445 } else if(brDown >= 1000) { 446 printf(" (%u Kbps)", brDown / 1000); 447 } 448 printf(" MaxBitRateUp %u bps", brUp); 449 if(brUp >= 1000000) { 450 printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); 451 } else if(brUp >= 1000) { 452 printf(" (%u Kbps)", brUp / 1000); 453 } 454 printf("\n"); 455 } 456 r = UPNP_GetExternalIPAddress(urls->controlURL, 457 data->first.servicetype, 458 externalIPAddress); 459 if(r != UPNPCOMMAND_SUCCESS) { 460 printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); 461 } else { 462 printf("ExternalIPAddress = %s\n", externalIPAddress); 463 } 464} 465 466static void GetConnectionStatus(struct UPNPUrls * urls, 467 struct IGDdatas * data) 468{ 469 unsigned int bytessent, bytesreceived, packetsreceived, packetssent; 470 DisplayInfos(urls, data); 471 bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); 472 bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); 473 packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); 474 packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); 475 printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); 476 printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); 477} 478 479static void ListRedirections(struct UPNPUrls * urls, 480 struct IGDdatas * data) 481{ 482 int r; 483 int i = 0; 484 char index[6]; 485 char intClient[40]; 486 char intPort[6]; 487 char extPort[6]; 488 char protocol[4]; 489 char desc[80]; 490 char enabled[6]; 491 char rHost[64]; 492 char duration[16]; 493 /*unsigned int num=0; 494 UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); 495 printf("PortMappingNumberOfEntries : %u\n", num);*/ 496 printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); 497 do { 498 snprintf(index, 6, "%d", i); 499 rHost[0] = '\0'; enabled[0] = '\0'; 500 duration[0] = '\0'; desc[0] = '\0'; 501 extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; 502 r = UPNP_GetGenericPortMappingEntry(urls->controlURL, 503 data->first.servicetype, 504 index, 505 extPort, intClient, intPort, 506 protocol, desc, enabled, 507 rHost, duration); 508 if(r==0) 509 /* 510 printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" 511 " desc='%s' rHost='%s'\n", 512 i, protocol, extPort, intClient, intPort, 513 enabled, duration, 514 desc, rHost); 515 */ 516 printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", 517 i, protocol, extPort, intClient, intPort, 518 desc, rHost, duration); 519 else 520 printf("GetGenericPortMappingEntry() returned %d (%s)\n", 521 r, strupnperror(r)); 522 i++; 523 } while(r==0); 524} 525 526static void NewListRedirections(struct UPNPUrls * urls, 527 struct IGDdatas * data) 528{ 529 int r; 530 int i = 0; 531 struct PortMappingParserData pdata; 532 struct PortMapping * pm; 533 534 memset(&pdata, 0, sizeof(struct PortMappingParserData)); 535 r = UPNP_GetListOfPortMappings(urls->controlURL, 536 data->first.servicetype, 537 "0", 538 "65535", 539 "TCP", 540 "1000", 541 &pdata); 542 if(r == UPNPCOMMAND_SUCCESS) 543 { 544 printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); 545 for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) 546 { 547 printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", 548 i, pm->protocol, pm->externalPort, pm->internalClient, 549 pm->internalPort, 550 pm->description, pm->remoteHost, 551 (unsigned)pm->leaseTime); 552 i++; 553 } 554 FreePortListing(&pdata); 555 } 556 else 557 { 558 printf("GetListOfPortMappings() returned %d (%s)\n", 559 r, strupnperror(r)); 560 } 561 r = UPNP_GetListOfPortMappings(urls->controlURL, 562 data->first.servicetype, 563 "0", 564 "65535", 565 "UDP", 566 "1000", 567 &pdata); 568 if(r == UPNPCOMMAND_SUCCESS) 569 { 570 for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) 571 { 572 printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", 573 i, pm->protocol, pm->externalPort, pm->internalClient, 574 pm->internalPort, 575 pm->description, pm->remoteHost, 576 (unsigned)pm->leaseTime); 577 i++; 578 } 579 FreePortListing(&pdata); 580 } 581 else 582 { 583 printf("GetListOfPortMappings() returned %d (%s)\n", 584 r, strupnperror(r)); 585 } 586} 587 588/* Test function 589 * 1 - get connection type 590 * 2 - get extenal ip address 591 * 3 - Add port mapping 592 * 4 - get this port mapping from the IGD */ 593static void SetRedirectAndTest(struct UPNPUrls * urls, 594 struct IGDdatas * data, 595 const char * iaddr, 596 const char * iport, 597 const char * eport, 598 const char * proto, 599 const char * leaseDuration, 600 const char * description, 601 int addAny) 602{ 603 char externalIPAddress[40]; 604 char intClient[40]; 605 char intPort[6]; 606 char reservedPort[6]; 607 char duration[16]; 608 int r; 609 610 if(!iaddr || !iport || !eport || !proto) 611 { 612 fprintf(stderr, "Wrong arguments\n"); 613 return; 614 } 615 proto = protofix(proto); 616 if(!proto) 617 { 618 fprintf(stderr, "invalid protocol\n"); 619 return; 620 } 621 622 r = UPNP_GetExternalIPAddress(urls->controlURL, 623 data->first.servicetype, 624 externalIPAddress); 625 if(r!=UPNPCOMMAND_SUCCESS) 626 printf("GetExternalIPAddress failed.\n"); 627 else 628 printf("ExternalIPAddress = %s\n", externalIPAddress); 629 630 if (addAny) { 631 r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, 632 eport, iport, iaddr, description, 633 proto, 0, leaseDuration, reservedPort); 634 if(r==UPNPCOMMAND_SUCCESS) 635 eport = reservedPort; 636 else 637 printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n", 638 eport, iport, iaddr, r, strupnperror(r)); 639 } else { 640 r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, 641 eport, iport, iaddr, description, 642 proto, 0, leaseDuration); 643 if(r!=UPNPCOMMAND_SUCCESS) 644 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", 645 eport, iport, iaddr, r, strupnperror(r)); 646 } 647 648 r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, 649 data->first.servicetype, 650 eport, proto, NULL/*remoteHost*/, 651 intClient, intPort, NULL/*desc*/, 652 NULL/*enabled*/, duration); 653 if(r!=UPNPCOMMAND_SUCCESS) 654 printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", 655 r, strupnperror(r)); 656 else { 657 printf("InternalIP:Port = %s:%s\n", intClient, intPort); 658 printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", 659 externalIPAddress, eport, proto, intClient, intPort, duration); 660 } 661} 662 663static void 664RemoveRedirect(struct UPNPUrls * urls, 665 struct IGDdatas * data, 666 const char * eport, 667 const char * proto, 668 const char * remoteHost) 669{ 670 int r; 671 if(!proto || !eport) 672 { 673 fprintf(stderr, "invalid arguments\n"); 674 return; 675 } 676 proto = protofix(proto); 677 if(!proto) 678 { 679 fprintf(stderr, "protocol invalid\n"); 680 return; 681 } 682 r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost); 683 printf("UPNP_DeletePortMapping() returned : %d\n", r); 684} 685 686static void 687RemoveRedirectRange(struct UPNPUrls * urls, 688 struct IGDdatas * data, 689 const char * ePortStart, char const * ePortEnd, 690 const char * proto, const char * manage) 691{ 692 int r; 693 694 if (!manage) 695 manage = "0"; 696 697 if(!proto || !ePortStart || !ePortEnd) 698 { 699 fprintf(stderr, "invalid arguments\n"); 700 return; 701 } 702 proto = protofix(proto); 703 if(!proto) 704 { 705 fprintf(stderr, "protocol invalid\n"); 706 return; 707 } 708 r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); 709 printf("UPNP_DeletePortMappingRange() returned : %d\n", r); 710} 711 712/* IGD:2, functions for service WANIPv6FirewallControl:1 */ 713static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) 714{ 715 unsigned int bytessent, bytesreceived, packetsreceived, packetssent; 716 int firewallEnabled = 0, inboundPinholeAllowed = 0; 717 718 UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); 719 printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); 720 printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); 721 722 bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); 723 bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); 724 packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); 725 packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); 726 printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); 727 printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); 728} 729 730/* Test function 731 * 1 - Add pinhole 732 * 2 - Check if pinhole is working from the IGD side */ 733static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, 734 const char * remoteaddr, const char * eport, 735 const char * intaddr, const char * iport, 736 const char * proto, const char * lease_time) 737{ 738 char uniqueID[8]; 739 /*int isWorking = 0;*/ 740 int r; 741 char proto_tmp[8]; 742 743 if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) 744 { 745 fprintf(stderr, "Wrong arguments\n"); 746 return; 747 } 748 if(atoi(proto) == 0) 749 { 750 const char * protocol; 751 protocol = protofix(proto); 752 if(protocol && (strcmp("TCP", protocol) == 0)) 753 { 754 snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP); 755 proto = proto_tmp; 756 } 757 else if(protocol && (strcmp("UDP", protocol) == 0)) 758 { 759 snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP); 760 proto = proto_tmp; 761 } 762 else 763 { 764 fprintf(stderr, "invalid protocol\n"); 765 return; 766 } 767 } 768 r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); 769 if(r!=UPNPCOMMAND_SUCCESS) 770 printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", 771 remoteaddr, eport, intaddr, iport, r, strupnperror(r)); 772 else 773 { 774 printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", 775 remoteaddr, eport, intaddr, iport, uniqueID); 776 /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); 777 if(r!=UPNPCOMMAND_SUCCESS) 778 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); 779 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ 780 } 781} 782 783/* Test function 784 * 1 - Check if pinhole is working from the IGD side 785 * 2 - Update pinhole */ 786static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, 787 const char * uniqueID, const char * lease_time) 788{ 789 int isWorking = 0; 790 int r; 791 792 if(!uniqueID || !lease_time) 793 { 794 fprintf(stderr, "Wrong arguments\n"); 795 return; 796 } 797 r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); 798 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); 799 if(r!=UPNPCOMMAND_SUCCESS) 800 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); 801 if(isWorking || r==709) 802 { 803 r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); 804 printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); 805 if(r!=UPNPCOMMAND_SUCCESS) 806 printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); 807 } 808} 809 810/* Test function 811 * Get pinhole timeout 812 */ 813static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, 814 const char * remoteaddr, const char * eport, 815 const char * intaddr, const char * iport, 816 const char * proto) 817{ 818 int timeout = 0; 819 int r; 820 821 if(!intaddr || !remoteaddr || !iport || !eport || !proto) 822 { 823 fprintf(stderr, "Wrong arguments\n"); 824 return; 825 } 826 827 r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); 828 if(r!=UPNPCOMMAND_SUCCESS) 829 printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", 830 intaddr, iport, remoteaddr, eport, r, strupnperror(r)); 831 else 832 printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); 833} 834 835static void 836GetPinholePackets(struct UPNPUrls * urls, 837 struct IGDdatas * data, const char * uniqueID) 838{ 839 int r, pinholePackets = 0; 840 if(!uniqueID) 841 { 842 fprintf(stderr, "invalid arguments\n"); 843 return; 844 } 845 r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); 846 if(r!=UPNPCOMMAND_SUCCESS) 847 printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); 848 else 849 printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); 850} 851 852static void 853CheckPinhole(struct UPNPUrls * urls, 854 struct IGDdatas * data, const char * uniqueID) 855{ 856 int r, isWorking = 0; 857 if(!uniqueID) 858 { 859 fprintf(stderr, "invalid arguments\n"); 860 return; 861 } 862 r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); 863 if(r!=UPNPCOMMAND_SUCCESS) 864 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); 865 else 866 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); 867} 868 869static void 870RemovePinhole(struct UPNPUrls * urls, 871 struct IGDdatas * data, const char * uniqueID) 872{ 873 int r; 874 if(!uniqueID) 875 { 876 fprintf(stderr, "invalid arguments\n"); 877 return; 878 } 879 r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); 880 printf("UPNP_DeletePinhole() returned : %d\n", r); 881} 882 883 884/* sample upnp client program */ 885int main(int argc, char ** argv) 886{ 887 char command = 0; 888 char ** commandargv = 0; 889 int commandargc = 0; 890 struct UPNPDev * devlist = 0; 891 char lanaddr[64]; /* my ip address on the LAN */ 892 int i; 893 const char * rootdescurl = 0; 894 const char * multicastif = 0; 895 const char * minissdpdpath = 0; 896 int retcode = 0; 897 int error = 0; 898 int ipv6 = 0; 899 const char * description = 0; 900 901#ifdef _WIN32 902 WSADATA wsaData; 903 int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); 904 if(nResult != NO_ERROR) 905 { 906 fprintf(stderr, "WSAStartup() failed.\n"); 907 return -1; 908 } 909#endif 910/* 911 printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n"); 912 printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" 913 "for more information.\n"); 914*/ 915 916 /* command line processing */ 917 for(i=1; i<argc; i++) 918 { 919 if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h")) 920 { 921 command = 0; 922 break; 923 } 924 if(argv[i][0] == '-') 925 { 926 if(argv[i][1] == 'u') 927 rootdescurl = argv[++i]; 928 else if(argv[i][1] == 'm') 929 multicastif = argv[++i]; 930 else if(argv[i][1] == 'p') 931 minissdpdpath = argv[++i]; 932 else if(argv[i][1] == '6') 933 ipv6 = 1; 934 else if(argv[i][1] == 'e') 935 description = argv[++i]; 936 else 937 { 938 command = argv[i][1]; 939 i++; 940 commandargv = argv + i; 941 commandargc = argc - i; 942 break; 943 } 944 } 945 else 946 { 947 fprintf(stderr, "option '%s' invalid\n", argv[i]); 948 } 949 } 950 951 if(!command || (command == 'a' && commandargc<4) 952 || (command == 'd' && argc<2) 953 || (command == 'r' && argc<2) 954 || (command == 'A' && commandargc<6) 955 || (command == 'U' && commandargc<2) 956 || (command == 'D' && commandargc<1)) 957 { 958 fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]); 959 fprintf(stderr, " \t%s [options] -d external_port protocol <remote host>\n\t\tDelete port redirection\n", argv[0]); 960 fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); 961 fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); 962 fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); 963 fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); 964 fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); 965 fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); 966 fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); 967 fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); 968 fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); 969 fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]); 970 fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]); 971 fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]); 972 fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]); 973 fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); 974 fprintf(stderr, "\nprotocol is UDP or TCP\n"); 975 fprintf(stderr, "Options:\n"); 976 fprintf(stderr, " -e description : set description for port mapping.\n"); 977 fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); 978 fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); 979 fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); 980 fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); 981 return 1; 982 } 983 984#if 0 985 if( rootdescurl 986 || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 987 0/*sameport*/, ipv6, &error))) 988#endif 989 990#ifdef RTCONFIG_JFFS2USERICON 991 if(!check_if_dir_exist("/tmp/upnpicon")) 992 system("mkdir /tmp/upnpicon"); 993#endif 994 995 int x = 0; 996 while(x<3) 997 { 998 devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath, 1, ipv6, &error); 999 if(devlist) 1000 break; 1001 x++; 1002 sleep(6); 1003 } 1004 1005 if(devlist) 1006 { 1007 struct UPNPDev * device; 1008 struct UPNPUrls urls; 1009 struct IGDdatas data; 1010 if(devlist) 1011 { 1012#ifdef DEBUG 1013 printf("List of UPNP devices found on the network :\n"); 1014 for(device = devlist; device; device = device->pNext) 1015 { 1016 printf(" desc: %s\n st: %s\n\n", 1017 device->descURL, device->st); 1018 } 1019#endif 1020 } 1021 else 1022 { 1023 printf("upnpDiscover() error code=%d\n", error); 1024 } 1025 1026 i = 1; 1027 1028 if(i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))) 1029 { 1030 FILE *fp; 1031 int i, shm_client_info_id; 1032 void *shared_client_info=(void *) 0; 1033 int lock; 1034 1035 if(fp = fopen("/tmp/miniupnpc.log", "w")) 1036 { 1037 for(device = devlist; device; device = device->pNext) 1038 { 1039 if(strcmp(device->DevInfo.hostname, "")) 1040 { 1041 fprintf(fp,"%s>", device->DevInfo.hostname); 1042 fprintf(fp,"%s>", device->DevInfo.type); 1043 fprintf(fp,"%s\n", device->DevInfo.friendlyName); 1044 } 1045 } 1046 fclose(fp); 1047 } 1048 1049#ifdef RTCONFIG_JFFS2USERICON 1050 get_icon_files(); 1051 lock = file_lock("networkmap"); 1052 shm_client_info_id = shmget((key_t)1001, sizeof(CLIENT_DETAIL_INFO_TABLE), 0666| IPC_CREAT); 1053 if (shm_client_info_id == -1){ 1054 perror("shmget failed:\n"); 1055 file_unlock(lock); 1056 return 0; 1057 } 1058 1059 shared_client_info = shmat(shm_client_info_id,(void *) 0,SHM_RDONLY); 1060 if (shared_client_info == (void *)-1){ 1061 printf("shmat failed\n"); 1062 file_unlock(lock); 1063 return 0; 1064 } 1065 1066 TransferUpnpIcon(shared_client_info); 1067#endif 1068 1069#ifdef DEBUG 1070 switch(i) { 1071 case 1: 1072 printf("Found valid IGD : %s\n", urls.controlURL); 1073 break; 1074 case 2: 1075 printf("Found a (not connected?) IGD : %s\n", urls.controlURL); 1076 printf("Trying to continue anyway\n"); 1077 break; 1078 case 3: 1079 printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); 1080 printf("Trying to continue anyway\n"); 1081 break; 1082 default: 1083 printf("Found device (igd ?) : %s\n", urls.controlURL); 1084 printf("Trying to continue anyway\n"); 1085 } 1086 printf("Local LAN ip address : %s\n", lanaddr); 1087#endif 1088 #if 0 1089 printf("getting \"%s\"\n", urls.ipcondescURL); 1090 descXML = miniwget(urls.ipcondescURL, &descXMLsize); 1091 if(descXML) 1092 { 1093 /*fwrite(descXML, 1, descXMLsize, stdout);*/ 1094 free(descXML); descXML = NULL; 1095 } 1096 #endif 1097 1098 switch(command) 1099 { 1100 case 'l': 1101 DisplayInfos(&urls, &data); 1102 ListRedirections(&urls, &data); 1103 break; 1104 case 'L': 1105 NewListRedirections(&urls, &data); 1106 break; 1107 case 'a': 1108 SetRedirectAndTest(&urls, &data, 1109 commandargv[0], commandargv[1], 1110 commandargv[2], commandargv[3], 1111 (commandargc > 4)?commandargv[4]:"0", 1112 description, 0); 1113 break; 1114 case 'd': 1115 RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], 1116 commandargc > 2 ? commandargv[2] : NULL); 1117 break; 1118 case 'n': /* aNy */ 1119 SetRedirectAndTest(&urls, &data, 1120 commandargv[0], commandargv[1], 1121 commandargv[2], commandargv[3], 1122 (commandargc > 4)?commandargv[4]:"0", 1123 description, 1); 1124 break; 1125 case 'N': 1126 if (commandargc < 3) 1127 fprintf(stderr, "too few arguments\n"); 1128 1129 RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], 1130 commandargc > 3 ? commandargv[3] : NULL); 1131 break; 1132 case 's': 1133 GetConnectionStatus(&urls, &data); 1134 break; 1135 case 'r': 1136 for(i=0; i<commandargc; i+=2) 1137 { 1138 /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/ 1139 SetRedirectAndTest(&urls, &data, 1140 lanaddr, commandargv[i], 1141 commandargv[i], commandargv[i+1], "0", 1142 description, 0); 1143 } 1144 break; 1145 case 'A': 1146 SetPinholeAndTest(&urls, &data, 1147 commandargv[0], commandargv[1], 1148 commandargv[2], commandargv[3], 1149 commandargv[4], commandargv[5]); 1150 break; 1151 case 'U': 1152 GetPinholeAndUpdate(&urls, &data, 1153 commandargv[0], commandargv[1]); 1154 break; 1155 case 'C': 1156 for(i=0; i<commandargc; i++) 1157 { 1158 CheckPinhole(&urls, &data, commandargv[i]); 1159 } 1160 break; 1161 case 'K': 1162 for(i=0; i<commandargc; i++) 1163 { 1164 GetPinholePackets(&urls, &data, commandargv[i]); 1165 } 1166 break; 1167 case 'D': 1168 for(i=0; i<commandargc; i++) 1169 { 1170 RemovePinhole(&urls, &data, commandargv[i]); 1171 } 1172 break; 1173 case 'S': 1174 GetFirewallStatus(&urls, &data); 1175 break; 1176 case 'G': 1177 GetPinholeOutboundTimeout(&urls, &data, 1178 commandargv[0], commandargv[1], 1179 commandargv[2], commandargv[3], 1180 commandargv[4]); 1181 break; 1182 case 'P': 1183 printf("Presentation URL found:\n"); 1184 printf(" %s\n", data.presentationurl); 1185 break; 1186 case 't': 1187 break; 1188 default: 1189 fprintf(stderr, "Unknown switch -%c\n", command); 1190 retcode = 1; 1191 } 1192 1193 FreeUPNPUrls(&urls); 1194 } 1195 else 1196 { 1197 fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); 1198 retcode = 1; 1199 } 1200 1201 freeUPNPDevlist(devlist); devlist = 0; 1202 } 1203 else 1204 { 1205 fprintf(stderr, "No IGD UPnP Device found on the network !\n"); 1206 retcode = 1; 1207 } 1208 return retcode; 1209} 1210 1211