1/* 2 3 Tomato Firmware 4 Copyright (C) 2006-2009 Jonathan Zarate 5 6*/ 7#include <string.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <unistd.h> 11#include <fcntl.h> 12#include <sys/stat.h> 13#include <stdarg.h> 14#include <syslog.h> 15#include <sys/ioctl.h> 16#include <net/if.h> 17#include <sys/socket.h> 18#include <arpa/inet.h> 19#include <ifaddrs.h> 20#include <sys/sysinfo.h> 21#include <sys/types.h> 22#include <sys/wait.h> 23#include <dirent.h> 24#include <ctype.h> 25#include <sys/socket.h> 26#include <netdb.h> 27 28#include <bcmnvram.h> 29#include <bcmdevs.h> 30#include <wlutils.h> 31 32#include "shutils.h" 33#include "shared.h" 34 35#ifndef ETHER_ADDR_LEN 36#define ETHER_ADDR_LEN 6 37#endif 38 39extern char *read_whole_file(const char *target){ 40 FILE *fp; 41 char *buffer, *new_str; 42 int i; 43 unsigned int read_bytes = 0; 44 unsigned int each_size = 1024; 45 46 if((fp = fopen(target, "r")) == NULL) 47 return NULL; 48 49 buffer = (char *)malloc(sizeof(char)*each_size); 50 if(buffer == NULL){ 51 _dprintf("No memory \"buffer\".\n"); 52 fclose(fp); 53 return NULL; 54 } 55 memset(buffer, 0, each_size); 56 57 while ((i = fread(buffer+read_bytes, each_size * sizeof(char), 1, fp)) == 1){ 58 read_bytes += each_size; 59 new_str = (char *)malloc(sizeof(char)*(each_size+read_bytes)); 60 if(new_str == NULL){ 61 _dprintf("No memory \"new_str\".\n"); 62 free(buffer); 63 fclose(fp); 64 return NULL; 65 } 66 memset(new_str, 0, sizeof(char)*(each_size+read_bytes)); 67 memcpy(new_str, buffer, read_bytes); 68 69 free(buffer); 70 buffer = new_str; 71 } 72 73 fclose(fp); 74 return buffer; 75} 76 77extern char *get_line_from_buffer(const char *buf, char *line, const int line_size){ 78 int buf_len, len; 79 char *ptr; 80 81 if(buf == NULL || (buf_len = strlen(buf)) <= 0) 82 return NULL; 83 84 if((ptr = strchr(buf, '\n')) == NULL) 85 ptr = (char *)(buf+buf_len); 86 87 if((len = ptr-buf) < 0) 88 len = buf-ptr; 89 ++len; // include '\n'. 90 91 memset(line, 0, line_size); 92 strncpy(line, buf, len); 93 94 return line; 95} 96 97extern char *get_upper_str(const char *const str, char **target){ 98 int len, i; 99 char *ptr; 100 101 len = strlen(str); 102 *target = (char *)malloc(sizeof(char)*(len+1)); 103 if(*target == NULL){ 104 _dprintf("No memory \"*target\".\n"); 105 return NULL; 106 } 107 ptr = *target; 108 for(i = 0; i < len; ++i) 109 ptr[i] = toupper(str[i]); 110 ptr[len] = 0; 111 112 return ptr; 113} 114 115extern int upper_strcmp(const char *const str1, const char *const str2){ 116 char *upper_str1, *upper_str2; 117 int ret; 118 119 if(str1 == NULL || str2 == NULL) 120 return -1; 121 122 if(get_upper_str(str1, &upper_str1) == NULL) 123 return -1; 124 125 if(get_upper_str(str2, &upper_str2) == NULL){ 126 free(upper_str1); 127 return -1; 128 } 129 130 ret = strcmp(upper_str1, upper_str2); 131 free(upper_str1); 132 free(upper_str2); 133 134 return ret; 135} 136 137extern int upper_strncmp(const char *const str1, const char *const str2, int count){ 138 char *upper_str1, *upper_str2; 139 int ret; 140 141 if(str1 == NULL || str2 == NULL) 142 return -1; 143 144 if(get_upper_str(str1, &upper_str1) == NULL) 145 return -1; 146 147 if(get_upper_str(str2, &upper_str2) == NULL){ 148 free(upper_str1); 149 return -1; 150 } 151 152 ret = strncmp(upper_str1, upper_str2, count); 153 free(upper_str1); 154 free(upper_str2); 155 156 return ret; 157} 158 159extern char *upper_strstr(const char *const str, const char *const target){ 160 char *upper_str, *upper_target; 161 char *ret; 162 int len; 163 164 if(str == NULL || target == NULL) 165 return NULL; 166 167 if(get_upper_str(str, &upper_str) == NULL) 168 return NULL; 169 170 if(get_upper_str(target, &upper_target) == NULL){ 171 free(upper_str); 172 return NULL; 173 } 174 175 ret = strstr(upper_str, upper_target); 176 if(ret == NULL){ 177 free(upper_str); 178 free(upper_target); 179 return NULL; 180 } 181 182 if((len = upper_str-ret) < 0) 183 len = ret-upper_str; 184 185 free(upper_str); 186 free(upper_target); 187 188 return (char *)(str+len); 189} 190 191#ifdef RTCONFIG_IPV6 192char *ipv6_nvname_by_unit(const char *name, int unit) 193{ 194 static char name_ipv6[128]; 195 196 if (strncmp(name, "ipv6_", sizeof("ipv6_") - 1) != 0) { 197 _dprintf("Wrong ipv6 nvram namespace: \"%s\"\n", name); 198 return (char *)name; 199 } 200 201 if (unit == 0) 202 return (char *)name; 203 204 snprintf(name_ipv6, sizeof(name_ipv6), "ipv6%d_%s", unit, name + sizeof("ipv6_") - 1); 205 206 return name_ipv6; 207} 208 209char *ipv6_nvname(const char *name) 210{ 211 return ipv6_nvname_by_unit(name, wan_primary_ifunit()); 212} 213 214int get_ipv6_service_by_unit(int unit) 215{ 216 static const struct { 217 char *name; 218 int service; 219 } services[] = { 220 { "dhcp6", IPV6_NATIVE_DHCP }, 221#ifdef RTCONFIG_6RELAYD 222 { "ipv6pt", IPV6_PASSTHROUGH }, 223#endif 224 { "6to4", IPV6_6TO4 }, 225 { "6in4", IPV6_6IN4 }, 226 { "6rd", IPV6_6RD }, 227 { "other", IPV6_MANUAL }, 228 { "static6", IPV6_MANUAL }, /* legacy */ 229 { NULL } 230 }; 231 char *value; 232 int i; 233 234 value = nvram_safe_get(ipv6_nvname_by_unit("ipv6_service", unit)); 235 for (i = 0; services[i].name; i++) { 236 if (strcmp(value, services[i].name) == 0) 237 return services[i].service; 238 } 239 return IPV6_DISABLED; 240} 241 242int get_ipv6_service(void) 243{ 244 return get_ipv6_service_by_unit(wan_primary_ifunit()); 245} 246 247const char *ipv6_router_address(struct in6_addr *in6addr) 248{ 249 char *p; 250 struct in6_addr addr; 251 static char addr6[INET6_ADDRSTRLEN]; 252 253 addr6[0] = '\0'; 254 memset(&addr, 0, sizeof(addr)); 255 256 if ((p = nvram_get(ipv6_nvname("ipv6_rtr_addr"))) && *p) { 257 inet_pton(AF_INET6, p, &addr); 258 } else if ((p = nvram_get(ipv6_nvname("ipv6_prefix"))) && *p) { 259 inet_pton(AF_INET6, p, &addr); 260 addr.s6_addr16[7] = htons(0x0001); 261 } else 262 return addr6; 263 264 inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6)); 265 if (in6addr) 266 memcpy(in6addr, &addr, sizeof(addr)); 267 268 return addr6; 269} 270 271// trim useless 0 from IPv6 address 272const char *ipv6_address(const char *ipaddr6) 273{ 274 struct in6_addr addr; 275 static char addr6[INET6_ADDRSTRLEN]; 276 277 addr6[0] = '\0'; 278 279 if (inet_pton(AF_INET6, ipaddr6, &addr) > 0) 280 inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6)); 281 282 return addr6; 283} 284 285// extract prefix from configured IPv6 address 286const char *ipv6_prefix(struct in6_addr *in6addr) 287{ 288 static char prefix[INET6_ADDRSTRLEN]; 289 struct in6_addr addr; 290 int i, r; 291 292 prefix[0] = '\0'; 293 memset(&addr, 0, sizeof(addr)); 294 295 if (inet_pton(AF_INET6, nvram_safe_get(ipv6_nvname("ipv6_rtr_addr")), &addr) > 0) { 296 r = nvram_get_int(ipv6_nvname("ipv6_prefix_length")) ? : 64; 297 for (r = 128 - r, i = 15; r > 0; r -= 8) { 298 if (r >= 8) 299 addr.s6_addr[i--] = 0; 300 else 301 addr.s6_addr[i--] &= (0xff << r); 302 } 303 inet_ntop(AF_INET6, &addr, prefix, sizeof(prefix)); 304 } 305 306 if (in6addr) 307 memcpy(in6addr, &addr, sizeof(addr)); 308 309 return prefix; 310} 311 312#if 0 /* unused */ 313const char *ipv6_prefix(const char *ifname) 314{ 315 return getifaddr(ifname, AF_INET6, GIF_PREFIX) ? : ""; 316} 317 318int ipv6_prefix_len(const char *ifname) 319{ 320 const char *value; 321 322 value = getifaddr(ifname, AF_INET6, /*GIF_PREFIX |*/ GIF_PREFIXLEN); 323 if (value == NULL) 324 return 0; 325 326 value = strchr(value, '/'); 327 if (value) 328 return atoi(value + 1); 329 330 return 128; 331} 332#endif 333 334void reset_ipv6_linklocal_addr(const char *ifname, int flush) 335{ 336 static char buf[INET6_ADDRSTRLEN]; 337 struct in6_addr addr; 338 struct ifreq ifr; 339 char *mac; 340 int fd; 341 342 if (!ifname || 343 !strcmp(ifname, "lo") || !strncmp(ifname, "ppp", 3)) 344 return; 345 346 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 347 return; 348 349 memset(&ifr, 0, sizeof(ifr)); 350 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 351 mac = (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) ? 352 NULL : ifr.ifr_hwaddr.sa_data; 353 close(fd); 354 355 if (mac == NULL) 356 return; 357 358 addr.s6_addr32[0] = htonl(0xfe800000); 359 addr.s6_addr32[1] = 0; 360 memcpy(&addr.s6_addr[8], mac, 3); 361 memcpy(&addr.s6_addr[13], mac + 3, 3); 362 addr.s6_addr[8] ^= 0x02; 363 addr.s6_addr[11] = 0xff; 364 addr.s6_addr[12] = 0xfe; 365 366 if (flush) 367 eval("ip", "-6", "addr", "flush", "dev", (char *) ifname); 368 if (inet_ntop(AF_INET6, &addr, buf, sizeof(buf))) 369 eval("ip", "-6", "addr", "add", buf, "dev", (char *) ifname); 370} 371 372int with_ipv6_linklocal_addr(const char *ifname) 373{ 374 return (getifaddr(ifname, AF_INET6, GIF_LINKLOCAL) != NULL); 375} 376 377static int ipv6_expand(char *buf, char *str, struct in6_addr *addr) 378{ 379 char *dst = buf; 380 char *src = str; 381 int i; 382 383 for (i = 1; dst < src && *src; i++) { 384 *dst++ = *src++; 385 if (i % 4 == 0) *dst++ = ':'; 386 } 387 return inet_pton(AF_INET6, buf, addr); 388} 389 390const char *ipv6_gateway_address(void) 391{ 392 static char buf[INET6_ADDRSTRLEN] = ""; 393 FILE *fp; 394 struct in6_addr addr; 395 char dest[41], nexthop[41], dev[17]; 396 int mask, prefix, metric, flags; 397 int maxprefix, minmetric = minmetric; 398 399 fp = fopen("/proc/net/ipv6_route", "r"); 400 if (fp == NULL) { 401 perror("/proc/net/ipv6_route"); 402 return NULL; 403 } 404 405 maxprefix = -1; 406 while (fscanf(fp, "%32s%x%*s%*x%32s%x%*x%*x%x%16s\n", 407 &dest[7], &prefix, &nexthop[7], &metric, &flags, dev) == 6) { 408 /* Skip interfaces that are down and host routes */ 409 if ((flags & (RTF_UP | RTF_HOST)) != RTF_UP) 410 continue; 411 412 /* Skip dst not in "::/0 - 2000::/3" */ 413 if (prefix > 3) 414 continue; 415 if (ipv6_expand(dest, &dest[7], &addr) <= 0) 416 continue; 417 mask = htons((0xffff0000 >> prefix) & 0xffff); 418 if ((addr.s6_addr16[0] & mask) != (htons(0x2000) & mask)) 419 continue; 420 421 /* Skip dups & worse routes */ 422 if ((maxprefix > prefix) || 423 (maxprefix == prefix && minmetric <= metric)) 424 continue; 425 426 if (flags & RTF_GATEWAY) { 427 if (ipv6_expand(nexthop, &nexthop[7], &addr) <= 0) 428 continue; 429 inet_ntop(AF_INET6, &addr, buf, sizeof(buf)); 430 } else 431 snprintf(buf, sizeof(buf), "::"); 432 maxprefix = prefix; 433 minmetric = metric; 434 435 if (prefix == 0) 436 break; 437 } 438 fclose(fp); 439 440 return *buf ? buf : NULL; 441} 442#endif 443 444int wl_client(int unit, int subunit) 445{ 446 char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit)); 447 448 return ((strcmp(mode, "sta") == 0) || (strcmp(mode, "wet") == 0)); 449} 450 451int foreach_wif(int include_vifs, void *param, 452 int (*func)(int idx, int unit, int subunit, void *param)) 453{ 454 char ifnames[256]; 455 char name[64], ifname[64], *next = NULL; 456 int unit = -1, subunit = -1; 457 int i; 458 int ret = 0; 459 460 snprintf(ifnames, sizeof(ifnames), "%s %s", 461 nvram_safe_get("lan_ifnames"), nvram_safe_get("wan_ifnames")); 462 remove_dups(ifnames, sizeof(ifnames)); 463 464 i = 0; 465 foreach(name, ifnames, next) { 466 if (nvifname_to_osifname(name, ifname, sizeof(ifname)) != 0) 467 continue; 468 469#ifdef CONFIG_BCMWL5 470 if (wl_probe(ifname) || wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit))) 471 continue; 472#endif 473 474 // Convert eth name to wl name 475 if (osifname_to_nvifname(name, ifname, sizeof(ifname)) != 0) 476 continue; 477 478#ifdef CONFIG_BCMWL5 479 // Slave intefaces have a '.' in the name 480 if (strchr(ifname, '.') && !include_vifs) 481 continue; 482#endif 483 484 if (get_ifname_unit(ifname, &unit, &subunit) < 0) 485 continue; 486 487 ret |= func(i++, unit, subunit, param); 488 } 489 return ret; 490} 491 492void notice_set(const char *path, const char *format, ...) 493{ 494 char p[256]; 495 char buf[2048]; 496 va_list args; 497 498 va_start(args, format); 499 vsnprintf(buf, sizeof(buf), format, args); 500 va_end(args); 501 502 mkdir("/var/notice", 0755); 503 snprintf(p, sizeof(p), "/var/notice/%s", path); 504 f_write_string(p, buf, 0, 0); 505 if (buf[0]) syslog(LOG_INFO, "notice[%s]: %s", path, buf); 506} 507 508 509// #define _x_dprintf(args...) syslog(LOG_DEBUG, args); 510#define _x_dprintf(args...) do { } while (0); 511 512// ----------------------------------------------------------------------------- 513#define ACT_COMM_LEN 20 514struct action_s { 515 char comm[ACT_COMM_LEN]; 516 pid_t pid; 517 int action; 518}; 519 520void set_action(int a) 521{ 522 int r = 3; 523 struct action_s act; 524 char *s, *p, stat[sizeof("/proc/XXXXXX/statXXXXXX")]; 525 526 act.action = a; 527 act.pid = getpid(); 528 snprintf(stat, sizeof(stat), "/proc/%d/stat", act.pid); 529 s = file2str(stat); 530 if (s) { 531 if ((p = strrchr(s, ')')) != NULL) 532 *p = '\0'; 533 if ((p = strchr(s, '(')) != NULL) 534 snprintf(act.comm, sizeof(act.comm), "%s", ++p); 535 free(s); 536 s = (p && *act.comm) ? act.comm : NULL; 537 } 538 if (!s) 539 snprintf(act.comm, sizeof(act.comm), "%d <UNKNOWN>", act.pid); 540 _dprintf("%d: set_action %d\n", getpid(), act.action); 541 while (f_write_excl(ACTION_LOCK, &act, sizeof(act), 0, 0600) != sizeof(act)) { 542 sleep(1); 543 if (--r == 0) return; 544 } 545 if (a != ACT_IDLE) sleep(2); 546} 547 548static int __check_action(struct action_s *pa) 549{ 550 int r = 3; 551 struct action_s act; 552 553 while (f_read_excl(ACTION_LOCK, &act, sizeof(act)) != sizeof(act)) { 554 sleep(1); 555 if (--r == 0) return ACT_UNKNOWN; 556 } 557 if (pa) 558 *pa = act; 559 _dprintf("%d: check_action %d\n", getpid(), act.action); 560 561 return act.action; 562} 563 564int check_action(void) 565{ 566 return __check_action(NULL); 567} 568 569int wait_action_idle(int n) 570{ 571 int r; 572 struct action_s act; 573 574 while (n-- > 0) { 575 act.pid = 0; 576 if (__check_action(&act) == ACT_IDLE) return 1; 577 if (act.pid > 0 && !process_exists(act.pid)) { 578 if (!(r = unlink(ACTION_LOCK)) || errno == ENOENT) { 579 _dprintf("Terminated process, pid %d %s, hold action lock %d !!!\n", 580 act.pid, act.comm, act.action); 581 return 1; 582 } 583 _dprintf("Remove " ACTION_LOCK " failed. errno %d (%s)\n", errno, strerror(errno)); 584 } 585 sleep(1); 586 } 587 _dprintf("pid %d %s hold action lock %d !!!\n", act.pid, act.comm, act.action); 588 return 0; 589} 590 591const char *get_wanip(void) 592{ 593 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 594 595 snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit()); 596 597 return nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)); 598} 599 600int get_wanstate(void) 601{ 602 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 603 604 snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit()); 605 606 return nvram_get_int(strcat_r(prefix, "state_t", tmp)); 607} 608 609const char *get_wanface(void) 610{ 611 return get_wan_ifname(wan_primary_ifunit()); 612} 613 614#ifdef RTCONFIG_IPV6 615const char *get_wan6face(void) 616{ 617 switch (get_ipv6_service()) { 618 case IPV6_NATIVE_DHCP: 619#ifdef RTCONFIG_6RELAYD 620 case IPV6_PASSTHROUGH: 621#endif 622 case IPV6_MANUAL: 623 return get_wanface(); 624 case IPV6_6TO4: 625 return "v6to4"; 626 case IPV6_6IN4: 627 return "v6in4"; 628 case IPV6_6RD: 629 return "6rd"; 630 } 631 return ""; 632} 633 634int update_6rd_info(void) 635{ 636 char tmp[100], prefix[]="wanXXXXX_"; 637 char addr6[INET6_ADDRSTRLEN + 1], *value; 638 struct in6_addr addr; 639 640 if (get_ipv6_service() != IPV6_6RD || !nvram_get_int(ipv6_nvname("ipv6_6rd_dhcp"))) 641 return -1; 642 643 snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit()); 644 645 value = nvram_safe_get(strcat_r(prefix, "6rd_prefix", tmp)); 646 if (*value ) { 647 /* try to compact IPv6 prefix */ 648 if (inet_pton(AF_INET6, value, &addr) > 0) 649 value = (char *) inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6)); 650 nvram_set(ipv6_nvname("ipv6_6rd_prefix"), value); 651 nvram_set(ipv6_nvname("ipv6_6rd_router"), nvram_safe_get(strcat_r(prefix, "6rd_router", tmp))); 652 nvram_set(ipv6_nvname("ipv6_6rd_prefixlen"), nvram_safe_get(strcat_r(prefix, "6rd_prefixlen", tmp))); 653 nvram_set(ipv6_nvname("ipv6_6rd_ip4size"), nvram_safe_get(strcat_r(prefix, "6rd_ip4size", tmp))); 654 return 1; 655 } 656 657 return 0; 658} 659#endif 660 661const char *_getifaddr(const char *ifname, int family, int flags, char *buf, int size) 662{ 663 struct ifaddrs *ifap, *ifa; 664 union { 665#ifdef RTCONFIG_IPV6 666 struct in6_addr in6; 667#endif 668 struct in_addr in; 669 } addrbuf; 670 unsigned char *addr, *netmask, *paddr, *pnetmask; 671 unsigned char len, maxlen; 672 673 if (getifaddrs(&ifap) != 0) { 674 _dprintf("getifaddrs failed: %s\n", strerror(errno)); 675 return NULL; 676 } 677 678 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 679 if (ifa->ifa_addr == NULL || 680 ifa->ifa_addr->sa_family != family || 681 strncmp(ifa->ifa_name, ifname, IFNAMSIZ) != 0) 682 continue; 683 684 switch (ifa->ifa_addr->sa_family) { 685#ifdef RTCONFIG_IPV6 686 case AF_INET6: 687 addr = (void *) &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr; 688 if (IN6_IS_ADDR_LINKLOCAL(addr) ^ !!(flags & GIF_LINKLOCAL)) 689 continue; 690 netmask = (void *) &((struct sockaddr_in6 *) ifa->ifa_netmask)->sin6_addr; 691 maxlen = sizeof(struct in6_addr) * 8; 692 break; 693#endif 694 case AF_INET: 695 addr = (void *) &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; 696 netmask = (void *) &((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr; 697 maxlen = sizeof(struct in_addr) * 8; 698 break; 699 default: 700 continue; 701 } 702 703 if ((flags & GIF_PREFIX) && addr && netmask) { 704 paddr = addr = memcpy(&addrbuf, addr, maxlen / 8); 705 pnetmask = netmask; 706 for (len = 0; len < maxlen; len += 8) 707 *paddr++ &= *pnetmask++; 708 } 709 710 if (addr && inet_ntop(ifa->ifa_addr->sa_family, addr, buf, size) != NULL) { 711 if ((flags & GIF_PREFIXLEN) && netmask) { 712 for (len = 0; len < maxlen && *netmask == 0xff; len += 8) 713 netmask++; 714 if (len < maxlen && *netmask) { 715 switch (*netmask) { 716 case 0xfe: len += 7; break; 717 case 0xfc: len += 6; break; 718 case 0xf8: len += 5; break; 719 case 0xf0: len += 4; break; 720 case 0xe0: len += 3; break; 721 case 0xc0: len += 2; break; 722 case 0x80: len += 1; break; 723 default: 724 _dprintf("getifaddrs netmask error: %x\n", *netmask); 725 goto error; 726 } 727 } 728 if (len < maxlen) { 729 netmask = memchr(buf, 0, size); 730 if (netmask) 731 snprintf(netmask, size - ((char *) netmask - buf), "/%d", len); 732 } 733 } 734 freeifaddrs(ifap); 735 return buf; 736 } 737 } 738 739error: 740 freeifaddrs(ifap); 741 return NULL; 742} 743 744const char *getifaddr(const char *ifname, int family, int flags) 745{ 746 static char buf[INET6_ADDRSTRLEN]; 747 748 return _getifaddr(ifname, family, flags, buf, sizeof(buf)); 749} 750 751int is_intf_up(const char* ifname) 752{ 753 struct ifreq ifr; 754 int sfd; 755 int ret = 0; 756 757 if (!((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)) 758 { 759 strcpy(ifr.ifr_name, ifname); 760 if (!ioctl(sfd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP)) 761 ret = 1; 762 763 close(sfd); 764 } 765 766 return ret; 767} 768 769char *wl_nvname(const char *nv, int unit, int subunit) 770{ 771 static char tmp[128]; 772 char prefix[] = "wlXXXXXXXXXX_"; 773 774 if (unit < 0) 775 strcpy(prefix, "wl_"); 776 else if (subunit > 0) 777 snprintf(prefix, sizeof(prefix), "wl%d.%d_", unit, subunit); 778 else 779 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 780 return strcat_r(prefix, nv, tmp); 781} 782 783// ----------------------------------------------------------------------------- 784 785int mtd_getinfo(const char *mtdname, int *part, int *size) 786{ 787 FILE *f; 788 char s[256]; 789 char t[256]; 790 int r; 791 792 r = 0; 793 if ((strlen(mtdname) < 128)) { // && (strcmp(mtdname, "pmon") != 0)) { //Yau dbg 794 sprintf(t, "\"%s\"", mtdname); 795 if ((f = fopen("/proc/mtd", "r")) != NULL) { 796 while (fgets(s, sizeof(s), f) != NULL) { 797 if ((sscanf(s, "mtd%d: %x", part, size) == 2) && (strstr(s, t) != NULL)) { 798 // don't accidentally mess with bl (0) 799 if (*part >= 0) r = 1; //Yau > -> >= 800 r =1; 801 break; 802 } 803 } 804 fclose(f); 805 } 806 } 807 if (!r) { 808 *size = 0; 809 *part = -1; 810 } 811 return r; 812} 813 814#if defined(RTCONFIG_UBIFS) 815#define UBI_SYSFS_DIR "/sys/class/ubi" 816/* return device number, volume id, and volume size in bytes 817 * @return: 818 * 1: ubi volume not found 819 * 0: success 820 * -1: invalid parameter 821 * -2: UBI not exist (open /sys/class/ubi failed) 822 * <0: error 823 */ 824int ubi_getinfo(const char *ubiname, int *dev, int *part, int *size) 825{ 826 DIR *dir; 827 int d, p, l, cmp, ret = 1; 828 char *s1, *s2, path[PATH_MAX]; 829 struct dirent *ent; 830 831 if (!ubiname || *ubiname == '\0' || !dev || !part || !size) 832 return -1; 833 834 if ((dir = opendir(UBI_SYSFS_DIR)) == NULL) 835 return -2; 836 837 while (ret && (ent = readdir(dir)) != NULL) { 838 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || strncmp(ent->d_name, "ubi", 3)) 839 continue; 840 if (sscanf(ent->d_name, "ubi%d_%d", &d, &p) != 2) 841 continue; 842 843 snprintf(path, sizeof(path), "%s/ubi%d_%d/name", UBI_SYSFS_DIR, d, p); 844 if (!(s1 = file2str(path))) 845 continue; 846 /* remove tailed line-feed character */ 847 l = strlen(s1); 848 if (*(s1+l-1) == '\xa') 849 *(s1+l-1) = '\0'; 850 cmp = strcmp(ubiname, s1); 851 free(s1); 852 if (cmp) 853 continue; 854 855 snprintf(path, sizeof(path), "%s/ubi%d_%d/data_bytes", UBI_SYSFS_DIR, d, p); 856 if (!(s2 = file2str(path))) 857 continue; 858 *dev = d; 859 *part = p; 860 *size = atoi(s2); 861 free(s2); 862 ret = 0; 863 } 864 closedir(dir); 865 866 return ret; 867} 868#endif 869 870// ----------------------------------------------------------------------------- 871 872int nvram_get_int(const char *key) 873{ 874 return atoi(nvram_safe_get(key)); 875} 876 877int nvram_set_int(const char *key, int value) 878{ 879 char nvramstr[16]; 880 881 snprintf(nvramstr, sizeof(nvramstr), "%d", value); 882 return nvram_set(key, nvramstr); 883} 884 885double nvram_get_double(const char *key) 886{ 887 return atof(nvram_safe_get(key)); 888} 889 890int nvram_set_double(const char *key, double value) 891{ 892 char nvramstr[33]; 893 894 snprintf(nvramstr, sizeof(nvramstr), "%.9g", value); 895 return nvram_set(key, nvramstr); 896} 897 898#if defined(RTCONFIG_SSH) || defined(RTCONFIG_HTTPS) 899int nvram_get_file(const char *key, const char *fname, int max) 900{ 901 int n; 902 char *p; 903 char *b; 904 int r; 905 906 r = 0; 907 p = nvram_safe_get(key); 908 n = strlen(p); 909 if (n <= max) { 910 if ((b = malloc(base64_decoded_len(n) + 128)) != NULL) { 911 n = base64_decode(p, (unsigned char *) b, n); 912 if (n > 0) r = (f_write(fname, b, n, 0, 0644) == n); 913 free(b); 914 } 915 } 916 return r; 917/* 918 char b[2048]; 919 int n; 920 char *p; 921 922 p = nvram_safe_get(key); 923 n = strlen(p); 924 if (n <= max) { 925 n = base64_decode(p, b, n); 926 if (n > 0) return (f_write(fname, b, n, 0, 0700) == n); 927 } 928 return 0; 929*/ 930} 931 932int nvram_set_file(const char *key, const char *fname, int max) 933{ 934 char *in; 935 char *out; 936 long len; 937 int n; 938 int r; 939 940 if ((len = f_size(fname)) > max) return 0; 941 max = (int)len; 942 r = 0; 943 if (f_read_alloc(fname, &in, max) == max) { 944 if ((out = malloc(base64_encoded_len(max) + 128)) != NULL) { 945 n = base64_encode((unsigned char *) in, out, max); 946 out[n] = 0; 947 nvram_set(key, out); 948 free(out); 949 r = 1; 950 } 951 free(in); 952 } 953 return r; 954/* 955 char a[2048]; 956 char b[4096]; 957 int n; 958 959 if (((n = f_read(fname, &a, sizeof(a))) > 0) && (n <= max)) { 960 n = base64_encode(a, b, n); 961 b[n] = 0; 962 nvram_set(key, b); 963 return 1; 964 } 965 return 0; 966*/ 967} 968#endif 969 970int nvram_contains_word(const char *key, const char *word) 971{ 972 return (find_word(nvram_safe_get(key), word) != NULL); 973} 974 975int nvram_is_empty(const char *key) 976{ 977 char *p; 978 return (((p = nvram_get(key)) == NULL) || (*p == 0)); 979} 980 981void nvram_commit_x(void) 982{ 983 if (!nvram_get_int("debug_nocommit")) nvram_commit(); 984} 985 986void chld_reap(int sig) 987{ 988 while (waitpid(-1, NULL, WNOHANG) > 0) {} 989} 990 991static uint32 crc_table[256]={ 0x00000000,0x77073096,0xEE0E612C,0x990951BA, 9920x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E, 9930x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2, 9940xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856, 9950x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, 9960x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD, 9970xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75, 9980xDCD60DCF,0xABD13D59,0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5, 9990x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924, 10000x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC, 10010xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934, 10020x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4, 10030x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, 10040x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3, 10050xFBD44C65,0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7, 10060xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73, 10070x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086, 10080x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822, 10090xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6, 10100x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12, 10110x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, 10120xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671, 10130x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9, 10140x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1, 10150xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60, 10160xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0, 10170x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28, 10180x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0, 10190xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, 10200x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7, 10210x0BDBDF21,0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B, 10220x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF, 10230xF862AE69,0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2, 10240xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66, 10250x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A, 10260x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E, 10270xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D}; 1028 1029uint32_t crc_calc(uint32_t crc, const char *buf, int len) 1030{ 1031 crc = crc ^ 0xffffffff; 1032 while (len-- > 0) { 1033 crc = crc_table[(crc ^ *((unsigned char *)buf)) & 0xFF] ^ (crc >> 8); 1034 buf++; 1035 } 1036 crc = crc ^ 0xffffffff; 1037 return crc; 1038} 1039 1040// ugly solution and doesn't support wantag 1041void bcmvlan_models(int model, char *vlan) 1042{ 1043 switch (model) { 1044 case MODEL_DSLAC68U: 1045 case MODEL_RPAC68U: 1046 case MODEL_RTAC68U: 1047 case MODEL_RTAC87U: 1048 case MODEL_RTAC56S: 1049 case MODEL_RTAC56U: 1050 case MODEL_RTAC66U: 1051 case MODEL_RTN66U: 1052 case MODEL_RTN16: 1053 case MODEL_RTN18U: 1054 case MODEL_RTN15U: 1055 case MODEL_RTAC53U: 1056 case MODEL_RTAC3200: 1057 case MODEL_RTAC88U: 1058 case MODEL_RTAC3100: 1059 case MODEL_RTAC5300: 1060 case MODEL_RTAC5300R: 1061 case MODEL_RTAC1200G: 1062 case MODEL_RTAC1200GP: 1063 strcpy(vlan, "vlan1"); 1064 break; 1065 case MODEL_RTN53: 1066 case MODEL_RTN12: 1067 case MODEL_RTN12B1: 1068 case MODEL_RTN12C1: 1069 case MODEL_RTN12D1: 1070 case MODEL_RTN12VP: 1071 case MODEL_RTN12HP: 1072 case MODEL_RTN12HP_B1: 1073 case MODEL_RTN14UHP: 1074 case MODEL_RTN10U: 1075 case MODEL_RTN10P: 1076 case MODEL_RTN10D1: 1077 case MODEL_RTN10PV2: 1078 strcpy(vlan, "vlan0"); 1079 break; 1080 default: 1081 strcpy(vlan, ""); 1082 break; 1083 } 1084} 1085 1086char *get_productid(void) 1087{ 1088 char *productid = nvram_safe_get("productid"); 1089#ifdef RTCONFIG_ODMPID 1090 char *odmpid = nvram_safe_get("odmpid"); 1091 if (*odmpid) 1092 productid = odmpid; 1093#endif 1094 return productid; 1095} 1096 1097int backup_rx; 1098int backup_tx; 1099int backup_set = 0; 1100 1101unsigned int netdev_calc(char *ifname, char *ifname_desc, unsigned long *rx, unsigned long *tx, char *ifname_desc2, unsigned long *rx2, unsigned long *tx2) 1102{ 1103 char word[100], word1[100], *next, *next1; 1104 char tmp[100]; 1105 char modelvlan[32]; 1106 int i, j, model, unit; 1107 strcpy(ifname_desc2, ""); 1108 1109 model = get_model(); 1110 bcmvlan_models(model, modelvlan); 1111 1112 // find in LAN interface 1113 if(nvram_contains_word("lan_ifnames", ifname)) 1114 { 1115 // find Wireless interface 1116 i=0; 1117 foreach(word, nvram_safe_get("wl_ifnames"), next) { 1118 if(strcmp(word, ifname)==0) { 1119 sprintf(ifname_desc, "WIRELESS%d", i); 1120 return 1; 1121 } 1122 1123#ifdef RTCONFIG_RALINK 1124 if(model == MODEL_RTN65U && strncmp(ifname, "rai", 3) == 0) // invalid traffic amount for interface 1125 return 0; 1126#endif 1127 1128 sprintf(tmp, "wl%d_vifnames", i); 1129 j = 0; 1130 foreach(word1, nvram_safe_get(tmp), next1) { 1131 if(strcmp(word1, wif_to_vif(ifname))==0) 1132 { 1133 sprintf(ifname_desc, "WIRELESS%d.%d", i, j); 1134 return 1; 1135 } 1136 j++; 1137 } 1138 1139 i++; 1140 } 1141 1142#if defined(RTCONFIG_RALINK) && defined(RTCONFIG_WLMODULE_RT3352_INIC_MII) 1143 if(model == MODEL_RTN65U) 1144 { 1145 i = 0; 1146 j = 0; 1147 foreach(word, nvram_safe_get("nic_lan_ifnames"), next) { 1148 if(strcmp(word, ifname)==0) 1149 { 1150 sprintf(tmp, "wl%d_vifnames", 0); 1151 foreach(word1, nvram_safe_get(tmp), next1) { 1152 char vifname[32]; 1153 sprintf(vifname, "%s_ifname", word1); 1154 if(strlen(nvram_safe_get(vifname)) > 0) 1155 { 1156 if(i-- == 0) 1157 break; 1158 } 1159 j++; 1160 } 1161 sprintf(ifname_desc, "WIRELESS%d.%d", 0, j); 1162 return 1; 1163 } 1164 i++; 1165 } 1166 } 1167#endif 1168 1169 // find wired interface 1170 strcpy(ifname_desc, "WIRED"); 1171 1172 if(model == MODEL_DSLAC68U) 1173 return 1; 1174 1175#ifdef RTCONFIG_BCM5301X_TRAFFIC_MONITOR 1176 return 1; 1177#endif 1178 1179 // special handle for non-tag wan of broadcom solution 1180 // pretend vlanX is must called after ethX 1181 if(nvram_match("switch_wantag", "none")) { //Don't calc if select IPTV 1182 if(backup_set && strlen(modelvlan) && strcmp(ifname, modelvlan)==0) { 1183 backup_set = 0; 1184 backup_rx -= *rx; 1185 backup_tx -= *tx; 1186 1187 *rx2 = backup_rx; 1188 *tx2 = backup_tx; 1189 /* Cherry Cho modified for RT-AC3200 Bug#202 in 2014/11/4. */ 1190 unit = get_wan_unit("eth0"); 1191 1192#ifdef RTCONFIG_DUALWAN 1193 if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) ) 1194 { 1195 if (unit == WAN_UNIT_FIRST) 1196 strcpy(ifname_desc2, "INTERNET"); 1197 else 1198 sprintf(ifname_desc2,"INTERNET%d", unit); 1199 } 1200#else 1201 if(unit == wan_primary_ifunit()) 1202 strcpy(ifname_desc2, "INTERNET"); 1203#endif /* RTCONFIG_DUALWAN */ 1204 } 1205 }//End of switch_wantag 1206 1207 return 1; 1208 } 1209 // find bridge interface 1210 else if(nvram_match("lan_ifname", ifname)) 1211 { 1212 strcpy(ifname_desc, "BRIDGE"); 1213 return 1; 1214 } 1215 // find in WAN interface 1216 else if (ifname && (unit = get_wan_unit(ifname)) >= 0) { 1217 if (dualwan_unit__nonusbif(unit)) { 1218#if defined(RA_ESW) 1219#if defined(RTCONFIG_RALINK_MT7620) 1220 get_mt7620_wan_unit_bytecount(unit, tx, rx); 1221#elif defined(RTCONFIG_RALINK_MT7621) 1222 get_mt7621_wan_unit_bytecount(unit, tx, rx); 1223#endif 1224#endif 1225#ifndef RTCONFIG_BCM5301X_TRAFFIC_MONITOR 1226 if(strlen(modelvlan) && strcmp(ifname, "eth0")==0) { 1227 backup_rx = *rx; 1228 backup_tx = *tx; 1229 backup_set = 1; 1230 } 1231 else{ 1232#endif 1233#ifdef RTCONFIG_DUALWAN 1234 if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) ) 1235 { 1236 if (unit == WAN_UNIT_FIRST) { 1237 strcpy(ifname_desc, "INTERNET"); 1238 return 1; 1239 } 1240 else { 1241 sprintf(ifname_desc,"INTERNET%d", unit); 1242 return 1; 1243 } 1244 } 1245#else 1246 if(unit == wan_primary_ifunit()){ 1247 strcpy(ifname_desc, "INTERNET"); 1248 return 1; 1249 } 1250#endif /* RTCONFIG_DUALWAN */ 1251#ifndef RTCONFIG_BCM5301X_TRAFFIC_MONITOR 1252 } 1253#endif 1254 } 1255 else if (dualwan_unit__usbif(unit)) { 1256#ifdef RTCONFIG_DUALWAN 1257 if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) ) 1258 { 1259 if(unit == WAN_UNIT_FIRST){//Cherry Cho modified in 2014/11/4. 1260 strcpy(ifname_desc, "INTERNET"); 1261 return 1; 1262 } 1263 else{ 1264 sprintf(ifname_desc,"INTERNET%d", unit); 1265 return 1; 1266 } 1267 } 1268#else 1269 if(unit == wan_primary_ifunit()){ 1270 strcpy(ifname_desc, "INTERNET"); 1271 return 1; 1272 } 1273#endif /* RTCONFIG_DUALWAN */ 1274 } 1275 else { 1276 _dprintf("%s: unknown ifname %s\n", __func__, ifname); 1277 } 1278 } 1279 1280 return 0; 1281} 1282 1283// 0: Not private subnet, 1: A class, 2: B class, 3: C class. 1284int is_private_subnet(const char *ip) 1285{ 1286 unsigned long long ip_num; 1287 unsigned long long A_class_start, A_class_end; 1288 unsigned long long B_class_start, B_class_end; 1289 unsigned long long C_class_start, C_class_end; 1290 1291 if(ip == NULL) 1292 return 0; 1293 1294 A_class_start = inet_network("10.0.0.0"); 1295 A_class_end = inet_network("10.255.255.255"); 1296 B_class_start = inet_network("172.16.0.0"); 1297 B_class_end = inet_network("172.31.255.255"); 1298 C_class_start = inet_network("192.168.0.0"); 1299 C_class_end = inet_network("192.168.255.255"); 1300 1301 ip_num = inet_network(ip); 1302 1303 if(ip_num > A_class_start && ip_num < A_class_end) 1304 return 1; 1305 else if(ip_num > B_class_start && ip_num < B_class_end) 1306 return 2; 1307 else if(ip_num > C_class_start && ip_num < C_class_end) 1308 return 3; 1309 else 1310 return 0; 1311} 1312 1313// clean_mode: 0~3, clean_time: 0~(LONG_MAX-1), threshold(KB): 0: always act, >0: act when lower than. 1314int free_caches(const char *clean_mode, const int clean_time, const unsigned int threshold){ 1315 int test_num; 1316 FILE *fp; 1317 char memdata[256] = {0}; 1318 unsigned int memfree = 0; 1319 1320#ifdef RTCONFIG_BCMARM 1321 return 0; 1322#endif 1323 1324 /* Paul add 2012/7/17, skip free caches for DSL model. */ 1325 #ifdef RTCONFIG_DSL 1326 return 0; 1327 #endif 1328 1329 if(!clean_mode || clean_time < 0) 1330 return -1; 1331 1332_dprintf("clean_mode(%s) clean_time(%d) threshold(%u)\n", clean_mode, clean_time, threshold); 1333 test_num = strtol(clean_mode, NULL, 10); 1334 if(test_num == LONG_MIN || test_num == LONG_MAX 1335 || test_num < atoi(FREE_MEM_NONE) || test_num > atoi(FREE_MEM_ALL) 1336 ) 1337 return -1; 1338 1339 if(threshold > 0){ 1340 if((fp = fopen("/proc/meminfo", "r")) != NULL){ 1341 while(fgets(memdata, 255, fp) != NULL){ 1342 if(strstr(memdata, "MemFree") != NULL){ 1343 sscanf(memdata, "MemFree: %d kB", &memfree); 1344_dprintf("%s: memfree=%u.\n", __FUNCTION__, memfree); 1345 break; 1346 } 1347 } 1348 fclose(fp); 1349 if(memfree > threshold){ 1350_dprintf("%s: memfree > threshold.\n", __FUNCTION__); 1351 return 0; 1352 } 1353 } 1354 } 1355 1356_dprintf("%s: Start syncing...\n", __FUNCTION__); 1357 sync(); 1358 1359_dprintf("%s: Start cleaning...\n", __FUNCTION__); 1360 f_write_string("/proc/sys/vm/drop_caches", clean_mode, 0, 0); 1361 if(clean_time > 0){ 1362_dprintf("%s: waiting %d second...\n", __FUNCTION__, clean_time); 1363 sleep(clean_time); 1364_dprintf("%s: Finish.\n", __FUNCTION__); 1365 f_write_string("/proc/sys/vm/drop_caches", FREE_MEM_NONE, 0, 0); 1366 } 1367 1368 return 0; 1369} 1370 1371void logmessage_normal(char *logheader, char *fmt, ...){ 1372 va_list args; 1373 char buf[512]; 1374 1375 va_start(args, fmt); 1376 1377 vsnprintf(buf, sizeof(buf), fmt, args); 1378 1379 openlog(logheader, 0, 0); 1380 syslog(0, buf); 1381 closelog(); 1382 va_end(args); 1383} 1384 1385char *get_logfile_path(void) 1386{ 1387 static char prefix[] = "/jffsXXXXXX"; 1388 1389#if defined(RTCONFIG_PSISTLOG) 1390 strcpy(prefix, "/jffs"); 1391 if (!check_if_dir_writable(prefix)) { 1392 _dprintf("logfile output directory: /tmp.\n"); 1393 strcpy(prefix, "/tmp"); 1394 } 1395#else 1396 strcpy(prefix, "/tmp"); 1397#endif 1398 1399 return prefix; 1400} 1401 1402char *get_syslog_fname(unsigned int idx) 1403{ 1404 char prefix[] = "/jffsXXXXXX"; 1405 static char buf[PATH_MAX]; 1406 1407#if defined(RTCONFIG_PSISTLOG) 1408 strcpy(prefix, "/jffs"); 1409 if (!check_if_dir_writable(prefix)) { 1410 _dprintf("syslog output directory: /tmp.\n"); 1411 strcpy(prefix, "/tmp"); 1412 } 1413#else 1414 strcpy(prefix, "/tmp"); 1415#endif 1416 1417 if (!idx) 1418 sprintf(buf, "%s/syslog.log", prefix); 1419 else 1420 sprintf(buf, "%s/syslog.log-%d", prefix, idx); 1421 1422 return buf; 1423} 1424 1425#ifdef RTCONFIG_USB_MODEM 1426char *get_modemlog_fname(void){ 1427 char prefix[] = "/tmpXXXXXX"; 1428 static char buf[PATH_MAX]; 1429 1430 strcpy(prefix, "/tmp"); 1431 sprintf(buf, "%s/3ginfo.txt", prefix); 1432 1433 return buf; 1434} 1435#endif 1436 1437#ifdef RTCONFIG_BCMWL6 1438#ifdef RTCONFIG_PROXYSTA 1439int is_psta(int unit) 1440{ 1441 if (unit < 0) return 0; 1442 if ((nvram_get_int("sw_mode") == SW_MODE_AP) && 1443 (nvram_get_int("wlc_psta") == 1) && 1444 ((nvram_get_int("wlc_band") == unit) 1445#ifdef PXYSTA_DUALBAND 1446 || (nvram_match("exband", "1") && nvram_get_int("wlc_band_ex") == unit) 1447#endif 1448 )) 1449 return 1; 1450 1451 return 0; 1452} 1453 1454int is_psr(int unit) 1455{ 1456 if (unit < 0) return 0; 1457#ifdef RTCONFIG_QTN 1458 if (unit == 1) return 0; 1459#endif 1460 if ((nvram_get_int("sw_mode") == SW_MODE_AP) && 1461 (nvram_get_int("wlc_psta") == 2) && 1462 ((nvram_get_int("wlc_band") == unit) 1463#ifdef PXYSTA_DUALBAND 1464 || (nvram_match("exband", "1") && nvram_get_int("wlc_band_ex") == unit) 1465#endif 1466 )) 1467 return 1; 1468 1469 return 0; 1470} 1471 1472int psta_exist() 1473{ 1474 char word[256], *next; 1475 int idx = 0; 1476 1477 foreach (word, nvram_safe_get("wl_ifnames"), next) { 1478 if (is_psta(idx)) return 1; 1479 idx++; 1480 } 1481 1482 return 0; 1483} 1484 1485int psta_exist_except(int unit) 1486{ 1487 char word[256], *next; 1488 int idx = 0; 1489 1490 if (unit < 0) return 0; 1491 foreach (word, nvram_safe_get("wl_ifnames"), next) { 1492 if (idx == unit) goto END; 1493 if (is_psta(idx)) return 1; 1494END: 1495 idx++; 1496 } 1497 1498 return 0; 1499} 1500 1501int psr_exist() 1502{ 1503 char word[256], *next; 1504 int idx = 0; 1505 1506 foreach (word, nvram_safe_get("wl_ifnames"), next) { 1507 if (is_psr(idx)) return 1; 1508 idx++; 1509 } 1510 1511 return 0; 1512} 1513 1514int psr_exist_except(int unit) 1515{ 1516 char word[256], *next; 1517 int idx = 0; 1518 1519 if (unit < 0) return 0; 1520 foreach (word, nvram_safe_get("wl_ifnames"), next) { 1521 if (idx == unit) goto END; 1522 if (is_psr(idx)) return 1; 1523END: 1524 idx++; 1525 } 1526 1527 return 0; 1528} 1529#endif 1530#endif 1531 1532#ifdef RTCONFIG_OPENVPN 1533char *get_parsed_crt(const char *name, char *buf, size_t buf_len) 1534{ 1535 char *value; 1536 int len, i; 1537#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1538 FILE *fp; 1539 char tmpBuf[256] = {0}; 1540 char *p = buf; 1541#endif 1542 1543 value = nvram_safe_get(name); 1544 len = strlen(value); 1545 1546#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1547 if(!check_if_dir_exist(OVPN_FS_PATH)) 1548 mkdir(OVPN_FS_PATH, S_IRWXU); 1549 snprintf(tmpBuf, sizeof(tmpBuf) -1, "%s/%s", OVPN_FS_PATH, name); 1550#endif 1551 1552 if(len) { 1553 for (i=0; (i < len); i++) { 1554 if (value[i] == '>') 1555 buf[i] = '\n'; 1556 else 1557 buf[i] = value[i]; 1558 } 1559 buf[i] = '\0'; 1560 1561#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1562 //save to file and then clear nvram value 1563 fp = fopen(tmpBuf, "w"); 1564 if(fp) { 1565 chmod(tmpBuf, S_IRUSR|S_IWUSR); 1566 fprintf(fp, "%s", buf); 1567 fclose(fp); 1568 nvram_set(name, ""); 1569 } 1570#endif 1571 } 1572 else { 1573#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1574 //nvram value cleard, get from file 1575 fp = fopen(tmpBuf, "r"); 1576 if(fp) { 1577 while(fgets(buf, buf_len, fp)) { 1578 if(!strncmp(buf, "-----BEGIN", 10)) 1579 break; 1580 } 1581 if(feof(fp)) { 1582 fclose(fp); 1583 memset(buf, 0, buf_len); 1584 return buf; 1585 } 1586 p += strlen(buf); 1587 memset(tmpBuf, 0, sizeof(tmpBuf)); 1588 while(fgets(tmpBuf, sizeof(tmpBuf), fp)) { 1589 strncpy(p, tmpBuf, strlen(tmpBuf)); 1590 p += strlen(tmpBuf); 1591 } 1592 *p = '\0'; 1593 fclose(fp); 1594 } 1595#endif 1596 } 1597 return buf; 1598} 1599 1600int set_crt_parsed(const char *name, char *file_path) 1601{ 1602#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1603 char target_file_path[128] ={0}; 1604 1605 if(!check_if_dir_exist(OVPN_FS_PATH)) 1606 mkdir(OVPN_FS_PATH, S_IRWXU); 1607 1608 if(check_if_file_exist(file_path)) { 1609 snprintf(target_file_path, sizeof(target_file_path) -1, "%s/%s", OVPN_FS_PATH, name); 1610 return eval("cp", file_path, target_file_path); 1611 } 1612 else { 1613 return -1; 1614 } 1615#else 1616 FILE *fp=fopen(file_path, "r"); 1617 char buffer[4000] = {0}; 1618 char buffer2[256] = {0}; 1619 char *p = buffer; 1620 1621 if(fp) { 1622 while(fgets(buffer, sizeof(buffer), fp)) { 1623 if(!strncmp(buffer, "-----BEGIN", 10)) 1624 break; 1625 } 1626 if(feof(fp)) { 1627 fclose(fp); 1628 return -EINVAL; 1629 } 1630 p += strlen(buffer); 1631 //if( *(p-1) == '\n' ) 1632 //*(p-1) = '>'; 1633 while(fgets(buffer2, sizeof(buffer2), fp)) { 1634 strncpy(p, buffer2, strlen(buffer2)); 1635 p += strlen(buffer2); 1636 //if( *(p-1) == '\n' ) 1637 //*(p-1) = '>'; 1638 } 1639 *p = '\0'; 1640 nvram_set(name, buffer); 1641 fclose(fp); 1642 return 0; 1643 } 1644 else 1645 return -ENOENT; 1646#endif 1647} 1648 1649int ovpn_crt_is_empty(const char *name) 1650{ 1651 char file_path[128] ={0}; 1652 struct stat st; 1653 1654 if( nvram_is_empty(name) ) { 1655#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 1656 //check file 1657 if(d_exists(OVPN_FS_PATH)) { 1658 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, name); 1659 if(stat(file_path, &st) == 0) { 1660 if( !S_ISDIR(st.st_mode) && st.st_size ) { 1661 return 0; 1662 } 1663 else { 1664 return 1; 1665 } 1666 } 1667 else { 1668 return 1; 1669 } 1670 } 1671 else { 1672 mkdir(OVPN_FS_PATH, S_IRWXU); 1673 return 1; 1674 } 1675#else 1676 return 1; 1677#endif 1678 } 1679 else { 1680 return 0; 1681 } 1682} 1683#endif 1684 1685#ifdef RTCONFIG_DUALWAN 1686/** 1687 * Get wan_unit of USB interface 1688 * @return 1689 * >= 0: wan_unit 1690 * < 0: not found 1691 */ 1692int get_usbif_dualwan_unit(void) 1693{ 1694 int wan_unit; 1695 1696 for (wan_unit = WAN_UNIT_FIRST; wan_unit < WAN_UNIT_MAX; ++wan_unit) 1697 if (dualwan_unit__usbif(wan_unit)) 1698 break; 1699 1700 if (wan_unit == WAN_UNIT_MAX) 1701 wan_unit = -1; 1702 1703 return wan_unit; 1704} 1705 1706/** 1707 * Get unit of primary interface (WAN/LAN/USB only) 1708 * @return 1709 * >= 0: wan_unit 1710 * < 0: not found 1711 */ 1712int get_primaryif_dualwan_unit(void) 1713{ 1714 int unit, wan_type; 1715 1716 for(unit = WAN_UNIT_FIRST; unit < WAN_UNIT_MAX; ++unit){ 1717 if (unit != wan_primary_ifunit() && !nvram_match("wans_mode", "lb")) 1718 continue; 1719 1720 wan_type = get_dualwan_by_unit(unit); 1721 if (wan_type != WANS_DUALWAN_IF_WAN 1722 && wan_type != WANS_DUALWAN_IF_LAN 1723 && wan_type != WANS_DUALWAN_IF_USB) 1724 continue; 1725 1726 break; 1727 } 1728 1729 if(unit == WAN_UNIT_MAX) 1730 unit = -1; 1731 1732 return unit; 1733} 1734#endif 1735 1736/* Return WiFi unit number in accordance with interface name. 1737 * @wif: pointer to WiFi interface name. 1738 * @return: 1739 * < 0: invalid 1740 * otherwise: unit 1741 */ 1742int get_wifi_unit(char *wif) 1743{ 1744 int i; 1745 char word[256], *next, *ifn, nv[20]; 1746 1747 if (!wif || *wif == '\0') 1748 return -1; 1749 foreach (word, nvram_safe_get("wl_ifnames"), next) { 1750 if (strncmp(word, wif, strlen(word))) 1751 continue; 1752 1753 for (i = 0; i <= 1; ++i) { 1754 sprintf(nv, "wl%d_ifname", i); 1755 ifn = nvram_safe_get(nv); 1756 if (!strncmp(word, ifn, strlen(word))) 1757 return i; 1758 } 1759 } 1760 return -1; 1761} 1762 1763 1764#ifdef RTCONFIG_YANDEXDNS 1765int get_yandex_dns(int family, int mode, char **server, int max_count) 1766{ 1767 static const struct { 1768 int mode; 1769 int family; 1770 char *server; 1771 } table[] = { 1772 { YADNS_BASIC, AF_INET, "77.88.8.8" }, /* dns.yandex.ru */ 1773 { YADNS_BASIC, AF_INET, "77.88.8.1" }, /* secondary.dns.yandex.ru */ 1774 { YADNS_SAFE, AF_INET, "77.88.8.88" }, /* safe.dns.yandex.ru */ 1775 { YADNS_SAFE, AF_INET, "77.88.8.2" }, /* secondary.safe.dns.yandex.ru */ 1776 { YADNS_FAMILY, AF_INET, "77.88.8.7" }, /* family.dns.yandex.ru */ 1777 { YADNS_FAMILY, AF_INET, "77.88.8.3" }, /* secondary.family.dns.yandex.ru */ 1778#ifdef RTCONFIG_IPV6 1779 { YADNS_BASIC, AF_INET6, "2a02:6b8::feed:0ff" }, /* dns.yandex.ru */ 1780 { YADNS_BASIC, AF_INET6, "2a02:6b8:0:1::feed:0ff" }, /* secondary.dns.yandex.ru */ 1781 { YADNS_SAFE, AF_INET6, "2a02:6b8::feed:bad" }, /* safe.dns.yandex.ru */ 1782 { YADNS_SAFE, AF_INET6, "2a02:6b8:0:1::feed:bad" }, /* secondary.safe.dns.yandex.ru */ 1783 { YADNS_FAMILY, AF_INET6, "2a02:6b8::feed:a11" }, /* family.dns.yandex.ru */ 1784 { YADNS_FAMILY, AF_INET6, "2a02:6b8:0:1::feed:a11" }, /* secondary.family.dns.yandex.ru */ 1785#endif 1786 }; 1787 int i, count = 0; 1788 1789 if (mode < YADNS_FIRST || mode >= YADNS_COUNT) 1790 return -1; 1791 1792 for (i = 0; i < sizeof(table)/sizeof(table[0]) && count < max_count; i++) { 1793 if ((mode == table[i].mode) && 1794 (family == AF_UNSPEC || family == table[i].family)) 1795 server[count++] = table[i].server; 1796 } 1797 1798 return count; 1799} 1800#endif 1801 1802#ifdef RTCONFIG_BWDPI 1803/* 1804 usage in rc or bwdpi for checking service 1805*/ 1806int check_bwdpi_nvram_setting() 1807{ 1808 int enabled = 1; 1809 int debug = nvram_get_int("bwdpi_debug"); 1810 1811 // check no qos service 1812 if(nvram_get_int("wrs_enable") == 0 && nvram_get_int("wrs_app_enable") == 0 && 1813 nvram_get_int("wrs_vp_enable") == 0 && nvram_get_int("wrs_cc_enable") == 0 && 1814 nvram_get_int("wrs_mals_enable") == 0 && 1815 nvram_get_int("bwdpi_db_enable") == 0 && 1816 nvram_get_int("apps_analysis") == 0 && 1817 nvram_get_int("bwdpi_wh_enable") == 0 && 1818 nvram_get_int("qos_enable") == 0) 1819 enabled = 0; 1820 1821 // check qos service (not adaptive qos) 1822 if(nvram_get_int("wrs_enable") == 0 && nvram_get_int("wrs_app_enable") == 0 && 1823 nvram_get_int("wrs_vp_enable") == 0 && nvram_get_int("wrs_cc_enable") == 0 && 1824 nvram_get_int("wrs_mals_enable") == 0 && 1825 nvram_get_int("bwdpi_db_enable") == 0 && 1826 nvram_get_int("apps_analysis") == 0 && 1827 nvram_get_int("bwdpi_wh_enable") == 0 && 1828 nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") != 1) 1829 enabled = 0; 1830 1831 if(debug) dbg("[check_bwdpi_nvram_setting] enabled= %d\n", enabled); 1832 1833 return enabled; 1834} 1835#endif 1836 1837/* 1838 transfer timestamp into date 1839 ex. date = 2014-07-14 19:20:10 1840*/ 1841void StampToDate(unsigned long timestamp, char *date) 1842{ 1843 struct tm *local; 1844 time_t now; 1845 1846 now = timestamp; 1847 local = localtime(&now); 1848 strftime(date, 30, "%Y-%m-%d %H:%M:%S", local); 1849} 1850 1851/* 1852 check filesize is over or not 1853 if over size, return 1, else return 0 1854*/ 1855int check_filesize_over(char *path, long int size) 1856{ 1857 struct stat st; 1858 off_t cursize; 1859 1860 stat(path, &st); 1861 cursize = st.st_size; 1862 1863 size = size * 1024; // KB 1864 1865 if(cursize > size) 1866 return 1; 1867 else 1868 return 0; 1869} 1870 1871/* 1872 get last month's timestamp 1873 ex. 1874 now = 1445817600 1875 tm = 2015/10/26 00:00:00 1876 t = 2015/10/01 00:00:00 1877 t_t = 1443628800 1878*/ 1879time_t get_last_month_timestamp() 1880{ 1881 struct tm local, t; 1882 time_t now, t_t = 0; 1883 1884 // get timestamp and tm 1885 time(&now); 1886 localtime_r(&now, &local); 1887 1888 // copy t from local 1889 t.tm_year = local.tm_year; 1890 t.tm_mon = local.tm_mon; 1891 t.tm_mday = 1; 1892 t.tm_hour = 0; 1893 t.tm_min = 0; 1894 t.tm_sec = 0; 1895 1896 // transfer tm to timestamp 1897 t_t = mktime(&t); 1898 1899 return t_t; 1900} 1901 1902int get_iface_hwaddr(char *name, unsigned char *hwaddr) 1903{ 1904 struct ifreq ifr; 1905 int ret = 0; 1906 int s; 1907 1908 /* open socket to kernel */ 1909 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1910 perror("socket"); 1911 return errno; 1912 } 1913 1914 /* do it */ 1915 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)-1); 1916 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; 1917 if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0) 1918 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 1919 1920 /* cleanup */ 1921 close(s); 1922 return ret; 1923} 1924 1925int internet_ready(void) 1926{ 1927 if(nvram_get_int("ntp_ready") == 1) 1928 return 1; 1929 return 0; 1930} 1931 1932void set_no_internet_ready(void) 1933{ 1934 nvram_set("ntp_ready", "0"); 1935} 1936 1937#ifdef RTCONFIG_TRAFFIC_LIMITER 1938static char *traffic_limiter_get_path(const char *type) 1939{ 1940 if (type == NULL) 1941 return NULL; 1942 else if (strcmp(type, "limit") == 0) 1943 return "/jffs/tld/tl_limit"; 1944 else if (strcmp(type, "alert") == 0) 1945 return "/jffs/tld/tl_alert"; 1946 else if (strcmp(type, "count") == 0) 1947 return "/jffs/tld/tl_count"; 1948 1949 return NULL; 1950} 1951 1952unsigned int traffic_limiter_read_bit(const char *type) 1953{ 1954 char *path; 1955 char buf[sizeof("4294967295")]; 1956 unsigned int val = 0; 1957 int debug = nvram_get_int("tl_debug"); 1958 1959 path = traffic_limiter_get_path(type); 1960 if (path && f_read_string(path, buf, sizeof(buf)) > 0) 1961 val = strtoul(buf, NULL, 10); 1962 1963 if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val); 1964 return val; 1965} 1966 1967void traffic_limiter_set_bit(const char *type, int unit) 1968{ 1969 char *path; 1970 char buf[sizeof("4294967295")]; 1971 unsigned int val = 0; 1972 int debug = nvram_get_int("tl_debug"); 1973 1974 path = traffic_limiter_get_path(type); 1975 if (path) { 1976 val = traffic_limiter_read_bit(type); 1977 val |= (1U << unit); 1978 snprintf(buf, sizeof(buf), "%u", val); 1979 f_write_string(path, buf, 0, 0); 1980 } 1981 1982 if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val); 1983} 1984 1985void traffic_limiter_clear_bit(const char *type, int unit) 1986{ 1987 char *path; 1988 char buf[sizeof("4294967295")]; 1989 unsigned int val = 0; 1990 int debug = nvram_get_int("tl_debug"); 1991 1992 path = traffic_limiter_get_path(type); 1993 if (path) { 1994 val = traffic_limiter_read_bit(type); 1995 val &= ~(1U << unit); 1996 snprintf(buf, sizeof(buf), "%u", val); 1997 f_write_string(path, buf, 0, 0); 1998 } 1999 2000 if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val); 2001} 2002 2003double traffic_limiter_get_realtime(int unit) 2004{ 2005 char path[PATH_MAX]; 2006 char buf[32]; 2007 double val = 0; 2008 2009 snprintf(path, sizeof(path), "/tmp/tl%d_realtime", unit); 2010 if (f_read_string(path, buf, sizeof(buf)) > 0) 2011 val = atof(buf); 2012 2013 return val; 2014} 2015 2016int TL_UNIT_S; // traffic limiter dual wan unit start 2017int TL_UNIT_E; // traffic limiter dual wan unit end 2018 2019int traffic_limiter_dualwan_check(char *dualwan_mode) 2020{ 2021 int ret = 1; 2022 2023 /* check daul wan mode */ 2024 if (!strcmp(dualwan_mode, "lb")) 2025 { 2026 // load balance 2027 TL_UNIT_S = WAN_UNIT_FIRST; 2028 TL_UNIT_E = WAN_UNIT_MAX; 2029 } 2030 else if (!strcmp(dualwan_mode, "fo") || !strcmp(dualwan_mode, "fb")) 2031 { 2032 // fail over or fail back 2033 TL_UNIT_S = wan_primary_ifunit(); 2034 TL_UNIT_E = wan_primary_ifunit() + 1; 2035 } 2036 else 2037 { 2038 printf("%s : can't identify daulwan_mode\n", __FUNCTION__); 2039 ret = 0; 2040 } 2041 2042 return ret; 2043} 2044#endif 2045