1/* 2 * Broadcom Home Gateway Reference Design 3 * Web Page Configuration Support Routines 4 * 5 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * $Id: broadcom.c 517676 2014-11-26 09:02:04Z $ 19 */ 20 21#ifdef WEBS 22#include <webs.h> 23#include <uemf.h> 24#include <ej.h> 25#else /* !WEBS */ 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <ctype.h> 30#include <errno.h> 31#include <unistd.h> 32#include <limits.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <sys/socket.h> 36#include <netinet/in.h> 37#include <arpa/inet.h> 38#include <netdb.h> 39#include <assert.h> 40#include <httpd.h> 41#endif /* WEBS */ 42 43 44/* Required for hash table headers*/ 45#if defined(linux) || defined(__NetBSD__) 46/* Use SVID search */ 47#define __USE_GNU 48#include <search.h> 49#elif defined(__ECOS) 50#include <search.h> 51#endif 52 53#include <typedefs.h> 54#include <proto/ethernet.h> 55#include <bcmparams.h> 56#include <bcmconfig.h> 57#include <bcmnvram.h> 58#include <bcmutils.h> 59#include <bcmdevs.h> 60#include <shutils.h> 61#include <wlif_utils.h> 62#include <netconf.h> 63#include <nvparse.h> 64#include <wlutils.h> 65#include <bcmcvar.h> 66#include <ezc.h> 67#include <opencrypto.h> 68#include <time.h> 69#include <epivers.h> 70#include "router_version.h" 71#include <proto/802.11.h> 72#include <proto/802.1d.h> 73#include <security_ipc.h> 74#ifdef __CONFIG_WPS__ 75#include <wps_ui.h> 76#endif 77#ifdef PLC 78#include <dict.h> 79#endif 80 81 82 83#ifdef __CONFIG_HSPOT__ 84#include "passpoint_gui.h" 85#endif /* __CONFIG_HSPOT__ */ 86 87#include <etioctl.h> 88#if defined(__CONFIG_TREND_IQOS__) && defined(CONFIG_TREND_IQOS_ENABLED) 89#include "iqos_gui.h" 90#endif /* __CONFIG_TREND_IQOS__ && CONFIG_TREND_IQOS_ENABLED */ 91 92#if defined(__CONFIG_VISUALIZATION__) && defined(CONFIG_VISUALIZATION_ENABLED) 93#include "vis_gui.h" 94#endif /* (__CONFIG_VISUALIZATION__) && (CONFIG_VISUALIZATION_ENABLED) */ 95 96#define HTTP_ERR_BAD_REQUEST 400 97 98/* FILE-CSTYLED */ 99int internal_init(void); 100 101static char * encrypt_var(char *varname, char *ctext, int ctext_len, char *ptext, int *ptext_len,char *key, int keylen); 102static char * decrypt_var(char *varname, char *ptext, int ptext_len, char *ctext, int *ctext_len,char *key, int keylen); 103char * make_wl_prefix(char *prefix,int prefix_size, int mode, char *ifname); 104static char * rfctime(const time_t *timep); 105static char * reltime(unsigned int seconds); 106static char * reltime_short(unsigned int seconds); 107static int wl_phytype_get(webs_t wp, int *phytype); 108#ifdef __CONFIG_WAPI_IAS__ 109static int cert_revoke(webs_t wp, char *sn_str); 110#endif 111 112#define WAN_PREFIX(unit, prefix) snprintf(prefix, sizeof(prefix), "wan%d_", unit) 113 114/* From wlc_rate.[ch] */ 115#define MCS_TABLE_SIZE 33 116 117struct mcs_table_info { 118 uint phy_rate_20; 119 uint phy_rate_40; 120}; 121 122/* rates are in units of Kbps */ 123static const struct mcs_table_info mcs_rate_table[MCS_TABLE_SIZE] = { 124 {6500, 13500}, /* MCS 0 */ 125 {13000, 27000}, /* MCS 1 */ 126 {19500, 40500}, /* MCS 2 */ 127 {26000, 54000}, /* MCS 3 */ 128 {39000, 81000}, /* MCS 4 */ 129 {52000, 108000}, /* MCS 5 */ 130 {58500, 121500}, /* MCS 6 */ 131 {65000, 135000}, /* MCS 7 */ 132 {13000, 27000}, /* MCS 8 */ 133 {26000, 54000}, /* MCS 9 */ 134 {39000, 81000}, /* MCS 10 */ 135 {52000, 108000}, /* MCS 11 */ 136 {78000, 162000}, /* MCS 12 */ 137 {104000, 216000}, /* MCS 13 */ 138 {117000, 243000}, /* MCS 14 */ 139 {130000, 270000}, /* MCS 15 */ 140 {19500, 40500}, /* MCS 16 */ 141 {39000, 81000}, /* MCS 17 */ 142 {58500, 121500}, /* MCS 18 */ 143 {78000, 162000}, /* MCS 19 */ 144 {117000, 243000}, /* MCS 20 */ 145 {156000, 324000}, /* MCS 21 */ 146 {175500, 364500}, /* MCS 22 */ 147 {195000, 405000}, /* MCS 23 */ 148 {26000, 54000}, /* MCS 24 */ 149 {52000, 108000}, /* MCS 25 */ 150 {78000, 162000}, /* MCS 26 */ 151 {104000, 216000}, /* MCS 27 */ 152 {156000, 324000}, /* MCS 28 */ 153 {208000, 432000}, /* MCS 29 */ 154 {234000, 486000}, /* MCS 30 */ 155 {260000, 540000}, /* MCS 31 */ 156 {0, 6000}, /* MCS 32 */ 157}; 158 159#define MCS_TABLE_RATE(mcs, _is40) ((_is40)? mcs_rate_table[(mcs)].phy_rate_40: \ 160 mcs_rate_table[(mcs)].phy_rate_20) 161 162/* 163 * Country names and abbreviations from ISO 3166 164 */ 165typedef struct { 166 char *name; /* Long name */ 167 char *abbrev; /* Abbreviation */ 168} country_name_t; 169country_name_t country_names[]; /* At end of this file */ 170 171struct variable variables[]; 172extern struct nvram_tuple router_defaults[]; 173 174enum { 175 NOTHING, 176 REBOOT, 177 RESTART, 178}; 179 180const char * const apply_header = 181"<head>" 182"<title>Broadcom Home Gateway Reference Design: Apply</title>" 183"<meta http-equiv=\"Content-Type\" content=\"application/html; charset=utf-8\">" 184"<style type=\"text/css\">" 185"body { background: white; color: black; font-family: arial, sans-serif; font-size: 9pt }" 186".title { font-family: arial, sans-serif; font-size: 13pt; font-weight: bold }" 187".subtitle { font-family: arial, sans-serif; font-size: 11pt }" 188".label { color: #306498; font-family: arial, sans-serif; font-size: 7pt }" 189"</style>" 190"</head>" 191"<body>" 192"<p>" 193"<span class=\"title\">APPLY</span><br>" 194"<span class=\"subtitle\">This screen notifies you of any errors " 195"that were detected while changing the router's settings.</span>" 196"<form method=\"get\" action=\"apply.cgi\">" 197"<p>" 198; 199 200const char * const apply_footer = 201"<p>" 202"<input type=\"button\" name=\"action\" value=\"Continue\" OnClick=\"document.location.href='%s';\">" 203"</form>" 204"<p class=\"label\">©2001-2007 Broadcom Corporation. All rights reserved.</p>" 205"</body>" 206; 207 208int ret_code; 209static char posterr_msg[255]; 210static int action = NOTHING; 211 212#ifdef PLC 213static dict_hdl_t BcmPostArgs; 214#endif /* PLC */ 215 216#define ERR_MSG_SIZE sizeof(posterr_msg) 217#if defined(linux) 218 219#include <fcntl.h> 220#include <signal.h> 221#include <time.h> 222#include <sys/klog.h> 223#include <sys/wait.h> 224#include <sys/ioctl.h> 225#include <net/if.h> 226 227 228typedef u_int64_t u64; 229typedef u_int32_t u32; 230typedef u_int16_t u16; 231typedef u_int8_t u8; 232#include <linux/types.h> 233#include <linux/ethtool.h> 234#include <linux/sockios.h> 235#include <net/if_arp.h> 236#include <sys/utsname.h> 237 238#define sys_restart() kill(1, SIGHUP) 239/* revised to shut down the radio before reboot */ 240//#define sys_reboot() kill(1, SIGTERM) 241inline void sys_reboot(void) 242{ 243 eval("wl", "reboot"); 244 kill(1, SIGTERM); 245} 246 247#define sys_stats(url) eval("stats", (url)) 248 249#define SLEEP(X) sleep(X) 250#define USLEEP(X) usleep(X) 251 252#ifndef min 253#define min(a, b) (((a) < (b)) ? (a) : (b)) 254#endif 255 256#ifndef WEBS 257 258#define MIN_BUF_SIZE 4096 259 260static int 261ej_kernel_version(int eid, webs_t wp, int argc, char_t **argv) 262{ 263 struct utsname utsn; 264 int ret; 265 char buf[100]; 266 char *ptr, *end; 267 268 ret = uname(&utsn); 269 if (ret != 0) 270 return -1; 271 272 strncpy(buf, utsn.release, sizeof(buf)-1); 273 buf[sizeof(buf)-1] = 0; 274 275 ptr = strstr(buf, "."); 276 if (!ptr) 277 return -1; 278 279 ptr = ptr+1; 280 end = strstr(ptr, "."); 281 if (end) 282 *end='\0'; 283 284 if (memcmp(buf, "2.4", 3)) 285 websWrite(wp,"%s", buf); 286 287 return 0; 288} 289 290 291#if (defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__) || \ 292 defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__)) 293char *linux_mtd_table[]={LINUX_FIRST, LINUX_SECOND}; 294 295static char* get_linux_partition_to_update(int* next) 296{ 297 char *target_to_flash; 298 299 /* Second priority: If the LINUX_BOOT_SEQUENCE is not set, we suppose the 300 * the user wants to disable the dual boot, always return the first one 301 */ 302 char *the_image = nvram_get(IMAGE_BOOT); 303 FILE *fp; 304 305 *next=-1; 306 if(the_image != NULL) { 307 unsigned int current_image = atoi(the_image); 308 unsigned int next_image = -1; 309 310 if(current_image > 1) { 311 cprintf("Image more than 2 is not supported, use default!!\n"); 312 goto my_default; 313 } 314 next_image = 1 - current_image; 315 316 /* Test if the linux2 partition exists. User may turn on the IMAGE_BOOT at runtime 317 * On this time the linux2 is not created until next boot 318 */ 319 if ( (next_image == 1) && (fp = fopen("/proc/mtd", "r"))) { 320 char dev[PATH_MAX]; 321 322 while (fgets(dev, sizeof(dev), fp)) { 323 if (strstr(dev, LINUX_SECOND)) { 324 fclose(fp); 325 goto my_continue; 326 } 327 } 328 cprintf("The linux2 does not exists, use default!\n"); 329 fclose(fp); 330 goto my_default; 331 } 332my_continue: 333 target_to_flash = linux_mtd_table[next_image]; 334 cprintf("\nToggled Linux Partition, next image using: %s\n", target_to_flash); 335 *next= next_image; 336 return target_to_flash; 337 } else { 338 cprintf("%s is not set, use the linux as default\n", IMAGE_BOOT); 339 } 340my_default: 341 return LINUX_FIRST; 342} 343 344/* Upgrade from remote server or socket stream */ 345static int 346sys_upgrade(char *url, FILE *stream, int *total) 347{ 348 char upload_fifo[] = "/tmp/uploadXXXXXX"; 349 FILE *fifo = NULL; 350 //write_argv[2] must be assigned a valid long-lived mtd partition 351 char *write_argv[] = { "write", upload_fifo, NULL, NULL }; 352 pid_t pid; 353 char *buf = NULL; 354 int count, ret = 0; 355 long flags = -1; 356 char *target_partition; 357 int the_next=-1; 358 359 assert(stream); 360 assert(total); 361 362 //Assign the target parition first!! 363 target_partition = write_argv[2] = get_linux_partition_to_update((int*) &the_next); 364 365 if(target_partition == NULL) { 366 cprintf("!!!! target_partition is NULL\n"); 367 goto err; 368 } 369 370 if (url) 371 return eval("write", url, target_partition); 372 373 /* Feed write from a temporary FIFO */ 374 if (!mktemp(upload_fifo) || 375 mkfifo(upload_fifo, S_IRWXU) < 0|| 376 (ret = _eval(write_argv, NULL, 0, &pid)) || 377 !(fifo = fopen(upload_fifo, "w"))) { 378 if (!ret) 379 ret = errno; 380 goto err; 381 } 382 383 /* Set nonblock on the socket so we can timeout */ 384 if ((flags = fcntl(fileno(stream), F_GETFL)) < 0 || 385 fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) { 386 ret = errno; 387 goto err; 388 } 389 390 /* 391 * The buffer must be at least as big as what the stream file is 392 * using so that it can read all the data that has been buffered 393 * in the stream file. Otherwise it would be out of sync with fn 394 * select specially at the end of the data stream in which case 395 * the select tells there is no more data available but there in 396 * fact is data buffered in the stream file's buffer. Since no 397 * one has changed the default stream file's buffer size, let's 398 * use the constant BUFSIZ until someone changes it. 399 * The code should be as follows 400 * if (size < MIN_BUF_SIZE) 401 * size = MIN_BUF_SIZE; 402 */ 403 404 if ((buf = malloc(BUFSIZ)) == NULL) { 405 ret = ENOMEM; 406 goto err; 407 } 408 409 /* Pipe the rest to the FIFO */ 410 cprintf("Upgrading.\n"); 411 while (total && *total) { 412 if (waitfor(fileno(stream), 5) <= 0) 413 break; 414 count = safe_fread(buf, 1, BUFSIZ, stream); 415 if (!count && (ferror(stream) || feof(stream))) 416 break; 417 *total -= count; 418 safe_fwrite(buf, 1, count, fifo); 419 cprintf("."); 420 } 421 fclose(fifo); 422 fifo = NULL; 423 424 /* Wait for write to terminate */ 425 waitpid(pid, &ret, 0); 426 cprintf("done\n"); 427 428 /* Reset nonblock on the socket */ 429 if (fcntl(fileno(stream), F_SETFL, flags) < 0) { 430 ret = errno; 431 goto err; 432 } 433 434 /* Only toggle would set the_next to 0 or 1 */ 435 if (!ret && (the_next == 0 || the_next == 1)) { 436 char temp[30]; 437 sprintf(temp, "%d", the_next); 438 nvram_set(IMAGE_BOOT, temp); 439 nvram_commit(); 440 cprintf("Set %s to %d\n", IMAGE_BOOT, the_next); 441 } 442 443 err: 444 if (buf) 445 free(buf); 446 if (fifo) 447 fclose(fifo); 448 unlink(upload_fifo); 449 return ret; 450} 451#else //__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ 452 453/* Upgrade from remote server or socket stream */ 454static int 455sys_upgrade(char *url, FILE *stream, int *total) 456{ 457 char upload_fifo[] = "/tmp/uploadXXXXXX"; 458 FILE *fifo = NULL; 459 char *write_argv[] = { "write", upload_fifo, "linux", NULL }; 460 pid_t pid; 461 char *buf = NULL; 462 int count, ret = 0; 463 long flags = -1; 464 char *cmd = "write"; 465 char *boot_partition = "boot"; 466 char *target_partition = "linux"; 467 468 /* Keep compiler happy */ 469 (void) boot_partition; 470 471 assert(stream); 472 assert(total); 473 474 475 if (url) 476 return eval(cmd, url, target_partition); 477 478 /* Feed write from a temporary FIFO */ 479 if (!mktemp(upload_fifo) || 480 mkfifo(upload_fifo, S_IRWXU) < 0|| 481 (ret = _eval(write_argv, NULL, 0, &pid)) || 482 !(fifo = fopen(upload_fifo, "w"))) { 483 if (!ret) 484 ret = errno; 485 goto err; 486 } 487 488 /* Set nonblock on the socket so we can timeout */ 489 if ((flags = fcntl(fileno(stream), F_GETFL)) < 0 || 490 fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) { 491 ret = errno; 492 goto err; 493 } 494 495 /* 496 * The buffer must be at least as big as what the stream file is 497 * using so that it can read all the data that has been buffered 498 * in the stream file. Otherwise it would be out of sync with fn 499 * select specially at the end of the data stream in which case 500 * the select tells there is no more data available but there in 501 * fact is data buffered in the stream file's buffer. Since no 502 * one has changed the default stream file's buffer size, let's 503 * use the constant BUFSIZ until someone changes it. 504 * 505 * if (size < MIN_BUF_SIZE) 506 * size = MIN_BUF_SIZE; 507 */ 508 509 if ((buf = malloc(BUFSIZ)) == NULL) { 510 ret = ENOMEM; 511 goto err; 512 } 513 514 /* Pipe the rest to the FIFO */ 515 cprintf("Upgrading.\n"); 516 while (total && *total) { 517 if (waitfor(fileno(stream), 5) <= 0) 518 break; 519 count = safe_fread(buf, 1, BUFSIZ, stream); 520 if (!count && (ferror(stream) || feof(stream))) 521 break; 522 *total -= count; 523 safe_fwrite(buf, 1, count, fifo); 524 cprintf("."); 525 } 526 fclose(fifo); 527 fifo = NULL; 528 529 /* Wait for write to terminate */ 530 waitpid(pid, &ret, 0); 531 cprintf("done\n"); 532 533 /* Reset nonblock on the socket */ 534 if (fcntl(fileno(stream), F_SETFL, flags) < 0) { 535 ret = errno; 536 goto err; 537 } 538 539 err: 540 if (buf) 541 free(buf); 542 if (fifo) 543 fclose(fifo); 544 unlink(upload_fifo); 545 return ret; 546} 547#endif //__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ 548 549#endif /* WEBS */ 550 551/* Dump firewall log */ 552static int 553ej_dumplog(int eid, webs_t wp, int argc, char_t **argv) 554{ 555 char buf[4096], *line, *next, *s; 556 int len, ret = 0; 557 558 time_t tm; 559 char *verdict, *src, *dst, *proto, *spt, *dpt; 560 561 if (klogctl(3, buf, 4096) < 0) { 562 websError(wp, 400, "Insufficient memory\n"); 563 return -1; 564 } 565 566 for (next = buf; (line = strsep(&next, "\n"));) { 567 if (!strncmp(line, "<4>DROP", 7)) 568 verdict = "denied"; 569 else if (!strncmp(line, "<4>ACCEPT", 9)) 570 verdict = "accepted"; 571 else 572 continue; 573 574 /* Parse into tokens */ 575 s = line; 576 len = strlen(s); 577 while (strsep(&s, " ")); 578 579 /* Initialize token values */ 580 time(&tm); 581 src = dst = proto = spt = dpt = "n/a"; 582 583 /* Set token values */ 584 for (s = line; s < &line[len] && *s; s += strlen(s) + 1) { 585 if (!strncmp(s, "TIME=", 5)) 586 tm = strtoul(&s[5], NULL, 10); 587 else if (!strncmp(s, "SRC=", 4)) 588 src = &s[4]; 589 else if (!strncmp(s, "DST=", 4)) 590 dst = &s[4]; 591 else if (!strncmp(s, "PROTO=", 6)) 592 proto = &s[6]; 593 else if (!strncmp(s, "SPT=", 4)) 594 spt = &s[4]; 595 else if (!strncmp(s, "DPT=", 4)) 596 dpt = &s[4]; 597 } 598 599 ret += websWrite(wp, "%s %s connection %s to %s:%s from %s:%s\n", 600 rfctime(&tm), proto, verdict, dst, dpt, src, spt); 601 ret += websWrite(wp, "<br>"); 602 } 603 604 return ret; 605} 606 607static int 608ej_syslog(int eid, webs_t wp, int argc, char_t **argv) 609{ 610 FILE *fp; 611 char buf[256] = "/sbin/logread > "; 612 char tmp[] = "/tmp/log.XXXXXX"; 613 int ret; 614 615 if (!nvram_match("log_ram_enable", "1")) { 616 websError(wp, 400, "\"Syslog in RAM\" is not enabled.\n"); 617 return (-1); 618 } 619 620 mktemp(tmp); 621 strcat(buf, tmp); 622 system(buf); 623 624 fp = fopen(tmp, "r"); 625 626 unlink(tmp); 627 628 if (fp == NULL) { 629 websError(wp, 400, "logread error\n"); 630 return (-1); 631 } 632 633 websWrite(wp, "<pre>"); 634 635 ret = 0; 636 while(fgets(buf, sizeof(buf), fp)) 637 ret += websWrite(wp, buf); 638 639 ret += websWrite(wp, "</pre>"); 640 641 fclose(fp); 642 643 return (ret); 644} 645 646struct lease_t { 647 unsigned char chaddr[16]; 648 u_int32_t yiaddr; 649 u_int32_t expires; 650 char hostname[64]; 651}; 652 653/* Dump leases in <tr><td>hostname</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 654static int 655ej_lan_leases(int eid, webs_t wp, int argc, char_t **argv) 656{ 657 FILE *fp = NULL; 658 struct lease_t lease; 659 int i; 660 int index,num_interfaces=0; 661 char buf[128]; 662 struct in_addr addr; 663 unsigned long expires = 0; 664 char sigusr1[] = "-XX"; 665 int ret = 0; 666 667 /* Write out leases file */ 668 sprintf(sigusr1, "-%d", SIGUSR1); 669 eval("killall", sigusr1, "udhcpd"); 670 671 /* Count the number of lan and guest interfaces */ 672 673 if (nvram_get("lan_ifname")) 674 num_interfaces++; 675 676 if (nvram_get("lan1_ifname")) 677 num_interfaces++; 678 679 for (index =0; index < num_interfaces; index++){ 680 snprintf(buf,sizeof(buf),"/tmp/udhcpd%d.leases",index); 681 682 if (!(fp = fopen(buf, "r"))) 683 continue; 684 685 while (fread(&lease, sizeof(lease), 1, fp)) { 686 /* Do not display reserved leases */ 687 if (ETHER_ISNULLADDR(lease.chaddr)) 688 continue; 689 lease.hostname[sizeof(lease.hostname) - 1] = '\0'; 690 ret += websWrite(wp, "<tr><td>%s</td><td>", lease.hostname); 691 for (i = 0; i < 6; i++) { 692 ret += websWrite(wp, "%02X", lease.chaddr[i]); 693 if (i != 5) ret += websWrite(wp, ":"); 694 } 695 addr.s_addr = lease.yiaddr; 696 ret += websWrite(wp, "</td><td>%s</td><td>", inet_ntoa(addr)); 697 expires = ntohl(lease.expires); 698 if (!expires) 699 ret += websWrite(wp, "Expired"); 700 else 701 ret += websWrite(wp, "%s", reltime(expires)); 702 if(index) 703 ret += websWrite(wp, "</td><td>Guest</td><td>"); 704 else 705 ret += websWrite(wp, "</td><td>Internal</td><td>"); 706 ret += websWrite(wp, "</td></tr>"); 707 } 708 709 fclose(fp); 710 } 711 712 return ret; 713} 714 715/* Renew lease */ 716static int 717sys_renew(void) 718{ 719 int unit; 720 char tmp[NVRAM_BUFSIZE]; 721 char *str = NULL; 722 int pid; 723 724 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 725 unit = 0; 726 727 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 728 if ((str = file2str(tmp))) { 729 pid = atoi(str); 730 free(str); 731 return kill(pid, SIGUSR1); 732 } 733 734 return -1; 735} 736 737/* Release lease */ 738static int 739sys_release(void) 740{ 741 int unit; 742 char tmp[NVRAM_BUFSIZE]; 743 char *str= NULL; 744 int pid; 745 746 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 747 unit = 0; 748 749 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 750 if ((str = file2str(tmp))) { 751 pid = atoi(str); 752 free(str); 753 return kill(pid, SIGUSR2); 754 } 755 756 return -1; 757} 758 759#ifdef __CONFIG_NAT__ 760#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr) 761 762/* Return WAN link state */ 763static int 764ej_wan_link(int eid, webs_t wp, int argc, char_t **argv) 765{ 766 char *wan_ifname; 767 int s; 768 struct ifreq ifr; 769 struct ethtool_cmd ecmd; 770 FILE *fp= NULL; 771 int unit; 772 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 773 774 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 775 unit = 0; 776 WAN_PREFIX(unit, prefix); 777 778 /* non-exist and disabled */ 779 if (nvram_match(strcat_r(prefix, "proto", tmp), "") || 780 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) { 781 return websWrite(wp, "N/A"); 782 } 783 /* PPPoE connection status */ 784 else if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { 785 wan_ifname = nvram_safe_get(strcat_r(prefix, "pppoe_ifname", tmp)); 786 if ((fp = fopen(strcat_r("/tmp/ppp/link.", wan_ifname, tmp), "r"))) { 787 fclose(fp); 788 return websWrite(wp, "Connected"); 789 } else 790 return websWrite(wp, "Disconnected"); 791 } 792 /* Get real interface name */ 793 else 794 wan_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 795 796 /* Open socket to kernel */ 797 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 798 return websWrite(wp, "N/A"); 799 800 /* Check for hardware link */ 801 strncpy(ifr.ifr_name, wan_ifname, sizeof(ifr.ifr_name) - 1); 802 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 803 804 ifr.ifr_data = (void *) &ecmd; 805 ecmd.cmd = ETHTOOL_GSET; 806 if (ioctl(s, SIOCETHTOOL, &ifr) < 0) { 807 close(s); 808 return websWrite(wp, "Unknown"); 809 } 810 if (!ecmd.speed) { 811 close(s); 812 return websWrite(wp, "Disconnected"); 813 } 814 815 /* Check for valid IP address */ 816 strncpy(ifr.ifr_name, wan_ifname, sizeof(ifr.ifr_name) - 1); 817 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 818 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { 819 close(s); 820 return websWrite(wp, "Connecting"); 821 } 822 823 /* Otherwise we are probably configured */ 824 close(s); 825 return websWrite(wp, "Connected"); 826} 827 828/* Display IP Address lease */ 829static int 830ej_wan_lease(int eid, webs_t wp, int argc, char_t **argv) 831{ 832 unsigned long expires = 0; 833 int ret = 0; 834 int unit; 835 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 836 837 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 838 unit = 0; 839 WAN_PREFIX(unit, prefix); 840 841 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 842 char *str; 843 time_t now; 844 845 snprintf(tmp, sizeof(tmp), "/tmp/udhcpc%d.expires", unit); 846 if ((str = file2str(tmp))) { 847 expires = atoi(str); 848 free(str); 849 } 850 time(&now); 851 if (expires <= now) 852 ret += websWrite(wp, "Expired"); 853 else 854 ret += websWrite(wp, "%s", reltime(expires - now)); 855 } else 856 ret += websWrite(wp, "N/A"); 857 858 return ret; 859} 860#endif /* __CONFIG_NAT__ */ 861 862/* Report sys up time */ 863static int 864ej_sysuptime(int eid, webs_t wp, int argc, char_t **argv) 865{ 866 char *str = file2str("/proc/uptime"); 867 if (str) { 868 unsigned int up = atoi(str); 869 free(str); 870 return websWrite(wp, reltime(up)); 871 } 872 return websWrite(wp, "N/A"); 873} 874 875#ifdef __CONFIG_NAT__ 876/* Return a list of wan interfaces (eth0/eth1/eth2/eth3) */ 877static int 878ej_wan_iflist(int eid, webs_t wp, int argc, char_t **argv) 879{ 880 char name[IFNAMSIZ], *next; 881 int ret = 0; 882 int unit; 883 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 884 char ea[64]; 885 int s; 886 struct ifreq ifr; 887 888 /* current unit # */ 889 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 890 unit = 0; 891 WAN_PREFIX(unit, prefix); 892 893 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 894 return errno; 895 896 /* build wan interface name list */ 897 foreach(name, nvram_safe_get("wan_ifnames"), next) { 898 strncpy(ifr.ifr_name, name, IFNAMSIZ); 899 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 900 continue; 901 ret += websWrite(wp, "<option value=\"%s\" %s>%s (%s)</option>", name, 902 nvram_match(strcat_r(prefix, "ifname", tmp), name) ? "selected" : "", 903 name, ether_etoa((unsigned char *)ifr.ifr_hwaddr.sa_data, ea)); 904 } 905 906 close(s); 907 908 return ret; 909} 910#endif /* __CONFIG_NAT__ */ 911 912 913#elif defined(__NetBSD__) 914 915#include <fcntl.h> 916#include <signal.h> 917#include <time.h> 918#include <sys/wait.h> 919#include <sys/ioctl.h> 920#include <sys/sysctl.h> 921#include <net/if.h> 922#include <proto/wpa.h> 923 924typedef u_int64_t u64; 925typedef u_int32_t u32; 926typedef u_int16_t u16; 927typedef u_int8_t u8; 928#include <sys/sockio.h> 929#include <net/if_arp.h> 930 931#define sys_restart() kill(1, SIGHUP) 932#define sys_reboot() kill(1, SIGTERM) 933#define sys_stats(url) eval("stats", (url)) 934 935#define SLEEP(X) sleep(X) 936#define USLEEP(X) usleep(X) 937 938void netbsd_random(uint8 *random, int len) 939{ 940 int tlen = len; 941 while (tlen--) { 942 *random = (uint8)rand(); 943 *random++; 944 } 945 return; 946} 947 948void RAND_bytes(unsigned char *buf, int num) 949{ 950 netbsd_random(buf, num); 951} 952 953#ifndef WEBS 954 955#define MIN_BUF_SIZE 4096 956 957/* Upgrade from remote server or socket stream */ 958static int 959sys_upgrade(char *url, FILE *stream, int *total) 960{ 961 char upload_fifo[] = "/tmp/uploadXXXXXX"; 962 FILE *fifo = NULL; 963 char *write_argv[] = { "write", upload_fifo, "linux", NULL }; 964 pid_t pid; 965 char *buf = NULL; 966 int count, ret = 0; 967 long flags = -1; 968 969 assert(stream); 970 assert(total); 971 972 if (url) 973 return eval("write", url, "linux"); 974 975 /* Feed write from a temporary FIFO */ 976 if (!mktemp(upload_fifo) || 977 mkfifo(upload_fifo, S_IRWXU) < 0|| 978 (ret = _eval(write_argv, NULL, 0, &pid)) || 979 !(fifo = fopen(upload_fifo, "w"))) { 980 if (!ret) 981 ret = errno; 982 goto err; 983 } 984 985 /* Set nonblock on the socket so we can timeout */ 986 if ((flags = fcntl(fileno(stream), F_GETFL)) < 0 || 987 fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) { 988 ret = errno; 989 goto err; 990 } 991 992 /* 993 * The buffer must be at least as big as what the stream file is 994 * using so that it can read all the data that has been buffered 995 * in the stream file. Otherwise it would be out of sync with fn 996 * select specially at the end of the data stream in which case 997 * the select tells there is no more data available but there in 998 * fact is data buffered in the stream file's buffer. Since no 999 * one has changed the default stream file's buffer size, let's 1000 * use the constant BUFSIZ until someone changes it. 1001 * The code should be as follows 1002 * if (size < MIN_BUF_SIZE) 1003 * size = MIN_BUF_SIZE; 1004 */ 1005 if ((buf = malloc(BUFSIZ)) == NULL) { 1006 ret = ENOMEM; 1007 goto err; 1008 } 1009 1010 /* Pipe the rest to the FIFO */ 1011 cprintf("Upgrading.\n"); 1012 while (total && *total) { 1013 if (waitfor(fileno(stream), 5) <= 0) 1014 break; 1015 count = safe_fread(buf, 1, BUFSIZ, stream); 1016 if (!count && (ferror(stream) || feof(stream))) 1017 break; 1018 *total -= count; 1019 safe_fwrite(buf, 1, count, fifo); 1020 cprintf("."); 1021 } 1022 fclose(fifo); 1023 fifo = NULL; 1024 1025 /* Wait for write to terminate */ 1026 waitpid(pid, &ret, 0); 1027 cprintf("done\n"); 1028 1029 /* Reset nonblock on the socket */ 1030 if (fcntl(fileno(stream), F_SETFL, flags) < 0) { 1031 ret = errno; 1032 goto err; 1033 } 1034 1035 err: 1036 if (buf) 1037 free(buf); 1038 if (fifo) 1039 fclose(fifo); 1040 unlink(upload_fifo); 1041 return ret; 1042} 1043 1044#endif /* WEBS */ 1045 1046/* Dump firewall log */ 1047static int 1048ej_dumplog(int eid, webs_t wp, int argc, char_t **argv) 1049{ 1050 return 0; 1051} 1052 1053static int 1054ej_syslog(int eid, webs_t wp, int argc, char_t **argv) 1055{ 1056 1057 1058 return (0); 1059} 1060 1061 1062/* Dump leases in <tr><td>hostname</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 1063static int 1064ej_lan_leases(int eid, webs_t wp, int argc, char_t **argv) 1065{ 1066 FILE *fp; 1067 char tmp[100]; 1068 char word[100]; 1069 char line[100]; 1070 int index,num_interfaces=0; 1071 char *cp1, *cp2; 1072 unsigned long expires = 0; 1073 int ret = 0; 1074 time_t tm; 1075 1076 /* Count the number of lan and guest interfaces */ 1077 if (nvram_get("lan_ifname")) 1078 num_interfaces++; 1079 1080 if (nvram_get("lan1_ifname")) 1081 num_interfaces++; 1082 1083 for (index =0; index < num_interfaces; index++){ 1084 snprintf(word, sizeof(word),"/etc/dhcpd%d.leases",index); 1085 1086 if (!(fp = fopen(word, "r"))) 1087 continue; 1088 1089 while (fgets(line, sizeof(line), fp)) { 1090 /* parse lease information */ 1091 cp1 = line; 1092 for (cp1 = line, cp2 = cp1; *cp2 && *cp2 != ';'; ++cp2) 1093 ; 1094 if (!*cp2) 1095 continue; 1096 *cp2 = '\0'; 1097 ret += websWrite(wp, "<tr><td>%s</td><td>", cp1); 1098 1099 /* hardware address */ 1100 for (cp1 = cp2+1, cp2 = cp1; *cp2 && *cp2 != ';'; ++cp2) 1101 ; 1102 if (!*cp2) 1103 continue; 1104 *cp2 = '\0'; 1105 ret += websWrite(wp, "%s", cp1); 1106 /* IP */ 1107 for (cp1 = cp2+1, cp2 = cp1; *cp2 && *cp2 != ';'; ++cp2) 1108 ; 1109 if (!*cp2) 1110 continue; 1111 *cp2 = '\0'; 1112 ret += websWrite(wp, "</td><td>%s</td><td>", cp1); 1113 1114 /* expires */ 1115 cp1 = cp2+1; 1116 if (!strcmp(cp1, "never")) 1117 ret += websWrite(wp, "Never"); 1118 else { 1119 time(&tm); 1120 expires = atoi(cp1); 1121 expires -= time(&tm); 1122 if (!expires) 1123 ret += websWrite(wp, "Expired"); 1124 else 1125 ret += websWrite(wp, "%s", reltime(expires)); 1126 } 1127 if(index) 1128 ret += websWrite(wp, "</td><td>Guest</td><td>"); 1129 else 1130 ret += websWrite(wp, "</td><td>Internal</td><td>"); 1131 ret += websWrite(wp, "</td></tr>"); 1132 } 1133 1134 fclose(fp); 1135 } 1136 1137 return ret; 1138} 1139 1140/* Renew lease */ 1141static int 1142sys_renew(void) 1143{ 1144 1145 return -1; 1146} 1147 1148/* Release lease */ 1149static int 1150sys_release(void) 1151{ 1152 1153 1154 return -1; 1155} 1156 1157#ifdef __CONFIG_NAT__ 1158#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr) 1159 1160/* Return WAN link state */ 1161static int 1162ej_wan_link(int eid, webs_t wp, int argc, char_t **argv) 1163{ 1164 1165 return 0; 1166} 1167 1168/* Display IP Address lease */ 1169static int 1170ej_wan_lease(int eid, webs_t wp, int argc, char_t **argv) 1171{ 1172 1173 1174 return 0; 1175} 1176#endif /* __CONFIG_NAT__ */ 1177 1178/* Report sys up time */ 1179static int 1180ej_sysuptime(int eid, webs_t wp, int argc, char_t **argv) 1181{ 1182 int mib[2]; 1183 size_t size; 1184 time_t uptime; 1185 struct timeval boottime; 1186 time_t now; 1187 1188 (void)time(&now); 1189 mib[0] = CTL_KERN; 1190 mib[1] = KERN_BOOTTIME; 1191 size = sizeof(boottime); 1192 if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && 1193 boottime.tv_sec != 0) { 1194 uptime = now - boottime.tv_sec; 1195 return websWrite(wp, reltime(uptime)); 1196 } 1197 return websWrite(wp, "N/A"); 1198} 1199 1200#ifdef __CONFIG_NAT__ 1201/* Return a list of wan interfaces (eth0/eth1/eth2/eth3) */ 1202static int 1203ej_wan_iflist(int eid, webs_t wp, int argc, char_t **argv) 1204{ 1205 char name[IFNAMSIZ], *next; 1206 int ret = 0; 1207 int unit; 1208 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1209 char ea[64]; 1210 int s; 1211 struct ifreq ifr; 1212 1213 /* current unit # */ 1214 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1215 unit = 0; 1216 WAN_PREFIX(unit, prefix); 1217 1218 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 1219 return errno; 1220 1221 /* build wan interface name list */ 1222 foreach(name, nvram_safe_get("wan_ifnames"), next) { 1223 strncpy(ifr.ifr_name, name, IFNAMSIZ); 1224 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 1225 continue; 1226 ret += websWrite(wp, "<option value=\"%s\" %s>%s (%s)</option>", name, 1227 nvram_match(strcat_r(prefix, "ifname", tmp), name) ? "selected" : "", 1228 name, ether_etoa((unsigned char *)ifr.ifr_addr.sa_data, ea)); 1229 } 1230 1231 close(s); 1232 1233 return ret; 1234} 1235#endif /* __CONFIG_NAT__ */ 1236 1237 1238static int 1239ej_kernel_version(int eid, webs_t wp, int argc, char_t **argv) 1240{ 1241 return 0; 1242} 1243 1244#elif defined(__ECOS) 1245 1246#include <cyg/kernel/kapi.h> 1247#include <cyg/infra/cyg_type.h> 1248#include <cyg/infra/diag.h> 1249#include <typedefs.h> 1250#include <sys/ioctl.h> 1251#include <dhcpc.h> 1252#include <dhcpd.h> 1253 1254#define cprintf(fmt, args...) fprintf(stderr, fmt , ## args) 1255extern void sys_restart(void); 1256extern void sys_reboot(void); 1257 1258#define sys_stats(server) (0) 1259extern int sys_upgrade(char *url, FILE *stream, int *total); 1260extern int wl_ioctl(char *name, int request, void *buf, int len); 1261 1262extern void udelay(int delay); 1263#define SLEEP(n) cyg_thread_delay(n * 100) 1264#define USLEEP(X) udelay(X) 1265 1266static int 1267ej_kernel_version(int eid, webs_t wp, int argc, char_t **argv) 1268{ 1269 websWrite(wp,"eCos 3.0/"); 1270 return 0; 1271} 1272 1273static int 1274sys_renew(void) 1275{ 1276 char *wan_ifname; 1277 int unit; 1278 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1279 1280 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1281 unit = 0; 1282 WAN_PREFIX(unit, prefix); 1283 1284 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 1285 wan_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1286 dhcpc_renew(wan_ifname); 1287 } 1288 1289 return 0; 1290} 1291 1292static int 1293sys_release(void) 1294{ 1295 char *wan_ifname; 1296 int unit; 1297 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1298 1299 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1300 unit = 0; 1301 WAN_PREFIX(unit, prefix); 1302 1303 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 1304 wan_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1305 dhcpc_release(wan_ifname); 1306 } 1307 1308 return 0; 1309} 1310 1311/* Dump leases in <tr><td>hostname</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 1312static int 1313ej_lan_leases(int eid, webs_t wp, int argc, char_t **argv) 1314{ 1315 int i; 1316 int index, num_interfaces = 0; 1317 int ret = 0; 1318 1319 char *ifname; 1320 struct lease_t *lease, *dump; 1321 int last; 1322 1323 /* Count the number of lan and guest interfaces */ 1324 if (nvram_get("lan_ifname")) 1325 num_interfaces++; 1326 1327 if (nvram_get("lan1_ifname")) 1328 num_interfaces++; 1329 1330 for (index = 0; index < num_interfaces; index++){ 1331 if (index == 0) 1332 ifname = nvram_get("lan_ifname"); 1333 else 1334 ifname = nvram_get("lan1_ifname"); 1335 if (!ifname) 1336 continue; 1337 1338 /* dump lease */ 1339 dump = lease = dhcpd_lease_dump(ifname); 1340 if (!dump) 1341 return 0; 1342 1343 /* Write HTML until last */ 1344 last = 0; 1345 while (last == 0) { 1346 /* Get the last flag for next time qualification */ 1347 last = lease->last; 1348 1349 if (lease->flag & RESERVED) { 1350 lease++; 1351 continue; 1352 } 1353 1354 ret += websWrite(wp, "<tr><td>%s</td><td>", lease->hostname); 1355 1356 for (i = 0; i < 6; i++) { 1357 ret += websWrite(wp, "%02X", lease->mac[i]); 1358 if (i != 5) ret += websWrite(wp, ":"); 1359 } 1360 1361 ret += websWrite(wp, "</td><td>%s</td><td>", inet_ntoa(lease->ipaddr)); 1362 1363 if (lease->expiry < time(0)) 1364 ret += websWrite(wp, "Expired"); 1365 else 1366 ret += websWrite(wp, "%s", 1367 reltime(lease->expiry-time(0))); 1368 1369 if (index) 1370 ret += websWrite(wp, "</td><td>Guest</td><td>"); 1371 else 1372 ret += websWrite(wp, "</td><td>Internal</td><td>"); 1373 ret += websWrite(wp, "</td></tr>"); 1374 1375 /* Advaince to next */ 1376 lease++; 1377 } 1378 1379 /* Free buffer */ 1380 free(dump); 1381 } 1382 1383 return ret; 1384} 1385 1386static int 1387ej_dumplog(int eid, webs_t wp, int argc, char_t **argv) 1388{ 1389 /* not implemented */ 1390 return 0; 1391} 1392 1393extern int syslog_open(); 1394extern int syslog_close(); 1395extern char *syslog_get(); 1396 1397static int 1398ej_syslog(int eid, webs_t wp, int argc, char_t **argv) 1399{ 1400 char *buf; 1401 int ret; 1402 1403 syslog_open(); 1404 1405 ret = 0; 1406 while((buf = syslog_get()) != NULL) { 1407 ret += websWrite(wp, "<pre>"); 1408 ret += websWrite(wp, buf); 1409 ret += websWrite(wp, "</pre>"); 1410 } 1411 1412 syslog_close(); 1413 1414 return (ret); 1415} 1416 1417#ifdef __CONFIG_NAT__ 1418static int 1419ej_wan_link(int eid, webs_t wp, int argc, char_t **argv) 1420{ 1421 char *val; 1422 1423 val = nvram_safe_get("wan_connect"); 1424 if (strcmp(val, "Connected")) 1425 websWrite(wp, "Connected"); 1426 else if (strcmp(val, "Connecting")) 1427 websWrite(wp, "Connecting"); 1428 else 1429 websWrite(wp, "Disconnected"); 1430 return 0; 1431} 1432 1433static int 1434ej_wan_lease(int eid, webs_t wp, int argc, char_t **argv) 1435{ 1436 int ret = 0; 1437 int unit; 1438 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1439 1440 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1441 unit = 0; 1442 WAN_PREFIX(unit, prefix); 1443 1444 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 1445 char *value; 1446 unsigned int expires; 1447 time_t now = time(0); 1448 1449 value = nvram_safe_get(strcat_r(prefix, "expiry", tmp)); 1450 expires = strtoul(value, NULL, 10); 1451 if (expires == 0) 1452 ret += websWrite(wp, "N/A"); 1453 else if (expires <= now) 1454 ret += websWrite(wp, "Expired"); 1455 else 1456 ret += websWrite(wp, "%s", reltime(expires - now)); 1457 } else 1458 ret += websWrite(wp, "N/A"); 1459 1460 return 0; 1461} 1462 1463static int 1464ej_sysuptime(int eid, webs_t wp, int argc, char_t **argv) 1465{ 1466 unsigned int up = (unsigned int)(cyg_current_time()/100); 1467 1468 return websWrite(wp, reltime(up)); 1469} 1470 1471/* Return a list of wan interfaces (eth0/eth1/eth2/eth3) */ 1472static int 1473ej_wan_iflist(int eid, webs_t wp, int argc, char_t **argv) 1474{ 1475 char name[IFNAMSIZ], *next; 1476 int ret = 0; 1477 int unit; 1478 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1479 char ea[64]; 1480 int s; 1481 struct ifreq ifr; 1482 1483 /* current unit # */ 1484 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1485 unit = 0; 1486 WAN_PREFIX(unit, prefix); 1487 1488 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 1489 return errno; 1490 1491 /* build wan interface name list */ 1492 foreach(name, nvram_safe_get("wan_ifnames"), next) { 1493 strncpy(ifr.ifr_name, name, IFNAMSIZ); 1494 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 1495 continue; 1496 ret += websWrite(wp, "<option value=\"%s\" %s>%s (%s)</option>", name, 1497 nvram_match(strcat_r(prefix, "ifname", tmp), name) ? "selected" : "", 1498 name, ether_etoa((unsigned char *)ifr.ifr_addr.sa_data, ea)); 1499 } 1500 1501 close(s); 1502 1503 return ret; 1504} 1505#endif /* __CONFIG_NAT__ */ 1506 1507 1508#endif /* __ECOS__ */ 1509 1510/* Common function */ 1511static int 1512wl_phytype_get(webs_t wp, int *phytype) 1513{ 1514 char *name =NULL; 1515 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1516 1517 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 1518 websError(wp, 400, "unit number variable doesn't exist\n"); 1519 return -1; 1520 } 1521 1522 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1523 1524 /* Get configured phy type */ 1525 wl_ioctl(name, WLC_GET_PHYTYPE, phytype, sizeof(int)); 1526 1527 return 0; 1528} 1529 1530static int 1531ej_lan_guest_iflist(int eid, webs_t wp, int argc, char_t **argv) 1532{ 1533 int ret = 0; 1534 char ifnames[255],name[IFNAMSIZ],os_name[IFNAMSIZ],*next=NULL; 1535 char buf[32],*config_num, *value=NULL; 1536 1537 if (ejArgs(argc, argv, "%s", &config_num) < 1) { 1538 websError(wp, 400, "Insufficient args\n"); 1539 return -1; 1540 } 1541 1542 /* Do some of the housekeeping here to remove any leftover invalid NVRAM vars 1543 prior to display */ 1544 1545 snprintf(ifnames, sizeof(ifnames), "%s", nvram_safe_get("unbridged_ifnames")); 1546 1547 snprintf(buf, sizeof(buf), "lan%s_ifname", config_num); 1548 1549 value = nvram_safe_get(buf); 1550 1551 1552 if (!*ifnames) 1553 { 1554 ret += websWrite(wp, "<option value=\"NONE\" selected >NONE</option>"); 1555 return ret; 1556 } 1557 1558 if (!remove_dups(ifnames,sizeof(ifnames))){ 1559 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 1560 return -1; 1561 } 1562 1563 foreach(name, ifnames, next) { 1564 1565 1566 if (nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0) 1567 continue; 1568 1569 ret += websWrite(wp, "<option value=\"%s\"%s>%s%s</option>", 1570 name, strcmp(name,value) ? "":" selected ", 1571 name, !wl_probe(os_name) ? " (Wireless)" : ""); 1572 } 1573 1574 ret += websWrite(wp, "<option value=\"NONE\"%s>NONE</option>",(*value) ? "" : " selected "); 1575 1576 return ret; 1577} 1578 1579 1580static int 1581ej_asp_list(int eid, webs_t wp, int argc, char_t **argv) 1582{ 1583 websWrite(wp, 1584 "<tr>\n" 1585 " <td><a href=\"index.asp\"><img border=\"0\" src=\"basic.gif\" alt=\"Basic\"></a></td>\n" 1586 " <td><a href=\"lan.asp\"><img border=\"0\" src=\"lan.gif\" alt=\"LAN\"></a></td>\n"); 1587#ifdef __CONFIG_NAT__ 1588 websWrite(wp, 1589 " <td><a href=\"wan.asp\"><img border=\"0\" src=\"wan.gif\" alt=\"WAN\"></a></td>\n"); 1590#endif 1591#ifndef __CONFIG_NETBOOT__ 1592 websWrite(wp, 1593 " <td><a href=\"status.asp\"><img border=\"0\" src=\"status.gif\" alt=\"Status\"></a></td>\n"); 1594#ifdef __CONFIG_NAT__ 1595 websWrite(wp, 1596 " <td><a href=\"filter.asp\"><img border=\"0\" src=\"filter.gif\" alt=\"Filters\"></a></td>\n" 1597 " <td><a href=\"forward.asp\"><img border=\"0\" src=\"forward.gif\" alt=\"Routing\"></a></td>\n"); 1598#endif 1599#endif /* !__CONFIG_NETBOOT__ */ 1600#ifdef BCMQOS 1601#if !defined(__CONFIG_TREND_IQOS__) && !defined(CONFIG_TREND_IQOS_ENABLED) 1602 websWrite(wp, 1603 " <td><a href=\"qos.asp\"><img border=\"0\" src=\"qos.gif\" alt=\"IQos\"></a></td>\n"); 1604#endif /* !defined (__CONFIG_TREND_IQOS__) && !defined (CONFIG_TREND_IQOS_ENABLED) */ 1605#endif 1606 websWrite(wp, 1607 " <td><a href=\"media.asp\"><img border=\"0\" src=\"media.gif\" alt=\"Media\"></a></td>\n"); 1608#ifdef PLC 1609 websWrite(wp, " <td><a href=\"plc.asp\"><img border=\"0\" src=\"plc.gif\" alt=\"PLC\"></a></td>\n"); 1610#endif 1611 1612#if defined(__CONFIG_SAMBA__) || defined(__CONFIG_DLNA_DMS__) 1613 websWrite(wp, 1614 " <td><a href=\"storage.asp\"><img border=\"0\" src=\"storage.gif\" alt=\"Storage\"></a></td>\n"); 1615#endif 1616 websWrite(wp, 1617 " <td><a href=\"radio.asp\"><img border=\"0\" src=\"radio.gif\" alt=\"Wlan I/F\"></a></td>\n" 1618 " <td><a href=\"ssid.asp\"><img border=\"0\" src=\"ssid.gif\" alt=\"xyz\"></a></td>\n"); 1619#ifdef __CONFIG_HSPOT__ 1620 websWrite(wp, 1621 " <td><a href=\"passpoint.asp\"><img border=\"0\" src=\"passpoint.gif\" alt=\"Passpoint\"></a></td>\n"); 1622#endif /* __CONFIG_HSPOT__ */ 1623 websWrite(wp, 1624 " <td><a href=\"security.asp\"><img border=\"0\" src=\"security.gif\" alt=\"Security\"></a></td>\n"); 1625#ifdef __CONFIG_WAPI_IAS__ 1626 websWrite(wp, 1627 " <td><a href=\"as.asp\"><img border=\"0\" src=\"as.gif\" alt=\"AS\"></a></td>\n"); 1628#endif /* __CONFIG_WAPI_IAS__ */ 1629#ifdef __CONFIG_WPS__ 1630 websWrite(wp, 1631 " <td><a href=\"wps.asp\"><img border=\"0\" src=\"wps.gif\" alt=\"wps\"></a></td>\n"); 1632#endif /* __CONFIG_WPS__ */ 1633#ifndef __CONFIG_NETBOOT__ 1634 websWrite(wp, 1635 " <td><a href=\"firmware.asp\"><img border=\"0\" src=\"firmware.gif\" alt=\"Firmware\"></a></td>\n"); 1636#else 1637 websWrite(wp, 1638 " <td><a href=\"netboot.asp\"><img border=\"0\" src=\"firmware.gif\" alt=\"Firmware\"></a></td>\n"); 1639#endif /* __CONFIG_NETBOOT */ 1640#if defined(__CONFIG_VISUALIZATION__) && defined(CONFIG_VISUALIZATION_ENABLED) 1641 websWrite(wp, 1642 " <td><a href=\"visindex.asp\"><img border=\"0\" src=\"visualization.gif\" alt=\"Visualization\"></a></td>\n"); 1643#endif /* (__CONFIG_VISUALIZATION__) && (CONFIG_VISUALIZATION_ENABLED) */ 1644#if defined(__CONFIG_TREND_IQOS__) && defined(CONFIG_TREND_IQOS_ENABLED) 1645 websWrite(wp, 1646 " <td><a href=\"iQoSNetworkSummary.asp\"><img border=\"0\" src=\"iqos.gif\" alt=\"iQoS\"></a></td>\n"); 1647#endif /* __CONFIG_TREND_IQOS__ && CONFIG_TREND_IQOS_ENABLED */ 1648 websWrite(wp, 1649 " <td width=\"100%%\"></td>\n" 1650 "</tr>\n"); 1651 return 0; 1652} 1653 1654static char * 1655rfctime(const time_t *timep) 1656{ 1657 static char s[201]; 1658 struct tm tm; 1659 1660#if defined(linux) || defined(__NetBSD__) 1661 setenv("TZ", nvram_safe_get("time_zone"), 1); 1662#endif 1663 memcpy(&tm, localtime(timep), sizeof(struct tm)); 1664 strftime(s, 200, "%a, %d %b %Y %H:%M:%S %z", &tm); 1665 return s; 1666} 1667 1668static char * 1669reltime(unsigned int seconds) 1670{ 1671 static char s[] = "XXXXX days, XX hours, XX minutes, XX seconds"; 1672 char *c = s; 1673 1674 if (seconds > 60*60*24) { 1675 c += sprintf(c, "%d days, ", seconds / (60*60*24)); 1676 seconds %= 60*60*24; 1677 } 1678 if (seconds > 60*60) { 1679 c += sprintf(c, "%d hours, ", seconds / (60*60)); 1680 seconds %= 60*60; 1681 } 1682 if (seconds > 60) { 1683 c += sprintf(c, "%d minutes, ", seconds / 60); 1684 seconds %= 60; 1685 } 1686 c += sprintf(c, "%d seconds", seconds); 1687 1688 return s; 1689} 1690 1691static char * 1692reltime_short(unsigned int seconds) 1693{ 1694 static char buf[16]; 1695 1696 sprintf(buf, "%02d:%02d:%02d", 1697 seconds / 3600, 1698 (seconds % 3600) / 60, 1699 seconds % 60); 1700 1701 return buf; 1702} 1703 1704 1705/* Report time in RFC-822 format */ 1706static int 1707ej_localtime(int eid, webs_t wp, int argc, char_t **argv) 1708{ 1709 time_t tm; 1710 1711 time(&tm); 1712 return websWrite(wp, rfctime(&tm)); 1713} 1714 1715static int 1716ej_wl_mode_list(int eid, webs_t wp, int argc, char_t **argv) 1717{ 1718 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1719 char wl_mode[]="wlXXXXXXXXXX_mode"; 1720 char *name=NULL, *next=NULL; 1721 int ap = 0, sta = 0, wet = 0, wds = 0, mac_spoof = 0, psta = 0, psr = 0; 1722 char cap[WLC_IOCTL_SMLEN]; 1723 char caps[WLC_IOCTL_MEDLEN]; 1724 int mode = 0; 1725 char *wl_bssid = NULL; 1726 1727 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))) 1728 mode=1; 1729 1730 if (!make_wl_prefix(prefix,sizeof(prefix), mode, NULL)){ 1731 websError(wp, 400, "unit number variable doesn't exist\n"); 1732 return -1; 1733 } 1734 1735 snprintf(wl_mode,sizeof(wl_mode),"%smode",prefix); 1736 1737 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1738 1739 if(mode) { 1740 /* VIF is being selected , show the mode as AccessPoint, even if 1741 * VIF is not configured yet */ 1742 websWrite(wp, "<option value=\"ap\" selected >Access Point</option>\n" ); 1743 } 1744 1745 1746 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 1747 return -1; 1748 1749 foreach(cap, caps, next) { 1750 if (!strcmp(cap, "ap")) 1751 ap = wds = 1; 1752 else if (!strcmp(cap, "sta")) 1753 sta = 1; 1754 else if (!strcmp(cap, "wet")) 1755 wet = 1; 1756 else if (!strcmp(cap, "mac_spoof")) 1757 mac_spoof = 1; 1758 else if (!strcmp(cap, "psta")) 1759 psta = 1; 1760 else if (!strcmp(cap, "psr")) 1761 psr = 1; 1762 } 1763 1764 if (ap) 1765 websWrite(wp, "<option value=\"ap\" %s>Access Point</option>\n", 1766 nvram_match(wl_mode, "ap" ) ? "selected" : ""); 1767 if (wds) 1768 websWrite(wp, "<option value=\"wds\" %s>Wireless Bridge</option>\n", 1769 nvram_match(wl_mode, "wds" ) ? "selected" : ""); 1770 if (wet) 1771 websWrite(wp, "<option value=\"wet\" %s>Wireless Ethernet</option>\n", 1772 nvram_match(wl_mode, "wet" ) ? "selected" : ""); 1773 if (mac_spoof) 1774 websWrite(wp, "<option value=\"mac_spoof\" %s>Wireless Ethernet MAC Spoof</option>\n", 1775 nvram_match(wl_mode, "mac_spoof" ) ? "selected" : ""); 1776 if (psta) 1777 websWrite(wp, "<option value=\"psta\" %s>Proxy STA</option>\n", 1778 nvram_match(wl_mode, "psta" ) ? "selected" : ""); 1779 if (psr) 1780 websWrite(wp, "<option value=\"psr\" %s>Proxy STA Repeater</option>\n", 1781 nvram_match(wl_mode, "psr" ) ? "selected" : ""); 1782 if (sta) 1783 websWrite(wp, "<option value=\"sta\" %s>Station</option>\n", 1784 nvram_match(wl_mode, "sta" ) ? "selected" : ""); 1785 return 0; 1786} 1787 1788static int 1789ej_wl_bw_cap_list(int eid, webs_t wp, int argc, char_t **argv) 1790{ 1791 int status = 0; 1792 char *name=NULL; 1793 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1794 int cur_phytype; 1795 1796 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 1797 websError(wp, 400, "unit number variable doesn't exist\n"); 1798 status = -1; 1799 goto exit; 1800 } 1801 1802 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1803 1804 /* Get configured phy type */ 1805 wl_ioctl(name, WLC_GET_PHYTYPE, &cur_phytype, sizeof(cur_phytype)); 1806 1807 websWrite(wp, "<option value=\"1\" %s>20 MHz</option>", 1808 nvram_match("wl_bw_cap", "1") ? "selected" : ""); 1809 websWrite(wp, "<option value=\"3\" %s>40 MHz</option>", 1810 nvram_match("wl_bw_cap", "3") ? "selected" : ""); 1811 1812 if (cur_phytype == WLC_PHY_TYPE_AC) { 1813 /* List 80 MHz bandwidth as well */ 1814 websWrite(wp, "<option value=\"7\" %s>80 MHz</option>", 1815 nvram_match("wl_bw_cap", "7") ? "selected" : ""); 1816 } 1817 1818exit: 1819 return status; 1820} 1821 1822static char * 1823translate_ssid(char *ssid) 1824{ 1825 static char ssid_html[32*5+1]; /* *5 => ÿ */ 1826 char *c = NULL, *pssid = ssid_html;; 1827 int len, size = sizeof(ssid_html); 1828 1829 /* Clear static ssid_html */ 1830 memset(ssid_html, 0, sizeof(ssid_html)); 1831 1832 for (c = ssid; *c; c++) { 1833 if (isprint((int) *c) && 1834 *c != '"' && *c != '&' && *c != '<' && *c != '>') 1835 len = snprintf(pssid, size, "%c", *c); 1836 else 1837 len = snprintf(pssid, size, "&#%d;", *c); 1838 1839 size -= len; 1840 pssid += len; 1841 } 1842 1843 return ssid_html; 1844} 1845 1846static int 1847ej_wl_bssid_list(int eid, webs_t wp, int argc, char_t **argv) 1848{ 1849 char vif[64]; 1850 char prefix[] = "wlXXXXXXXXXX_"; 1851 char *bssid = NULL; 1852 char *ssid = NULL; 1853 char i = 0; 1854 char *wl_bssid = NULL; 1855 char bssid_selected = 0; 1856 int mode = 0; 1857 char cap[WLC_IOCTL_SMLEN]; 1858 char caps[WLC_IOCTL_MEDLEN]; 1859 char *name = NULL; 1860 char *next = NULL; 1861 int max_no_vifs = 1; 1862 char *bss_enabled; 1863 1864 if (!make_wl_prefix(prefix, sizeof(prefix), mode, NULL)) { 1865 websError(wp, 400, "unit number variable doesn't exist\n"); 1866 return -1; 1867 } 1868 1869 snprintf(vif, sizeof(vif), "%sssid", prefix); 1870 ssid = nvram_safe_get(vif); 1871 snprintf(vif, sizeof(vif), "%shwaddr", prefix); 1872 bssid = nvram_get(vif); 1873 1874 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL))) 1875 bssid_selected = atoi(wl_bssid); 1876 snprintf(vif, sizeof(vif), "%sbss_enabled", prefix); 1877 bss_enabled = nvram_safe_get(vif); 1878 1879 /* show primary interface */ 1880 websWrite(wp, "<option value=%x %s > %s (%s %sabled) </option>\n", i, 1881 (bssid_selected == i) ? "selected" : "", bssid, translate_ssid(ssid), 1882 (bss_enabled[0] == '1') ? "en" : "dis"); 1883 1884 /* Get the no of VIFS to be dispalyed */ 1885 name = nvram_safe_get(strcat_r(prefix, "ifname",vif)); 1886 1887 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 1888 return -1; 1889 1890 foreach(cap, caps, next) { 1891 if (!strcmp(cap, "mbss16")) 1892 max_no_vifs = 16; 1893 else if (!strcmp(cap, "mbss8")) 1894 max_no_vifs = 8; 1895 else if (!strcmp(cap, "mbss4")) 1896 max_no_vifs = 4; 1897 } 1898 1899 if ((!atoi (nvram_safe_get("ure_disable"))) || 1900 (!strcmp ("psr", nvram_safe_get(strcat_r(prefix, "mode", vif))))) 1901 max_no_vifs = 2; 1902 1903 /* show all virtual interface */ 1904 for (i = 1; i < max_no_vifs ; i++) { 1905 snprintf(vif, sizeof(vif), "%c%c%c.%d_ssid", prefix[0], prefix[1], prefix[2], i); 1906 ssid = nvram_safe_get(vif); 1907 snprintf(vif, sizeof(vif), "%c%c%c.%d_hwaddr", prefix[0], prefix[1], prefix[2], i); 1908 bssid = nvram_get(vif); 1909 if (!bssid){ 1910 bssid = "virtual_bssid"; 1911 } 1912 snprintf(vif, sizeof(vif), "%c%c%c.%d_bss_enabled", prefix[0], prefix[1], 1913 prefix[2], i); 1914 bss_enabled = nvram_safe_get(vif); 1915 websWrite(wp, "<option value=%d %s > %s (%s %sabled)</option>\n", i, 1916 (bssid_selected == i) ? "selected" : "", bssid, translate_ssid(ssid), 1917 (bss_enabled[0] == '1') ? "en" : "dis"); 1918 } 1919 return 0; 1920 1921} 1922 1923static int 1924ej_wl_inlist(int eid, webs_t wp, int argc, char_t **argv) 1925{ 1926 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1927 char *name=NULL, *next=NULL; 1928 char cap[WLC_IOCTL_SMLEN]; 1929 char caps[WLC_IOCTL_MEDLEN]; 1930 char *var=NULL, *item=NULL; 1931 1932 if (ejArgs(argc, argv, "%s %s", &var, &item) < 2) { 1933 websError(wp, 400, "Insufficient args\n"); 1934 return -1; 1935 } 1936 1937 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 1938 websError(wp, 400, "unit number variable doesn't exist\n"); 1939 return -1; 1940 } 1941 1942 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1943 1944 if (wl_iovar_get(name, var, (void *)caps, sizeof(caps))) 1945 return -1; 1946 1947 foreach(cap, caps, next) { 1948 if (!strcmp(cap, item)) 1949 return websWrite(wp, "1"); 1950 } 1951 1952 return websWrite(wp, "0"); 1953} 1954 1955static int 1956ej_wl_wds_status(int eid, webs_t wp, int argc, char_t **argv) 1957{ 1958 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1959 char *macs=NULL, *next=NULL, *name=NULL; 1960 char mac[100]; 1961 int i=0, len=0; 1962 sta_info_t *sta=NULL; 1963 char buf[sizeof(sta_info_t)]; 1964 1965 if (ejArgs(argc, argv, "%d", &i) < 1) { 1966 websError(wp, 400, "Insufficient args\n"); 1967 return -1; 1968 } 1969 1970 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 1971 websError(wp, 400, "Insufficient args\n"); 1972 return -1; 1973 } 1974 1975 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1976 macs = nvram_safe_get(strcat_r(prefix, "wds", tmp)); 1977 1978 foreach(mac, macs, next) { 1979 if (i-- == 0) { 1980 len = sprintf(buf, "sta_info"); 1981 ether_atoe(mac, (unsigned char *)&buf[len + 1]); 1982 if (atoi(nvram_safe_get(strcat_r(prefix, "wds_timeout", tmp))) && 1983 !wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))) { 1984 sta = (sta_info_t *)buf; 1985 return websWrite(wp, "%s", (sta->flags & WL_STA_WDS_LINKUP) ? "up" : "down"); 1986 } 1987 else 1988 return websWrite(wp, "%s", "unknown"); 1989 } 1990 } 1991 1992 return 0; 1993} 1994 1995static int 1996ej_ses_button_display(int eid, webs_t wp, int argc, char_t **argv) 1997{ 1998 1999 return 1; 2000} 2001 2002 2003static int 2004ej_ses_cl_button_display(int eid, webs_t wp, int argc, char_t **argv) 2005{ 2006 2007 return 1; 2008} 2009 2010static int 2011ej_wl_auth_display(int eid, webs_t wp, int argc, char_t **argv) 2012{ 2013 if (!nvram_match("wl_mode", "ap")) 2014 websWrite(wp, "<option value=\"2\" %s>Auto</option>", 2015 nvram_match("wl_auth", "2") ? "selected" : ""); 2016 websWrite(wp, "<option value=\"1\" %s>Shared</option>", 2017 nvram_match("wl_auth", "1") ? "selected" : ""); 2018 websWrite(wp, "<option value=\"0\" %s>Open</option>", 2019 nvram_match("wl_auth", "0") ? "selected" : ""); 2020 2021 return 1; 2022} 2023 2024static int 2025ej_emf_enable_display(int eid, webs_t wp, int argc, char_t **argv) 2026{ 2027#ifdef __CONFIG_EMF__ 2028 websWrite(wp, "<p>\n"); 2029 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2030 websWrite(wp, "<tr>\n"); 2031 websWrite(wp, "<th width=\"310\"\n"); 2032 websWrite(wp, "onMouseOver=\"return overlib(\'Enables/Disables Efficient Multicast Forwarding feature\', LEFT);\"\n"); 2033 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2034 websWrite(wp, "EMF: \n"); 2035 websWrite(wp, "</th>\n"); 2036 websWrite(wp, "<td> </td>\n"); 2037 websWrite(wp, "<td>\n"); 2038 websWrite(wp, "<select name=\"emf_enable\">\n"); 2039 websWrite(wp, "<option value=\"1\" %s>Enabled</option>", nvram_match("emf_enable", "1") ? "selected": "\n"); 2040 websWrite(wp, "<option value=\"0\" %s>Disabled</option>", nvram_match("emf_enable", "0") ? "selected": "\n"); 2041 websWrite(wp, "</select>\n"); 2042 websWrite(wp, "</td>\n"); 2043 websWrite(wp, "</tr>\n"); 2044 websWrite(wp, "</table>\n"); 2045#endif /* __CONFIG_EMF__ */ 2046 2047 return 1; 2048} 2049 2050#ifdef __CONFIG_EMF__ 2051/* 2052 * Example: 2053 * emf_entry=225.0.0.1:wds0.1 225.0.0.2:wds0.2 ... 2054 * get_emf_entry("mgrp", 0) : produces "225.0.0.1" 2055 * get_emf_entry("if", 0) : produces "wds0.1" 2056 */ 2057void 2058get_emf_entry(char *arg, int entry, char *output) 2059{ 2060 char word[256], *next; 2061 char *mgrp, *ifname; 2062 2063 foreach(word, nvram_safe_get("emf_entry"), next) { 2064 if (entry-- == 0) { 2065 ifname = word; 2066 mgrp = strsep(&ifname, ":"); 2067 if (!mgrp || !ifname) 2068 continue; 2069 if (!strcmp(arg, "mgrp")) { 2070 strcpy(output, mgrp); 2071 return; 2072 } 2073 else if (!strcmp(arg, "if")) { 2074 strcpy(output, ifname); 2075 return; 2076 } 2077 } 2078 } 2079 2080 strcpy(output, ""); 2081 2082 return; 2083} 2084#endif /* __CONFIG_EMF__ */ 2085 2086static int 2087ej_emf_entries_display(int eid, webs_t wp, int argc, char_t **argv) 2088{ 2089#ifdef __CONFIG_EMF__ 2090 char value[32]; 2091 2092 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2093 websWrite(wp, "<tr>\n"); 2094 websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"6\"\n"); 2095 websWrite(wp, "onMouseOver=\"return overlib(\'Add/Delete static forwarding entries for the multicast groups.\', LEFT);\"\n"); 2096 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2097 websWrite(wp, "<input type=\"hidden\" name=\"emf_entry\" value=\"5\">\n"); 2098 websWrite(wp, "Static Multicast Forwarding Entries: \n"); 2099 websWrite(wp, "</th>\n"); 2100 websWrite(wp, "<td> </td>\n"); 2101 websWrite(wp, "<td class=\"label\">Multicast IP Address</td>\n"); 2102 websWrite(wp, "<td></td>\n"); 2103 websWrite(wp, "<td class=\"label\">Interface</td>\n"); 2104 websWrite(wp, "</tr>\n"); 2105 websWrite(wp, "<tr>\n"); 2106 websWrite(wp, "<td> </td>\n"); 2107 get_emf_entry("mgrp", 0, value); 2108 websWrite(wp, "<td><input name=\"emf_entry_mgrp0\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2109 websWrite(wp, "<td> </td>\n"); 2110 get_emf_entry("if", 0, value); 2111 websWrite(wp, "<td><input name=\"emf_entry_if0\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2112 websWrite(wp, "</tr>\n"); 2113 websWrite(wp, "<tr>\n"); 2114 websWrite(wp, "<td> </td>\n"); 2115 get_emf_entry("mgrp", 1, value); 2116 websWrite(wp, "<td><input name=\"emf_entry_mgrp1\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2117 websWrite(wp, "<td> </td>\n"); 2118 get_emf_entry("if", 1, value); 2119 websWrite(wp, "<td><input name=\"emf_entry_if1\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2120 websWrite(wp, "</tr>\n"); 2121 websWrite(wp, "<tr>\n"); 2122 websWrite(wp, "<td> </td>\n"); 2123 get_emf_entry("mgrp", 2, value); 2124 websWrite(wp, "<td><input name=\"emf_entry_mgrp2\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2125 websWrite(wp, "<td> </td>\n"); 2126 get_emf_entry("if", 2, value); 2127 websWrite(wp, "<td><input name=\"emf_entry_if2\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2128 websWrite(wp, "</tr>\n"); 2129 websWrite(wp, "<tr>\n"); 2130 websWrite(wp, "<td> </td>\n"); 2131 get_emf_entry("mgrp", 3, value); 2132 websWrite(wp, "<td><input name=\"emf_entry_mgrp3\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2133 websWrite(wp, "<td> </td>\n"); 2134 get_emf_entry("if", 3, value); 2135 websWrite(wp, "<td><input name=\"emf_entry_if3\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2136 websWrite(wp, "</tr>\n"); 2137 websWrite(wp, "<tr>\n"); 2138 websWrite(wp, "<td> </td>\n"); 2139 get_emf_entry("mgrp", 4, value); 2140 websWrite(wp, "<td><input name=\"emf_entry_mgrp4\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2141 websWrite(wp, "<td> </td>\n"); 2142 get_emf_entry("if", 4, value); 2143 websWrite(wp, "<td><input name=\"emf_entry_if4\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2144 websWrite(wp, "</tr>\n"); 2145 websWrite(wp, "</table>\n"); 2146#endif /* __CONFIG_EMF__ */ 2147 2148 return 1; 2149} 2150 2151#ifdef __CONFIG_EMF__ 2152/* 2153 * Example: 2154 * emf_uffp_entry=wds0.1 wds0.2 ... 2155 * get_emf_uffp_entry("if", 0) : produces "wds0.1" 2156 * get_emf_uffp_entry("if", 1) : produces "wds0.2" 2157 */ 2158void 2159get_emf_uffp_entry(char *arg, int entry, char *output) 2160{ 2161 char word[256], *next; 2162 char *ifname; 2163 2164 foreach(word, nvram_safe_get("emf_uffp_entry"), next) { 2165 if (entry-- == 0) { 2166 ifname = word; 2167 if (ifname[0] == '\0') 2168 continue; 2169 if (!strcmp(arg, "if")) { 2170 strcpy(output, ifname); 2171 return; 2172 } 2173 } 2174 } 2175 2176 strcpy(output, ""); 2177 2178 return; 2179} 2180 2181/* 2182 * Example: 2183 * emf_rtport_entry=wds0.1 wds0.2 ... 2184 * get_emf_rtport_entry("if", 0) : produces "wds0.1" 2185 * get_emf_rtport_entry("if", 1) : produces "wds0.2" 2186 */ 2187void 2188get_emf_rtport_entry(char *arg, int entry, char *output) 2189{ 2190 char word[256], *next; 2191 char *ifname; 2192 2193 foreach(word, nvram_safe_get("emf_rtport_entry"), next) { 2194 if (entry-- == 0) { 2195 ifname = word; 2196 if (ifname[0] == '\0') 2197 continue; 2198 if (!strcmp(arg, "if")) { 2199 strcpy(output, ifname); 2200 return; 2201 } 2202 } 2203 } 2204 2205 strcpy(output, ""); 2206 2207 return; 2208} 2209#endif /* __CONFIG_EMF__ */ 2210 2211static int 2212ej_emf_uffp_entries_display(int eid, webs_t wp, int argc, char_t **argv) 2213{ 2214#ifdef __CONFIG_EMF__ 2215 char value[32]; 2216 2217 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2218 websWrite(wp, "<tr>\n"); 2219 websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"6\"\n"); 2220 websWrite(wp, "onMouseOver=\"return overlib(\'Add/Delete unregistered multicast data frames forwarding port entries. Multicast data frames that fail MFDB lookup will be flooded on to these ports.\', LEFT);\"\n"); 2221 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2222 websWrite(wp, "<input type=\"hidden\" name=\"emf_uffp_entry\" value=\"5\">\n"); 2223 websWrite(wp, "Unregistered Multicast Frames Forwarding Ports: \n"); 2224 websWrite(wp, "</th>\n"); 2225 websWrite(wp, "<td> </td>\n"); 2226 websWrite(wp, "<td class=\"label\">Interface</td>\n"); 2227 websWrite(wp, "<td></td>\n"); 2228 websWrite(wp, "</tr>\n"); 2229 websWrite(wp, "<tr>\n"); 2230 websWrite(wp, "<td> </td>\n"); 2231 get_emf_uffp_entry("if", 0, value); 2232 websWrite(wp, "<td><input name=\"emf_uffp_entry_if0\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2233 websWrite(wp, "<td> </td>\n"); 2234 websWrite(wp, "<td></td>\n"); 2235 websWrite(wp, "</tr>\n"); 2236 websWrite(wp, "<tr>\n"); 2237 websWrite(wp, "<td> </td>\n"); 2238 get_emf_uffp_entry("if", 1, value); 2239 websWrite(wp, "<td><input name=\"emf_uffp_entry_if1\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2240 websWrite(wp, "<td> </td>\n"); 2241 websWrite(wp, "<td></td>\n"); 2242 websWrite(wp, "</tr>\n"); 2243 websWrite(wp, "<tr>\n"); 2244 websWrite(wp, "<td> </td>\n"); 2245 get_emf_uffp_entry("if", 2, value); 2246 websWrite(wp, "<td><input name=\"emf_uffp_entry_if2\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2247 websWrite(wp, "<td> </td>\n"); 2248 websWrite(wp, "<td></td>\n"); 2249 websWrite(wp, "</tr>\n"); 2250 websWrite(wp, "<tr>\n"); 2251 websWrite(wp, "<td> </td>\n"); 2252 get_emf_uffp_entry("if", 3, value); 2253 websWrite(wp, "<td><input name=\"emf_uffp_entry_if3\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2254 websWrite(wp, "<td> </td>\n"); 2255 websWrite(wp, "<td></td>\n"); 2256 websWrite(wp, "</tr>\n"); 2257 websWrite(wp, "<tr>\n"); 2258 websWrite(wp, "<td> </td>\n"); 2259 get_emf_uffp_entry("if", 4, value); 2260 websWrite(wp, "<td><input name=\"emf_uffp_entry_if4\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2261 websWrite(wp, "<td> </td>\n"); 2262 websWrite(wp, "<td></td>\n"); 2263 websWrite(wp, "</tr>\n"); 2264 websWrite(wp, "</table>\n"); 2265#endif /* __CONFIG_EMF__ */ 2266 2267 return 1; 2268} 2269 2270static int 2271ej_emf_rtport_entries_display(int eid, webs_t wp, int argc, char_t **argv) 2272{ 2273#ifdef __CONFIG_EMF__ 2274 char value[32]; 2275 2276 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2277 websWrite(wp, "<tr>\n"); 2278 websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"6\"\n"); 2279 websWrite(wp, "onMouseOver=\"return overlib(\'These are the LAN interfaces on which multicast routers are present. IGMP Report frames are forwared to these ports.\', LEFT);\"\n"); 2280 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2281 websWrite(wp, "<input type=\"hidden\" name=\"emf_rtport_entry\" value=\"5\">\n"); 2282 websWrite(wp, "Multicast Router / IGMP Forwarding Ports: \n"); 2283 websWrite(wp, "</th>\n"); 2284 websWrite(wp, "<td> </td>\n"); 2285 websWrite(wp, "<td class=\"label\">Interface</td>\n"); 2286 websWrite(wp, "<td></td>\n"); 2287 websWrite(wp, "</tr>\n"); 2288 websWrite(wp, "<tr>\n"); 2289 websWrite(wp, "<td> </td>\n"); 2290 get_emf_rtport_entry("if", 0, value); 2291 websWrite(wp, "<td><input name=\"emf_rtport_entry_if0\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2292 websWrite(wp, "<td> </td>\n"); 2293 websWrite(wp, "<td></td>\n"); 2294 websWrite(wp, "</tr>\n"); 2295 websWrite(wp, "<tr>\n"); 2296 websWrite(wp, "<td> </td>\n"); 2297 get_emf_rtport_entry("if", 1, value); 2298 websWrite(wp, "<td><input name=\"emf_rtport_entry_if1\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2299 websWrite(wp, "<td> </td>\n"); 2300 websWrite(wp, "<td></td>\n"); 2301 websWrite(wp, "</tr>\n"); 2302 websWrite(wp, "<tr>\n"); 2303 websWrite(wp, "<td> </td>\n"); 2304 get_emf_rtport_entry("if", 2, value); 2305 websWrite(wp, "<td><input name=\"emf_rtport_entry_if2\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2306 websWrite(wp, "<td> </td>\n"); 2307 websWrite(wp, "<td></td>\n"); 2308 websWrite(wp, "</tr>\n"); 2309 websWrite(wp, "<tr>\n"); 2310 websWrite(wp, "<td> </td>\n"); 2311 get_emf_rtport_entry("if", 3, value); 2312 websWrite(wp, "<td><input name=\"emf_rtport_entry_if3\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2313 websWrite(wp, "<td> </td>\n"); 2314 websWrite(wp, "<td></td>\n"); 2315 websWrite(wp, "</tr>\n"); 2316 websWrite(wp, "<tr>\n"); 2317 websWrite(wp, "<td> </td>\n"); 2318 get_emf_rtport_entry("if", 4, value); 2319 websWrite(wp, "<td><input name=\"emf_rtport_entry_if4\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>\n", value); 2320 websWrite(wp, "<td> </td>\n"); 2321 websWrite(wp, "<td></td>\n"); 2322 websWrite(wp, "</tr>\n"); 2323 websWrite(wp, "</table>\n"); 2324#endif /* __CONFIG_EMF__ */ 2325 2326 return 1; 2327} 2328 2329static int 2330ej_ses_wds_mode_list(int eid, webs_t wp, int argc, char_t **argv) 2331{ 2332 websWrite(wp, "<option value=\"0\" %s>Disabled</option>\n", 2333 nvram_match("ses_wds_mode", "0") ? "selected" : "" ); 2334 websWrite(wp, "<option value=\"1\" %s>Auto</option>\n", 2335 nvram_match("ses_wds_mode", "1") ? "selected" : "" ); 2336 websWrite(wp, "<option value=\"2\" %s>Configurator(Reg+WDS)</option>\n", 2337 nvram_match("ses_wds_mode", "2") ? "selected" : "" ); 2338 websWrite(wp, "<option value=\"3\" %s>Configurator(WDS only)</option>\n", 2339 nvram_match("ses_wds_mode", "3") ? "selected" : "" ); 2340 if( !nvram_match( "ses_cl_enable", "0" )) 2341 websWrite(wp, "<option value=\"4\" %s>Client</option>\n", 2342 nvram_match("ses_wds_mode", "4") ? "selected" : "" ); 2343 return 1; 2344} 2345 2346static int 2347ej_wl_radio_roam_option(int eid, webs_t wp, int argc, char_t **argv) 2348{ 2349 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 2350 char *name=NULL; 2351 int radio_status = 0; 2352 2353 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 2354 websError(wp, 400, "unit number variable doesn't exist\n"); 2355 return -1; 2356 } 2357 name = nvram_get(strcat_r(prefix, "ifname", tmp)); 2358 2359 if (!name){ 2360 websError(wp, 400, "Could not find: %s\n",strcat_r(prefix, "ifname", tmp)); 2361 return -1; 2362 } 2363 2364 wl_ioctl(name, WLC_GET_RADIO, &radio_status, sizeof (radio_status)); 2365 radio_status &= WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE; 2366 2367 if (!radio_status) /* Radio on*/ 2368 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"RadioOff\" >"); 2369 else /* Radio Off */ 2370 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"RadioOn\" >"); 2371 2372 return 1; 2373 2374 2375} 2376 2377static int 2378ej_wet_tunnel_display(int eid, webs_t wp, int argc, char_t **argv) 2379{ 2380 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 2381 char cap[WLC_IOCTL_SMLEN]; 2382 char caps[WLC_IOCTL_MEDLEN]; 2383 char *name = NULL; 2384 char *next = NULL; 2385 int wet_tunnel_cap = 0; 2386 2387 if (!make_wl_prefix(prefix, sizeof(prefix), 0, NULL)) { 2388 websError(wp, 400, "unit number variable doesn't exist\n"); 2389 return -1; 2390 } 2391 2392 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 2393 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 2394 return -1; 2395 2396 foreach(cap, caps, next) { 2397 if (!strcmp(cap, "wet_tunnel")) { 2398 wet_tunnel_cap = 1; 2399 break; 2400 } 2401 } 2402 if (wet_tunnel_cap == 0) 2403 return -1; 2404 2405 websWrite(wp, "<p>\n"); 2406 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2407 websWrite(wp, "<tr>\n"); 2408 websWrite(wp, "<th width=\"310\"\n"); 2409 websWrite(wp, "onMouseOver=\"return overlib(\'Enable/Disable WET tunnel\', LEFT);\"\n"); 2410 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2411 websWrite(wp, "WET Tunnel: \n"); 2412 websWrite(wp, "</th>\n"); 2413 websWrite(wp, "<td> </td>\n"); 2414 websWrite(wp, "<td>\n"); 2415 websWrite(wp, "<select name=\"wl_wet_tunnel\">\n"); 2416 websWrite(wp, "<option value=\"1\" %s>Enabled</option>", nvram_match("wl_wet_tunnel", "1") ? "selected": "\n"); 2417 websWrite(wp, "<option value=\"0\" %s>Disabled</option>", nvram_match("wl_wet_tunnel", "0") ? "selected": "\n"); 2418 websWrite(wp, "</select>\n"); 2419 websWrite(wp, "</td>\n"); 2420 websWrite(wp, "</tr>\n"); 2421 websWrite(wp, "</table>\n"); 2422 2423 return 1; 2424} 2425 2426#ifdef TRAFFIC_MGMT_RSSI_POLICY 2427static int 2428ej_trf_mgmt_rssi_policy_display(int eid, webs_t wp, int argc, char_t **argv) 2429{ 2430 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 2431 char cap[WLC_IOCTL_SMLEN]; 2432 char caps[WLC_IOCTL_MEDLEN]; 2433 char *name = NULL; 2434 char *next = NULL; 2435 int trf_mgmt_cap = 0; 2436 2437 if (!make_wl_prefix(prefix, sizeof(prefix), 0, NULL)) { 2438 websError(wp, 400, "unit number variable doesn't exist\n"); 2439 return -1; 2440 } 2441 2442 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 2443 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 2444 return -1; 2445 2446 foreach(cap, caps, next) { 2447 if (!strcmp(cap, "traffic-mgmt")) { 2448 trf_mgmt_cap = 1; 2449 break; 2450 } 2451 } 2452 if (trf_mgmt_cap == 0) 2453 return -1; 2454 2455 websWrite(wp, "<p>\n"); 2456 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 2457 websWrite(wp, "<tr>\n"); 2458 websWrite(wp, "<th width=\"310\"\n"); 2459 websWrite(wp, "onMouseOver=\"return overlib(\'Set to map lowest RSSI STA to low priority(BE) or disable.\', LEFT);\"\n"); 2460 websWrite(wp, "onMouseOut=\"return nd();\">\n"); 2461 websWrite(wp, "Traffic Management RSSI Policy: \n"); 2462 websWrite(wp, "</th>\n"); 2463 websWrite(wp, "<td> </td>\n"); 2464 websWrite(wp, "<td>\n"); 2465 websWrite(wp, "<select name=\"wl_trf_mgmt_rssi_policy\">\n"); 2466 websWrite(wp, "<option value=\"0\" %s>None</option>", nvram_match("wl_trf_mgmt_rssi_policy", "0") ? "selected": "\n"); 2467 websWrite(wp, "<option value=\"1\" %s>Lowest RSSI</option>", nvram_match("wl_trf_mgmt_rssi_policy", "1") ? "selected": "\n"); 2468 websWrite(wp, "</select>\n"); 2469 websWrite(wp, "</td>\n"); 2470 websWrite(wp, "</tr>\n"); 2471 websWrite(wp, "</table>\n"); 2472 2473 return 1; 2474} 2475#endif /* TRAFFIC_MGMT_RSSI_POLICY */ 2476 2477#if defined(__CONFIG_DLNA_DMS__) 2478#ifdef LINUX26 2479static char *mntdir = "/media"; 2480#else 2481static char *mntdir = "/mnt"; 2482#endif 2483#endif 2484 2485 2486#if defined(__CONFIG_DLNA_DMS__) 2487static int 2488ej_get_mnt_path(int eid, webs_t wp, int argc, char_t **argv) 2489{ 2490 char mntpath[128] = {0}; 2491 char devpath[128] = {0}; 2492 FILE *fp; 2493 char buf[256]; 2494 2495 memset(mntpath, 0, sizeof(mntpath)); 2496 memset(devpath, 0, sizeof(devpath)); 2497 2498 if ((fp = fopen("/proc/mounts", "r")) != NULL) { 2499 while (fgets(buf, sizeof(buf), fp) != NULL) { 2500 if (strstr(buf, mntdir) != NULL) { 2501 sscanf(buf, "%s %s", devpath, mntpath); 2502 break; 2503 } 2504 } 2505 fclose(fp); 2506 } 2507 2508 return websWrite(wp, mntpath); 2509} 2510#endif /* __CONFIG_DLNA_DMS__ */ 2511 2512#ifdef __CONFIG_WPS__ 2513/* WPS ENR mode APIs */ 2514typedef struct wps_ap_list_info 2515{ 2516 bool used; 2517 uint8 ssid[33]; 2518 uint8 ssidLen; 2519 uint8 BSSID[6]; 2520 uint8 *ie_buf; 2521 uint32 ie_buflen; 2522 uint8 channel; 2523 uint8 wep; 2524 bool scstate; 2525} wps_ap_list_info_t; 2526 2527#define WPS_ENR_DUMP_BUF_LEN (32 * 1024) 2528#define WPS_ENR_MAX_AP_SCAN_LIST_LEN 50 2529#define WPS_ENR_SCAN_RETRY_TIMES 5 2530 2531static wps_ap_list_info_t ap_list[WPS_ENR_MAX_AP_SCAN_LIST_LEN]; 2532static char scan_result[WPS_ENR_DUMP_BUF_LEN]; 2533static int scanned = 0, wps_ap_num = 0; 2534wps_ap_list_info_t *selected_ap = NULL; 2535 2536static int ej_wps_process(int eid, webs_t wp, int argc, char_t **argv); 2537static int ej_wps_current_mode(int eid, webs_t wp, int argc, char_t **argv, int wps_sta); 2538static int ej_wps_start(int eid, webs_t wp, int argc, char_t **argv, int wps_sta); 2539static int ej_wps_credentials(int eid, webs_t wp, int argc, char_t **argv, int wps_sta); 2540static int ej_wps_enr_scan_result(int eid, webs_t wp, int argc, char_t **argv); 2541static int ej_wps_enr_process(int eid, webs_t wp, int argc, char_t **argv); 2542static int wps_gen_ssid(char *ssid, int ssid_len); 2543static int wps_gen_key(char *key, int key_len); 2544static wps_ap_list_info_t *wps_enr_create_aplist(); 2545static int wps_enr_get_aplist(wps_ap_list_info_t *list_in, wps_ap_list_info_t *list_out ); 2546 2547#define MACLIST_MAX_NUM 16 2548 2549static int wps_config_command; 2550static int wps_action = 0; 2551static int wps_method; 2552static char wps_autho_sta_mac[sizeof("00:00:00:00:00:00")]; 2553static char wps_uuid[36]; 2554static char wps_unit[32]; 2555static int ssid_update = 0; 2556static char random_ssid[33] = {0}; 2557static char random_psk[65] = {0}; 2558#ifdef __CONFIG_NFC__ 2559static int wps_nfc_dm_status; 2560static int wps_nfc_err_code; 2561#endif 2562static int get_wps_env(); 2563 2564static int wps_get_lan_idx(); 2565static int wps_is_reg(); 2566static int wps_is_oob(); 2567static void wps_disable_oob(); 2568static int wps_get_oob_name(char *name, int lan); 2569 2570static void 2571wl_wpsPinGen(char *devPwd) 2572{ 2573 unsigned long PIN; 2574 unsigned long int accum = 0; 2575 int digit; 2576 2577 srand(time((time_t *)NULL)); 2578 PIN = rand(); 2579 sprintf(devPwd, "%08u", (unsigned int)PIN); 2580 devPwd[7] = '\0'; 2581 2582 PIN = strtoul( devPwd, NULL, 10 ); 2583 2584 PIN *= 10; 2585 accum += 3 * ((PIN / 10000000) % 10); 2586 accum += 1 * ((PIN / 1000000) % 10); 2587 accum += 3 * ((PIN / 100000) % 10); 2588 accum += 1 * ((PIN / 10000) % 10); 2589 accum += 3 * ((PIN / 1000) % 10); 2590 accum += 1 * ((PIN / 100) % 10); 2591 accum += 3 * ((PIN / 10) % 10); 2592 2593 digit = (accum % 10); 2594 accum = (10 - digit) % 10; 2595 2596 PIN += accum; 2597 sprintf(devPwd, "%u", (unsigned int)PIN); 2598 devPwd[8] = '\0'; 2599 2600 printf("Generate WPS PIN = %s\n", devPwd); 2601 return; 2602} 2603 2604static int 2605wl_wpsPincheck(char *pin_string) 2606{ 2607 unsigned long PIN = strtoul(pin_string, NULL, 10); 2608 unsigned long int accum = 0; 2609 unsigned int len = strlen(pin_string); 2610 2611 if (len != 4 && len != 8) 2612 return -1; 2613 2614 if (len == 8) { 2615 accum += 3 * ((PIN / 10000000) % 10); 2616 accum += 1 * ((PIN / 1000000) % 10); 2617 accum += 3 * ((PIN / 100000) % 10); 2618 accum += 1 * ((PIN / 10000) % 10); 2619 accum += 3 * ((PIN / 1000) % 10); 2620 accum += 1 * ((PIN / 100) % 10); 2621 accum += 3 * ((PIN / 10) % 10); 2622 accum += 1 * ((PIN / 1) % 10); 2623 2624 if (0 == (accum % 10)) 2625 return 0; 2626 } 2627 else if (len == 4) 2628 return 0; 2629 2630 return -1; 2631} 2632 2633#ifdef __CONFIG_NFC__ 2634static int 2635ej_wps_nfc_dm_status(int eid, webs_t wp, int argc, char_t **argv) 2636{ 2637 2638 char *status; 2639 2640 if (!nvram_match( "wl_wps_mode", "enabled" )) 2641 return 0; 2642 2643 switch (wps_nfc_dm_status) { 2644 case WPS_UI_NFC_STATUS_INITED: 2645 websWrite(wp, "Successful Initiated"); 2646 break; 2647 case WPS_UI_NFC_STATUS_INITING: 2648 websWrite(wp, "Initiating"); 2649 break; 2650 default: 2651 websWrite(wp, "Error: code %d\n", wps_nfc_dm_status); 2652 break; 2653 } 2654 2655 return 0; 2656} 2657#endif /* __CONFIG_NFC__ */ 2658#endif /* __CONFIG_WPS__ */ 2659 2660 2661/* Always have following ej_wps_xxx functions */ 2662static int 2663ej_wps_display(int eid, webs_t wp, int argc, char_t **argv) 2664{ 2665#ifdef __CONFIG_WPS__ 2666 /* We need to separate STA and AP */ 2667 char *str; 2668 int wps_sta = 0; 2669 char prefix[] = "wlXXXXXXXXXX_"; 2670 char wl_mode[]="wlXXXXXXXXXX_mode"; 2671 char wps_mode[100]; 2672 char *value; 2673 char tmp[100] = {0}; 2674 2675 if ((value = websGetVar(wp, "wl_unit", NULL))) { 2676 printf("ej_wps_display: wl_unit=%s\n", value); 2677 nvram_set("wl_unit", value); 2678 } 2679 2680 if (!make_wl_prefix(prefix,sizeof(prefix), 1, NULL)) { 2681 websError(wp, 400, "unit number variable doesn't exist\n"); 2682 return EINVAL; 2683 } 2684 2685 snprintf(wl_mode,sizeof(wl_mode),"%smode",prefix); 2686 value = nvram_safe_get(wl_mode); 2687 if (!strcmp(value, "wet") || 2688 !strcmp(value, "sta") || 2689 !strcmp(value, "psr") || 2690 !strcmp(value, "psta") || 2691 !strcmp(value, "mac_spoof")) { 2692 wps_sta = 1; 2693 } 2694 2695 if ((value = websGetVar(wp, "wps_action", NULL))) { 2696 if (!strcmp(value, "AddEnrollee")) 2697 wps_action = WPS_UI_ACT_ADDENROLLEE; 2698 else if (!strcmp(value, "Enroll")) 2699 wps_action = WPS_UI_ACT_ENROLL; 2700 else if (!strcmp(value, "ConfigAP")) 2701 wps_action = WPS_UI_ACT_STA_CONFIGAP; 2702 else if (!strcmp(value, "GetAPConfig")) 2703 wps_action = WPS_UI_ACT_STA_GETAPCONFIG; 2704 } 2705 2706 if (!wps_sta) { 2707 if (wps_action != WPS_UI_ACT_ADDENROLLEE ) 2708 wps_action = WPS_UI_ACT_ADDENROLLEE; 2709 } 2710 else { 2711 if (wps_action == WPS_UI_ACT_NONE || 2712 wps_action == WPS_UI_ACT_ADDENROLLEE ){ 2713 wps_action = WPS_UI_ACT_ENROLL; 2714 } 2715 } 2716 2717 /* Parse WPS method */ 2718 if (wps_action == WPS_UI_ACT_ENROLL) { 2719 if ((value = websGetVar(wp, "wps_method", NULL))) { 2720 if (!strcmp(value, "PIN")) 2721 wps_method = WPS_UI_METHOD_PIN; 2722 else 2723 wps_method = WPS_UI_METHOD_PBC; 2724 } 2725 snprintf(tmp, sizeof(tmp), "%d", wps_method); 2726 nvram_set("wps_method", tmp); 2727 } 2728 2729 websWrite(wp,"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"); 2730 2731 websWrite(wp, "<tr>" 2732 "<th width=\"310\"" 2733 "onMouseOver=\"return overlib('WPS current mode', LEFT);\"" 2734 "onMouseOut=\"return nd();\">" 2735 "WPS Current Mode: " 2736 "</th>" 2737 "<td> </td>" 2738 "<td>"); 2739 2740 ej_wps_current_mode(eid, wp, argc, argv, wps_sta); 2741 websWrite(wp, "</td> </tr>"); 2742 websWrite(wp, "<tr><th width=\"310\"></th><td> </td><td></td></tr>\n"); 2743 2744 websWrite(wp, "<tr>" 2745 "<th width=\"310\"" 2746 "onMouseOver=\"return overlib('Selects WiFi Simple Config mode.', LEFT);\"" 2747 "onMouseOut=\"return nd();\">" 2748 "WPS Configuration: " 2749 "</th>" 2750 "<td> </td>\n" 2751 "<td>" ); 2752 websWrite(wp,"<select name=\"wl_wps_mode\" onChange=\"wps_config_change();\">"); 2753 2754 sprintf(wps_mode, "%swps_mode", prefix); 2755 if (nvram_match(wps_mode, "enabled")) { 2756 websWrite(wp, "<option value=\"enabled\" selected>Enabled</option>"); 2757 websWrite(wp, "<option value=\"disabled\">Disabled</option>"); 2758 } 2759 else { 2760 websWrite(wp, "<option value=\"enabled\">Enabled</option>"); 2761 websWrite(wp, "<option value=\"disabled\" selected>Disabled</option>"); 2762 } 2763 2764 websWrite(wp, "</select> </td> </tr>\n"); 2765 2766 /* If WPS is disabled, don't show any configurations util wps_mode is enabled */ 2767 if (nvram_invmatch(wps_mode, "enabled")) { 2768 websWrite(wp, "</table>\n"); 2769 goto out; 2770 } 2771 2772 /* show Device UUID */ 2773 websWrite(wp,"<tr>" 2774 "<th width=\"310\"" 2775 "onMouseOver=\"return overlib('A WPS UUID number of this device.', LEFT);\"" 2776 "onMouseOut=\"return nd();\">" 2777 "Device WPS UUID: " 2778 "</th>" 2779 "<td> </td>\n"); 2780 str = wps_uuid; 2781 websWrite(wp,"<td>%s</td><td> ",str); 2782 websWrite(wp, "</td></tr>\n"); 2783 2784 /* show Device PIN */ 2785 websWrite(wp,"<tr>" 2786 "<th width=\"310\"" 2787 "onMouseOver=\"return overlib('A PIN number of this device.', LEFT);\"" 2788 "onMouseOut=\"return nd();\">" 2789 "Device PIN: " 2790 "</th>" 2791 "<td> </td>"); 2792 str = nvram_get("wps_device_pin"); 2793 websWrite(wp,"<td>%s",str); 2794 2795 /* show Generate button */ 2796 if (wps_config_command != WPS_UI_CMD_START) 2797 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Generate\">"); 2798 2799 websWrite(wp,"</td></tr>\n"); 2800 if (!wps_sta) { 2801 /* show allow/deny Wireless External Registrar Get/Configure AP securit */ 2802 websWrite(wp, "<tr>" 2803 "<th width=\"310\"" 2804 "onMouseOver=\"return overlib('Set allow/deny Wireless External Registrar get/configure AP security through AP PIN', LEFT);\"" 2805 "onMouseOut=\"return nd();\">" 2806 "Configure by External Registrar: " 2807 "</th>" 2808 "<td> </td>\n" 2809 "<td>"); 2810 websWrite(wp, "<select name=\"wps_wer_mode\">"); 2811 if (nvram_match("wps_wer_mode", "allow")) { 2812 websWrite(wp, "<option value=\"allow\" selected>Allow</option>"); 2813 websWrite(wp, "<option value=\"deny\" >Deny</option>"); 2814 } 2815 else { 2816 websWrite(wp, "<option value=\"allow\" >Allow</option>"); 2817 websWrite(wp, "<option value=\"deny\" selected>Deny</option>"); 2818 } 2819 websWrite(wp, "</select> </td> </tr>\n"); 2820 2821 /* show empty column */ 2822 websWrite(wp, "<tr><th width=\"310\"></th><td> </td><td></td></tr>\n"); 2823 2824 } /* !wps_sta */ 2825 2826 if (wps_sta) { 2827 2828 /* WPS AP list */ 2829 websWrite(wp,"<tr>" 2830 "<th width=\"310\"" 2831 "onMouseOver=\"return overlib('WPS support AP list.', LEFT);\"" 2832 "onMouseOut=\"return nd();\">" 2833 "WPS AP List: " 2834 "</th>" 2835 "<td> </td>" 2836 "<td>"); 2837 websWrite(wp, "<select name=\"wps_ap_list\">"); 2838 ej_wps_enr_scan_result(eid, wp, argc, argv); 2839 websWrite(wp, "</select>"); 2840 if (wps_config_command != WPS_UI_CMD_START) 2841 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Rescan\">"); 2842 websWrite(wp, "</td></tr>\n"); 2843 } 2844 2845 if (wps_config_command == WPS_UI_CMD_NONE) { 2846 /* show wps_action */ 2847 if (wps_sta) { 2848 /* show wps-action */ 2849 websWrite(wp, "<tr>" 2850 "<th width=\"310\"" 2851 "onMouseOver=\"return overlib('The action for wps running later', LEFT);\"" 2852 "onMouseOut=\"return nd();\">" 2853 "WPS Action: " 2854 "</th>" 2855 "<td> </td>\n" 2856 "<td>"); 2857 websWrite(wp, "<select name=\"wps_action\" onChange=\"submit();\">"); 2858 websWrite(wp, "<option value=\"Enroll\"%s>Enroll</option>", 2859 (wps_action == WPS_UI_ACT_ENROLL) ? " selected":""); 2860 websWrite(wp, "<option value=\"ConfigAP\"%s >Config AP</option>", 2861 (wps_action == WPS_UI_ACT_STA_CONFIGAP) ? " selected":""); 2862 websWrite(wp, "<option value=\"GetAPConfig\" %s>Get AP Config</option>", 2863 (wps_action == WPS_UI_ACT_STA_GETAPCONFIG) ? " selected":""); 2864 /* show empty column */ 2865 websWrite(wp, "<tr><th width=\"310\"></th><td> </td><td></td></tr>\n"); 2866 } 2867 else { 2868 /* AP always act as AddEnrollee */ 2869 websWrite(wp, "<tr><th width=\"310\"></th><td> </td>" 2870 "<td><input type=\"hidden\" name=\"wps_action\"" 2871 " value=\"AddEnrollee\"></td></tr>\n"); 2872 } 2873 2874 /* Show WPS credentials */ 2875 ej_wps_credentials(eid, wp, argc, argv, wps_sta); 2876 2877 /* show empty column */ 2878 websWrite(wp, "<tr><th width=\"310\"></th><td> </td><td></td></tr>\n"); 2879 2880 if (wps_action == WPS_UI_ACT_ENROLL) { 2881 /* show wps method */ 2882 websWrite(wp, "<tr>" 2883 "<th width=\"310\"" 2884 "onMouseOver=\"return overlib('The grant for wps exchange data', LEFT);\"" 2885 "onMouseOut=\"return nd();\">" 2886 "WPS Method: " 2887 "</th>" 2888 "<td> </td>\n" 2889 "<td>"); 2890 websWrite(wp, "<select name=\"wps_method\">"); 2891 if (wps_action == WPS_UI_ACT_ENROLL) { 2892 websWrite(wp, "<option value=\"PBC\"%s>PBC</option>", 2893 (wps_method == WPS_UI_METHOD_PBC)? " selected":""); 2894 } 2895 websWrite(wp, "<option value=\"PIN\" %s>PIN</option>", 2896 (wps_method == WPS_UI_METHOD_PIN)? " selected":""); 2897#ifdef __CONFIG_NFC__ 2898 /* NFC password token. When we are WPS_UI_ACT_ENROLL */ 2899 websWrite(wp, "<option value=\"NFC\" %s>NFC</option>", 2900 (wps_method == WPS_UI_METHOD_NFC_PW)? " selected":""); 2901#endif 2902 if (wps_action == WPS_UI_ACT_ENROLL) { 2903 websWrite(wp, "</select> If PIN is selected, please set PIN \"%s\" to the WPS AP or registrar.</td> </tr>\n", 2904 nvram_get("wps_device_pin")); 2905 } 2906 } 2907 if (wps_action == WPS_UI_ACT_ADDENROLLEE) { 2908 /* show pin field */ 2909 websWrite(wp,"<tr>" 2910 "<th width=\"310\"" 2911 "onMouseOver=\"return overlib('Station pin for verify the station is what we expect.', LEFT);\"" 2912 "onMouseOut=\"return nd();\">" 2913 "Station PIN: " 2914 "</th>" 2915 "<td> </td>\n"); 2916 websWrite(wp,"<td><input name=\"wps_sta_pin\" value=\"\" size=\"9\" maxlength=\"9\"> Note: Empty for PBC method."); 2917 websWrite(wp, "</td></tr>\n"); 2918 2919 /* show authorized mac field */ 2920 websWrite(wp,"<tr>" 2921 "<th width=\"310\"" 2922 "onMouseOver=\"return overlib('Authorized Station MAC.', LEFT);\"" 2923 "onMouseOut=\"return nd();\">" 2924 "Authorized Station MAC: " 2925 "</th>" 2926 "<td> </td>\n"); 2927 websWrite(wp,"<td><input name=\"wps_autho_sta_mac\" value=\"\" size=\"17\" maxlength=\"17\">"); 2928 } 2929 if (wps_action == WPS_UI_ACT_STA_GETAPCONFIG || wps_action == WPS_UI_ACT_STA_CONFIGAP) { 2930 /* AP pin field */ 2931 websWrite(wp, "<tr>" 2932 "<th width=\"310\"" 2933 "onMouseOver=\"return overlib('PIN of AP.', LEFT);\"" 2934 "onMouseOut=\"return nd();\">" 2935 "AP PIN: " 2936 "</th>" 2937 "<td> </td>\n"); 2938 websWrite(wp,"<td><input name=\"wps_ap_pin\" value=\"\" size=\"9\" maxlength=\"9\">"); 2939 websWrite(wp, "</td> </tr>\n"); 2940#ifdef __CONFIG_NFC__ 2941 /* Show wps method */ 2942 websWrite(wp, "<tr>" 2943 "<th width=\"310\"" 2944 "onMouseOver=\"return overlib('The grant for wps exchange data', LEFT);\"" 2945 "onMouseOut=\"return nd();\">" 2946 "WPS Method: " 2947 "</th>" 2948 "<td> </td>\n" 2949 "<td>"); 2950 websWrite(wp, "<select name=\"wps_method\">"); 2951 websWrite(wp, "<option value=\"PIN\" %s>PIN</option>", 2952 (wps_method == WPS_UI_METHOD_PIN)? " selected":""); 2953 /* NFC password token. When we are WPS_UI_ACT_ENROLL */ 2954 websWrite(wp, "<option value=\"NFC\" %s>NFC</option>", 2955 (wps_method == WPS_UI_METHOD_NFC_PW)? " selected":""); 2956#endif /* __CONFIG_NFC__ */ 2957 } 2958 websWrite(wp, " "); 2959 /* show trigger button */ 2960 ej_wps_start(eid, wp, argc, argv, wps_sta); 2961 } 2962 2963 /* show last attempted enrollee information */ 2964 if (!wps_sta) { 2965 char *err_state = nvram_safe_get("wps_pinfail_state"); 2966 char tmp[256], devPwd[12], *warning_msg = ""; 2967 2968 if (strcmp(err_state, "M4") == 0 || 2969 strcmp(err_state, "M6") == 0) { 2970 /* show empty column */ 2971 websWrite(wp, "<tr>" 2972 "<th width=\"310\">" 2973 "</th>" 2974 "<td> </td>" 2975 "<td></td></tr>\n "); 2976 2977 /* MAC */ 2978 websWrite(wp, "<tr>"); 2979 websWrite(wp, "<th width=\"310\">" 2980 "Last Enrollee MAC: </th>" 2981 "<td> </td>\n"); 2982 websWrite(wp, "<td>%s</td>\n", nvram_safe_get("wps_pinfail_mac")); 2983 2984 /* Device Name*/ 2985 websWrite(wp, "<tr>"); 2986 websWrite(wp, "<th width=\"310\">" 2987 "Last Enrollee Name: </th>" 2988 "<td> </td>\n"); 2989 websWrite(wp, "<td>%s</td>\n", nvram_safe_get("wps_pinfail_name")); 2990 2991 /* Attacker warnng */ 2992 if (strcmp(err_state, "M4") == 0) 2993 warning_msg = "Station PIN registration failed (first half), " 2994 "be aware a brute force offline attacker " 2995 "(Eavesdropped Enrollee)."; 2996 else { 2997 wl_wpsPinGen(devPwd); 2998 sprintf(tmp, 2999 "Station PIN registration failed (second half), be aware a " 3000 "brute force offline attacker (Eavesdropped Enrollee).<br>" 3001 "Please input new Station PIN %s on both AP and Station", 3002 devPwd); 3003 warning_msg = tmp; 3004 } 3005 3006 websWrite(wp, "<tr>"); 3007 websWrite(wp, "<th width=\"310\"> </th><td> </td>\n"); 3008 websWrite(wp, "<td><b>ATTACKER WARNING<br>%s</b></td>\n", warning_msg); 3009 } 3010 } 3011 3012 /* show empty column */ 3013 websWrite(wp, "<tr>" 3014 "<th width=\"310\">" 3015 "</th>" 3016 "<td> </td>" 3017 "<td></td></tr>\n "); 3018 3019 /* show Current Status */ 3020 websWrite(wp, "<tr>" 3021 "<th width=\"310\"" 3022 "onMouseOver=\"return overlib('WPS process status', LEFT);\"" 3023 "onMouseOut=\"return nd();\">" 3024 "WPS Current Status: " 3025 "</th>" 3026 "<td> </td>\n" 3027 "<td>"); 3028 if (!wps_sta) 3029 ej_wps_process(eid, wp, argc, argv); 3030 else 3031 ej_wps_enr_process(eid, wp, argc, argv); 3032 3033 websWrite(wp, "</td> </tr>\n"); 3034 websWrite(wp, "</table>\n"); 3035 3036#ifdef __CONFIG_NFC__ 3037 /* Show NFC stuffs */ 3038 if (wps_config_command == WPS_UI_CMD_NONE) { 3039 websWrite(wp, "<p>\n"); 3040 websWrite(wp,"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 3041 3042 if (wps_action == WPS_UI_ACT_ADDENROLLEE) { 3043 /* show NFC write/read Configuration token */ 3044 websWrite(wp,"<tr>" 3045 "<th width=\"310\"" 3046 "onMouseOver=\"return overlib('Write the AP security to NFC tag and use it to configure other devices. " 3047 "Read the configuration from the NFC tag and apply to AP system', LEFT);\"" 3048 "onMouseOut=\"return nd();\">" 3049 "NFC Configuration Token: " 3050 "</th>" 3051 "<td> </td>\n"); 3052 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Write Configuration\">  "); 3053 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"NFC Read Configuration\">"); 3054 websWrite(wp, "</td></tr>\n"); 3055 } 3056 3057 if (wps_action == WPS_UI_ACT_STA_GETAPCONFIG || wps_action == WPS_UI_ACT_STA_CONFIGAP) { 3058 if (wps_action == WPS_UI_ACT_STA_GETAPCONFIG) { 3059 /* show NFC read Configuration token */ 3060 websWrite(wp,"<tr>" 3061 "<th width=\"310\"" 3062 "onMouseOver=\"return overlib('Read the configuration from the NFC tag and apply to the station', LEFT);\"" 3063 "onMouseOut=\"return nd();\">" 3064 "NFC Configuration Token: " 3065 "</th>" 3066 "<td> </td>\n"); 3067 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Read Configuration\">"); 3068 } 3069 else { 3070 /* show NFC write Configuration token, need take care the "new credentials" on the GUI */ 3071 websWrite(wp,"<tr>" 3072 "<th width=\"310\"" 3073 "onMouseOver=\"return overlib('Write the station security to NFC tag and use it to configure AP or other stations.', LEFT);\"" 3074 "onMouseOut=\"return nd();\">" 3075 "NFC Configuration Token: " 3076 "</th>" 3077 "<td> </td>\n"); 3078 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Write Configuration\">"); 3079 } 3080 websWrite(wp, "</td></tr>\n"); 3081 } 3082 3083 /* Show NFC Password token */ 3084 if (!wps_sta) { 3085 websWrite(wp,"<tr>" 3086 "<th width=\"310\"" 3087 "onMouseOver=\"return overlib('Write the AP security to NFC tag and use it to configure other devices. " 3088 "Read the configuration from the NFC tag and apply to AP system', LEFT);\"" 3089 "onMouseOut=\"return nd();\">" 3090 "NFC Password Token: " 3091 "</th>" 3092 "<td> </td>\n"); 3093 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Add Enrollee\">  "); 3094 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"NFC Config AP\">"); 3095 websWrite(wp, "</td></tr>\n"); 3096 } 3097 3098 /* Show NFC Hand Over Selector/Requester */ 3099 if (wps_action == WPS_UI_ACT_ADDENROLLEE) { 3100 /* show NFC write/read Configuration token */ 3101 websWrite(wp,"<tr>" 3102 "<th width=\"310\"" 3103 "onMouseOver=\"return overlib('Selector provide the Configuration to Requester. Requester get Configuration from Selector.', LEFT);\"" 3104 "onMouseOut=\"return nd();\">" 3105 "NFC Hand Over: " 3106 "</th>" 3107 "<td> </td>\n"); 3108 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Selecotr\">  "); 3109 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Requester\">"); 3110 websWrite(wp, "</td></tr>\n"); 3111 } 3112 3113 if (wps_action == WPS_UI_ACT_STA_GETAPCONFIG || wps_action == WPS_UI_ACT_STA_CONFIGAP || 3114 wps_action == WPS_UI_ACT_ENROLL) { 3115 if (wps_action == WPS_UI_ACT_STA_GETAPCONFIG) { 3116 /* show NFC Hand Over as Requester */ 3117 websWrite(wp,"<tr>" 3118 "<th width=\"310\"" 3119 "onMouseOver=\"return overlib('As a Requester get Configuration from Selector.', LEFT);\"" 3120 "onMouseOut=\"return nd();\">" 3121 "NFC Hand Over: " 3122 "</th>" 3123 "<td> </td>\n"); 3124 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Requester\">"); 3125 } 3126 else if (wps_action == WPS_UI_ACT_STA_CONFIGAP) { 3127 /* show NFC Hand Over as Selector, need take care the "new credentials" on the GUI */ 3128 websWrite(wp,"<tr>" 3129 "<th width=\"310\"" 3130 "onMouseOver=\"return overlib('As a Selector provide the Configuration to Requester.', LEFT);\"" 3131 "onMouseOut=\"return nd();\">" 3132 "NFC Hand Over: " 3133 "</th>" 3134 "<td> </td>\n"); 3135 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Selecotr\">"); 3136 } 3137 else { 3138 /* show NFC Hand Over as Requester/Selector */ 3139 websWrite(wp,"<tr>" 3140 "<th width=\"310\"" 3141 "onMouseOver=\"return overlib('As a Requester get Configuration from Selector or as a Selector provide the Configuration to Requester.', LEFT);\"" 3142 "onMouseOut=\"return nd();\">" 3143 "NFC Hand Over: " 3144 "</th>" 3145 "<td> </td>\n"); 3146 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Selecotr\">  "); 3147 websWrite(wp,"<td><input type=\"submit\" name=\"action\" value=\"NFC Hand Over As Requester\">"); 3148 } 3149 websWrite(wp, "</td></tr>\n"); 3150 } 3151 3152 3153 /* show NFC Device Manager status */ 3154 websWrite(wp, "<tr>" 3155 "<th width=\"310\"" 3156 "onMouseOver=\"return overlib('NFC Device Management Status', LEFT);\"" 3157 "onMouseOut=\"return nd();\">" 3158 "NFC Device Management Status: " 3159 "</th>" 3160 "<td> </td>\n" 3161 "<td>"); 3162 ej_wps_nfc_dm_status(eid, wp, argc, argv); 3163 3164 websWrite(wp, "</table>"); 3165 } 3166#endif /* __CONFIG_NFC__ */ 3167 3168#ifdef WFA_WPS_20_TESTBED 3169 /* For PlugFest testing only */ 3170 websWrite(wp, "<p>\n"); 3171 3172 websWrite(wp,"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 3173 3174 /* WPS version */ 3175 websWrite(wp, "<tr>\n" 3176 "<th width=\"310\"\n" 3177 "onMouseOver=\"return overlib('Selects WPS version.', LEFT);\"\n" 3178 "onMouseOut=\"return nd();\">\n" 3179 "WPS Version: \n" 3180 "</th>\n" 3181 "<td> </td>\n" 3182 "<td>\n"); 3183 websWrite(wp, "<select name=\"wps_version2\" onChange=\"wps_version2_change();\">\n"); 3184 if (nvram_match("wps_version2", "enabled")) { 3185 websWrite(wp, "<option value=\"enabled\" selected>V2</option>\n"); 3186 websWrite(wp, "<option value=\"disabled\">V1</option>\n"); 3187 } 3188 else { 3189 websWrite(wp, "<option value=\"enabled\">V2</option>\n"); 3190 websWrite(wp, "<option value=\"disabled\" selected>V1</option>\n"); 3191 } 3192 websWrite(wp, "</select> </td> </tr>\n"); 3193 3194 /* WPS version number */ 3195 websWrite(wp,"<tr>\n" 3196 "<th width=\"310\"\n" 3197 "onMouseOver=\"return overlib('WPS version2 number 0 ~ 255.', LEFT);\"\n" 3198 "onMouseOut=\"return nd();\">\n" 3199 "WPS version2 number: \n" 3200 "</th>\n" 3201 "<td> </td>\n"); 3202 str = nvram_get("wps_version2_num"); 3203 websWrite(wp,"<td><input name=\"wps_version2_num\" value=\"%s\" size=\"2\" maxlength=\"2\">\n", 3204 str ? str : ""); 3205 websWrite(wp, "</td> </tr>\n"); 3206 3207 /* WPS IE fragment threshold */ 3208 websWrite(wp,"<tr>\n" 3209 "<th width=\"310\"\n" 3210 "onMouseOver=\"return overlib('WPS version2 IE fragment threshold 72 ~ 228.', LEFT);\"\n" 3211 "onMouseOut=\"return nd();\">\n" 3212 "WPS IE fragment threshold: \n" 3213 "</th>\n" 3214 "<td> </td>\n"); 3215 str = nvram_get("wps_ie_frag"); 3216 websWrite(wp,"<td><input name=\"wps_ie_frag\" value=\"%s\" size=\"4\" maxlength=\"4\">\n", 3217 str ? str : ""); 3218 websWrite(wp, "</td> </tr>\n"); 3219 3220 /* WPS EAP fragment threshold */ 3221 websWrite(wp,"<tr>\n" 3222 "<th width=\"310\"\n" 3223 "onMouseOver=\"return overlib('WPS version2 EAP fragment threshold 100 ~ 1398.', LEFT);\"\n" 3224 "onMouseOut=\"return nd();\">\n" 3225 "WPS EAP fragment threshold: \n" 3226 "</th>\n" 3227 "<td> </td>\n"); 3228 str = nvram_get("wps_eap_frag"); 3229 websWrite(wp,"<td><input name=\"wps_eap_frag\" value=\"%s\" size=\"4\" maxlength=\"4\">\n", 3230 str ? str : ""); 3231 websWrite(wp, "</td> </tr>\n"); 3232 3233 /* Append new attribute */ 3234 websWrite(wp, "<tr>\n" 3235 "<th width=\"310\"\n" 3236 "onMouseOver=\"return overlib('Append new attribute.', LEFT);\"\n" 3237 "onMouseOut=\"return nd();\">\n" 3238 "WPS New Attribute Append: \n" 3239 "</th>\n" 3240 "<td> </td>\n"); 3241 str = nvram_get("wps_nattr"); 3242 websWrite(wp,"<td><input name=\"wps_nattr\" value=\"%s\" size=\"32\" maxlength=\"127\">\n", 3243 str ? str : ""); 3244 websWrite(wp, "</td> </tr>\n"); 3245 3246 /* Enable zero padding */ 3247 websWrite(wp, "<tr>\n" 3248 "<th width=\"310\"\n" 3249 "onMouseOver=\"return overlib('Enabled Zero Padding.', LEFT);\"\n" 3250 "onMouseOut=\"return nd();\">\n" 3251 "WPS Zero Padding: \n" 3252 "</th>\n" 3253 "<td> </td>\n" 3254 "<td>\n"); 3255 websWrite(wp, "<select name=\"wps_zpadding\">\n"); 3256 if (nvram_match("wps_zpadding", "1")) { 3257 websWrite(wp, "<option value=\"1\" selected>YES</option>\n"); 3258 websWrite(wp, "<option value=\"0\">NO</option>\n"); 3259 } 3260 else { 3261 websWrite(wp, "<option value=\"1\">YES</option>\n"); 3262 websWrite(wp, "<option value=\"0\" selected>NO</option>\n"); 3263 } 3264 websWrite(wp, "</select> </td> </tr>\n"); 3265 3266 /* Multiple Credential Attribute */ 3267 websWrite(wp, "<tr>\n" 3268 "<th width=\"310\"\n" 3269 "onMouseOver=\"return overlib('Enabled Multiple Credential Attribute.', LEFT);\"\n" 3270 "onMouseOut=\"return nd();\">\n" 3271 "WPS Multiple Credential Attribute: \n" 3272 "</th>\n" 3273 "<td> </td>\n" 3274 "<td>\n"); 3275 websWrite(wp, "<select name=\"wps_mca\">\n"); 3276 if (nvram_match("wps_mca", "1")) { 3277 websWrite(wp, "<option value=\"1\" selected>YES</option>\n"); 3278 websWrite(wp, "<option value=\"0\">NO</option>\n"); 3279 } 3280 else { 3281 websWrite(wp, "<option value=\"1\">YES</option>\n"); 3282 websWrite(wp, "<option value=\"0\" selected>NO</option>\n"); 3283 } 3284 websWrite(wp, "</select> </td> </tr>\n"); 3285 3286 /* EAP fregmant threshold */ 3287 3288 websWrite(wp, "</table>"); 3289#endif /* WFA_WPS_20_TESTBED */ 3290 3291out: 3292#endif /* __CONFIG_WPS__ */ 3293 3294 return 1; 3295} 3296 3297static int 3298ej_wps_config_change_display(int eid, webs_t wp, int argc, char_t **argv) 3299{ 3300#ifdef __CONFIG_WPS__ 3301 int wps_sta = 0; 3302 char prefix[] = "wlXXXXXXXXXX_"; 3303 char tmp[] = "wlXXXXXXXXXX_mode"; 3304 char *mode; 3305 char *closed; 3306 3307 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 3308 websError(wp, 400, "unit number variable doesn't exist\n"); 3309 return EINVAL; 3310 } 3311 3312 /* Get wl_mode */ 3313 snprintf(tmp, sizeof(tmp), "%smode", tmp); 3314 mode = nvram_safe_get(tmp); 3315 if (!strcmp(mode, "wet") || 3316 !strcmp(mode, "sta") || 3317 !strcmp(mode, "psr") || 3318 !strcmp(mode, "psta") || 3319 !strcmp(mode, "mac_spoof")) { 3320 3321 wps_sta = 1; 3322 } 3323 3324 /* Get wl_closed */ 3325 snprintf(tmp, sizeof(tmp), "%sclosed", prefix); 3326 closed = nvram_safe_get(tmp); 3327 3328 websWrite(wp," var wps_sta = \"%d\";\n", wps_sta); 3329 websWrite(wp," var wl_closed = \"%s\";\n", closed); 3330 websWrite(wp," var msg = \"Enable WPS will change the SSID Network Type to Open, Are you sure?\";\n"); 3331 3332 websWrite(wp," if ((wps_sta == \"0\") && (wl_closed == \"1\") &&\n"); 3333 websWrite(wp," (document.forms[0].wl_wps_mode.value == \"enabled\") && !confirm(msg)) {\n"); 3334 websWrite(wp," document.forms[0].wl_wps_mode.value = \"disabled\";\n"); 3335 websWrite(wp," }\n"); 3336#endif /* __CONFIG_WPS__ */ 3337 3338 return 1; 3339} 3340 3341static int 3342ej_wps_current_psk_window_display(int eid, webs_t wp, int argc, char_t **argv) 3343{ 3344#ifdef __CONFIG_WPS__ 3345 char prefix[] = "wlXXXXXXXXXX_"; 3346 char tmp[100]; 3347 char *value; 3348 3349 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 3350 websError(wp, 400, "unit number variable doesn't exist\n"); 3351 return -1; 3352 } 3353 snprintf(tmp, sizeof(tmp), "%swpa_psk", prefix); 3354 value = nvram_safe_get(tmp); 3355 3356 websWrite(wp," var psk_window = window.open(\"\", \"\", \"toolbar=no,scrollbars=yes,width=400,height=100\");\n"); 3357 websWrite(wp," psk_window.document.write(\"The WPA passphrase is %s\");\n", value); 3358 websWrite(wp," psk_window.document.close();\n"); 3359#endif /* __CONFIG_WPS__ */ 3360 return 1; 3361} 3362 3363static int 3364ej_wps_psk_window_display(int eid, webs_t wp, int argc, char_t **argv) 3365{ 3366#ifdef __CONFIG_WPS__ 3367 char prefix[] = "wlXXXXXXXXXX_"; 3368 char tmp[100], psk[65]; 3369 char *value; 3370 int oob = wps_is_oob(); 3371 3372 if (oob) { 3373 if ((value = nvram_get("wps_randomkey"))) { 3374 strncpy(random_psk, value, sizeof(random_psk)); 3375 random_psk[sizeof(random_psk)-1] = '\0'; 3376 } 3377 else if (random_psk[0] == 0) 3378 wps_gen_key(random_psk, sizeof(random_psk)); 3379 strcpy(psk, random_psk); 3380 } 3381 else { 3382 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 3383 websError(wp, 400, "unit number variable doesn't exist\n"); 3384 return -1; 3385 } 3386 snprintf(tmp, sizeof(tmp), "%swpa_psk", prefix); 3387 value = nvram_safe_get(tmp); 3388 strncpy(psk, value, sizeof(psk)); 3389 psk[sizeof(psk)-1] = '\0'; 3390 } 3391 websWrite(wp," var psk_window = window.open(\"\", \"\", \"toolbar=no,scrollbars=yes,width=400,height=100\");\n"); 3392 websWrite(wp," psk_window.document.write(\"The WPA passphrase is %s\");\n", psk); 3393 websWrite(wp," psk_window.document.close();\n"); 3394#endif /* __CONFIG_WPS__ */ 3395 return 1; 3396} 3397 3398static int 3399ej_wps_closed_check_display(int eid, webs_t wp, int argc, char_t **argv) 3400{ 3401#ifdef __CONFIG_WPS__ 3402 if (nvram_match("wl_wps_mode", "enabled")) { 3403 websWrite(wp," var msg = \"Selecting Closed hides the network will disable the WPS, Are you sure?\";\n\n"); 3404 3405 websWrite(wp," if (document.forms[0].wl_closed.value == \"1\" && !confirm(msg))\n"); 3406 websWrite(wp," document.forms[0].wl_closed.value = \"0\";\n"); 3407 } 3408#endif /* __CONFIG_WPS__ */ 3409 3410 return 1; 3411} 3412 3413 3414static int 3415ej_wps_wep_change_display(int eid, webs_t wp, int argc, char_t **argv) 3416{ 3417#ifdef __CONFIG_WPS__ 3418 websWrite(wp," var mode = document.forms[0].wl_auth_mode[document.forms[0].wl_auth_mode.selectedIndex].value;\n"); 3419 websWrite(wp," var wep = document.forms[0].wl_wep[document.forms[0].wl_wep.selectedIndex].value;\n"); 3420 websWrite(wp," var wpa = document.forms[0].wl_akm_wpa[document.forms[0].wl_akm_wpa.selectedIndex].value;\n"); 3421 websWrite(wp," var psk = document.forms[0].wl_akm_psk[document.forms[0].wl_akm_psk.selectedIndex].value;\n"); 3422 websWrite(wp," var wpa2 = document.forms[0].wl_akm_wpa2[document.forms[0].wl_akm_wpa2.selectedIndex].value;\n"); 3423 websWrite(wp," var psk2 = document.forms[0].wl_akm_psk2[document.forms[0].wl_akm_psk2.selectedIndex].value;\n"); 3424 websWrite(wp," var brcm_psk = document.forms[0].wl_akm_brcm_psk[document.forms[0].wl_akm_brcm_psk.selectedIndex].value;\n"); 3425 websWrite(wp," var wps_mode = document.forms[0].wl_wps_mode.value;\n"); 3426 websWrite(wp," var msg = \"Selecting WEP Encryption will disable the WPS, Are you sure?\";\n\n"); 3427 3428 if (nvram_match("wps_version2", "enabled")) { 3429 websWrite(wp," if (wep == \"enabled\" && wps_mode == \"enabled\" &&\n"); 3430 websWrite(wp," wpa != \"enabled\" && psk != \"enabled\" &&\n"); 3431 websWrite(wp," wpa2 != \"enabled\" && psk2 != \"enabled\" &&\n"); 3432 websWrite(wp," brcm_psk != \"enabled\" && mode != \"radius\") {\n"); 3433 websWrite(wp," if (confirm(msg))\n"); 3434 websWrite(wp," document.forms[0].wl_wps_mode.value = \"disabled\";\n"); 3435 websWrite(wp," else\n"); 3436 websWrite(wp," document.forms[0].wl_wep.selectedIndex = 1;\n"); 3437 websWrite(wp," }\n"); 3438 } 3439#endif /* __CONFIG_WPS__ */ 3440 3441 return 1; 3442} 3443 3444static int 3445ej_wps_get_ap_config_submit_display(int eid, webs_t wp, int argc, char_t **argv) 3446{ 3447#ifdef __CONFIG_WPS__ 3448 int i = 0, buf_len; 3449 char buf[256] = {0}; 3450 wps_ap_list_info_t *wpsaplist, *ap; 3451 3452 if (!scanned && nvram_match( "wl_wps_mode", "disabled" )) { 3453 wps_ap_num = 0; 3454 return 0; 3455 } 3456 else if (!scanned) 3457 wps_enr_create_aplist(); 3458 3459 websWrite(wp," var unconfig, i;\n"); 3460 websWrite(wp," var ap_index=document.forms[0].wps_ap_list.selectedIndex;\n"); 3461 websWrite(wp," var str = \"Selected AP is UNCONFIGURED! Do you want to configure it using random credential?\";\n\n"); 3462 3463 wpsaplist = ap_list; 3464 wps_enr_get_aplist(wpsaplist, wpsaplist); 3465 3466 ap = wpsaplist; 3467 while(ap->used == TRUE ) { 3468 if (ap->scstate == FALSE) { 3469 buf_len = strlen(buf); 3470 if (buf_len) 3471 sprintf(buf+buf_len, ", \"%d\"", i); 3472 else 3473 sprintf(buf+buf_len, "\"%d\"", i); 3474 } 3475 ap++; 3476 i++; 3477 } 3478 websWrite(wp," unconfig = new Array(%s);\n", buf); 3479 3480 websWrite(wp," for (var i in unconfig) {\n"); 3481 websWrite(wp," if (unconfig[i] == ap_index)\n"); 3482 websWrite(wp," return confirm(str);\n"); 3483 websWrite(wp," };\n"); 3484 websWrite(wp," return 1;\n"); 3485#endif /* __CONFIG_WPS__ */ 3486 3487 return 1; 3488} 3489 3490static int 3491ej_wps_akm_change_display(int eid, webs_t wp, int argc, char_t **argv) 3492{ 3493#ifdef __CONFIG_WPS__ 3494 if (wps_config_command == WPS_UI_CMD_NONE) { 3495 websWrite(wp," var akm = document.forms[0].wps_akm[document.forms[0].wps_akm.selectedIndex].value;\n"); 3496 websWrite(wp," var action = document.forms[0].wps_action.value;\n"); 3497 3498 websWrite(wp," if (action == \"ConfigAP\" || action == \"AddEnrollee\") {\n"); 3499 websWrite(wp," if (akm ==\"0\") {\n"); 3500 websWrite(wp," document.forms[0].wps_crypto.disabled = 1;\n"); 3501 websWrite(wp," document.forms[0].wps_crypto.value = \"0\";\n"); 3502 websWrite(wp," document.forms[0].wps_psk.disabled = 1;\n"); 3503 websWrite(wp," }\n"); 3504 websWrite(wp," else {\n"); 3505 websWrite(wp," document.forms[0].wps_crypto.disabled = 0;\n"); 3506 websWrite(wp," document.forms[0].wps_psk.disabled = 0;\n"); 3507 websWrite(wp," }\n"); 3508 websWrite(wp," }\n"); 3509 } 3510#endif /* __CONFIG_WPS__ */ 3511 return 1; 3512} 3513 3514static int 3515ej_wps_refresh(int eid, webs_t wp, int argc, char_t **argv) 3516{ 3517#ifdef __CONFIG_WPS__ 3518 if (wps_config_command == WPS_UI_CMD_NONE) 3519 websWrite(wp, "0"); 3520 else { 3521 int interval = 3; 3522 char *value = nvram_get("wps_refresh_interval"); 3523 3524 if (value) 3525 interval = atoi(value); 3526 websWrite(wp, "%d", interval); 3527 } 3528#endif 3529 return 1; 3530} 3531 3532static int 3533ej_wps_security_pre_submit_display(int eid, webs_t wp, int argc, char_t **argv) 3534{ 3535#ifdef __CONFIG_WPS__ 3536 websWrite(wp," var auth = document.forms[0].wl_auth[document.forms[0].wl_auth.selectedIndex].value;\n"); 3537 websWrite(wp," var mode = document.forms[0].wl_auth_mode[document.forms[0].wl_auth_mode.selectedIndex].value;\n"); 3538 websWrite(wp," var wep = document.forms[0].wl_wep[document.forms[0].wl_wep.selectedIndex].value;\n"); 3539 websWrite(wp," var wpa = document.forms[0].wl_akm_wpa[document.forms[0].wl_akm_wpa.selectedIndex].value;\n"); 3540 websWrite(wp," var psk = document.forms[0].wl_akm_psk[document.forms[0].wl_akm_psk.selectedIndex].value;\n"); 3541 websWrite(wp," var wpa2 = document.forms[0].wl_akm_wpa2[document.forms[0].wl_akm_wpa2.selectedIndex].value;\n"); 3542 websWrite(wp," var psk2 = document.forms[0].wl_akm_psk2[document.forms[0].wl_akm_psk2.selectedIndex].value;\n"); 3543 websWrite(wp," var brcm_psk = document.forms[0].wl_akm_brcm_psk[document.forms[0].wl_akm_brcm_psk.selectedIndex].value;\n"); 3544 websWrite(wp," var wps_mode = document.forms[0].wl_wps_mode.value;\n"); 3545 websWrite(wp," var crypto = document.forms[0].wl_crypto[document.forms[0].wl_crypto.selectedIndex].value;\n"); 3546 websWrite(wp," var open_str = \"Are you sure to configure WPS in Open security?\";\n"); 3547 websWrite(wp," var shared_str = \"WPS dose not support Shared 802.11 authentication. Are you sure to configure WPS in Shared authentication? Yes will force disable WPS.\";\n"); 3548 websWrite(wp," var psk2_str = \"WPS only support WPA2-PSK or WPA2-PSK+WPA-PSK mixed mode authentication key management. Are you sure your settings are correct? Yes will force disable WPS.\";\n"); 3549 websWrite(wp," var tkip_str = \"WPS does not support TKIP only WPA encryption. Are you sure your settings are correct? Yes will force disable WPS.\";\n"); 3550 websWrite(wp," var wep_str = \"WPS dose not support WEP encryptipon. Are you sure to configure WPS in WEP mode? Yes will force disable WPS.\";\n\n"); 3551 3552 if (nvram_match("wps_version2", "enabled")) { 3553 websWrite(wp," if (wps_mode == \"enabled\") {\n"); 3554 /* 1. Check WPS in OPEN security */ 3555 websWrite(wp," if (auth == \"0\" && wep == \"disabled\" &&\n"); 3556 websWrite(wp," wpa == \"disabled\" && psk == \"disabled\" &&\n"); 3557 websWrite(wp," wpa2 == \"disabled\" && psk2 == \"disabled\" &&\n"); 3558 websWrite(wp," brcm_psk != \"enabled\" && mode != \"radius\")\n"); 3559 websWrite(wp," return confirm(open_str);\n"); 3560 3561 /* Check Auth, deprecated "Shared" mode */ 3562 websWrite(wp," if (auth == \"1\")\n"); 3563 websWrite(wp," return confirm(shared_str);\n"); 3564 3565 /* AKM enabled checking */ 3566 websWrite(wp," if (wpa == \"enabled\" || psk == \"enabled\" || wpa2 == \"enabled\" ||psk2 == \"enabled\") {\n"); 3567 websWrite(wp," if (psk2 != \"enabled\")\n"); 3568 websWrite(wp," return confirm(psk2_str);\n"); 3569 /* WSC 2.0, Encryption type check */ 3570 websWrite(wp," if (crypto == \"tkip\")\n"); 3571 websWrite(wp," return confirm(tkip_str);\n"); 3572 websWrite(wp," }\n"); 3573 websWrite(wp," else {\n"); 3574 /* Check WEP */ 3575 websWrite(wp," if (wep == \"enabled\" &&\n"); 3576 websWrite(wp," wpa != \"enabled\" && psk != \"enabled\" &&\n"); 3577 websWrite(wp," wpa2 != \"enabled\" && psk2 != \"enabled\" &&\n"); 3578 websWrite(wp," brcm_psk != \"enabled\" && mode != \"radius\")\n"); 3579 websWrite(wp," return confirm(wep_str);\n"); 3580 websWrite(wp," }\n"); 3581 websWrite(wp," }\n"); 3582 } 3583#endif /* __CONFIG_WPS__ */ 3584 3585 return 1; 3586} 3587 3588static int 3589wl_radio_onoff(webs_t wp, int disable) 3590{ 3591 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 3592 char *name=NULL; 3593 char *interface_status=NULL; 3594 uint radiomaskval = 0; 3595 3596 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 3597 websError(wp, 400, "unit number variable doesn't exist\n"); 3598 return -1; 3599 } 3600 3601 interface_status = nvram_get(strcat_r(prefix, "radio", tmp)); 3602 3603 if (interface_status != NULL) { 3604 if (!strcmp(interface_status, "1")) { 3605 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 3606 radiomaskval = WL_RADIO_SW_DISABLE << 16 | disable; 3607 wl_ioctl(name, WLC_SET_RADIO, &radiomaskval, sizeof (disable)); 3608 } 3609 else { 3610 websWrite(wp, "Interface is not Enabled..."); 3611 return 0; 3612 } 3613 } 3614 else { 3615 websWrite(wp, "Interface status UnKnown..."); 3616 return 0; 3617 } 3618 3619 3620 return 0; 3621 3622} 3623 3624/* 3625 * Example: 3626 * lan_ipaddr=192.168.1.1 3627 * <% nvram_get("lan_ipaddr"); %> produces "192.168.1.1" 3628 * <% nvram_get("undefined"); %> produces "" 3629 */ 3630static int 3631ej_nvram_get(int eid, webs_t wp, int argc, char_t **argv) 3632{ 3633 char *name=NULL, *c=NULL; 3634 int ret = 0; 3635 3636 if (ejArgs(argc, argv, "%s", &name) < 1) { 3637 websError(wp, 400, "Insufficient args\n"); 3638 return -1; 3639 } 3640 3641 assert(name); 3642 3643 for (c = nvram_safe_get(name); *c; c++) { 3644 if (isprint((int) *c) && 3645 *c != '"' && *c != '&' && *c != '<' && *c != '>') 3646 ret += websWrite(wp, "%c", *c); 3647 else 3648 ret += websWrite(wp, "&#%d;", *c); 3649 } 3650 3651 return ret; 3652} 3653 3654#define MAX_BRIDGE_PREFIX_LEN 14 3655static int 3656ej_wl_get_bridge(int eid, webs_t wp, int argc, char_t **argv) 3657{ 3658 int mode=0; 3659 char vif[MAX_BRIDGE_PREFIX_LEN]; 3660 char *wl_bssid = NULL; 3661 char prefix[MAX_BRIDGE_PREFIX_LEN] = "wlXXXXXXXXXX_"; 3662 unsigned int len; 3663 char name[IFNAMSIZ], *next = NULL; 3664 int found = 0; 3665 /* Get the interface name */ 3666 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))) 3667 mode=1; 3668 3669 /* In case of primary interfacae, it is always LAN */ 3670 if(!mode) { 3671 websWrite(wp, "<option value=%s selected >LAN </option>\n","0" ); 3672 websWrite(wp, "<option value=%s >Guest</option>\n","1" ); 3673 return 0; 3674 3675 } 3676 3677 if (!make_wl_prefix(prefix, sizeof(prefix), mode, NULL)) { 3678 websError(wp, 400, "unit number variable doesn't exist\n"); 3679 return -1; 3680 } 3681 3682 /* interface name is prefix less the trailing '_' */ 3683 strncpy(vif, prefix,MAX_BRIDGE_PREFIX_LEN-1); 3684 vif[MAX_BRIDGE_PREFIX_LEN - 1] = '\0'; 3685 len = strlen(vif); 3686 len--; 3687 vif[len] = 0; 3688 3689 foreach(name, nvram_get("lan_ifnames"), next) { 3690 if (!strcmp(name, vif)) { 3691 found = 1; 3692 break; 3693 } 3694 } 3695 3696 if(found) { 3697 websWrite(wp, "<option value=%s selected >LAN </option>\n","0" ); 3698 websWrite(wp, "<option value=%s >Guest</option>\n","1" ); 3699 } 3700 else { 3701 websWrite(wp, "<option value=%s >LAN </option>\n","0" ); 3702 websWrite(wp, "<option value=%s selected >Guest</option>\n","1" ); 3703 } 3704 3705 return 0; 3706} 3707 3708/* 3709 * Example: 3710 * wan_proto=dhcp 3711 * <% nvram_match("wan_proto", "dhcp", "selected"); %> produces "selected" 3712 * <% nvram_match("wan_proto", "static", "selected"); %> produces "" 3713 */ 3714static int 3715ej_nvram_match(int eid, webs_t wp, int argc, char_t **argv) 3716{ 3717 char *name=NULL, *match=NULL, *output=NULL; 3718 3719 if (ejArgs(argc, argv, "%s %s %s", &name, &match, &output) < 3) { 3720 websError(wp, 400, "Insufficient args\n"); 3721 return -1; 3722 } 3723 3724 assert(name); 3725 assert(match); 3726 assert(output); 3727 3728 if (nvram_match(name, match)) 3729 return websWrite(wp, output); 3730 3731 return 0; 3732} 3733 3734/* 3735 * Example: 3736 * wl_u11en=0 3737 * <% nvram_match_bitflag("wl_hsflag", 2, "0", "selected"); %> produces "selected" 3738 * <% nvram_match_bitflag("wl_hsflag", 2, "1", "selected"); %> produces "" 3739 */ 3740static int 3741ej_nvram_match_bitflag(int eid, webs_t wp, int argc, char_t **argv) 3742{ 3743 char *name=NULL, *match=NULL, *output=NULL; 3744 int bit = 0; 3745 3746 if (ejArgs(argc, argv, "%s %d %s %s", &name, &bit, &match, &output) < 4) { 3747 websError(wp, HTTP_ERR_BAD_REQUEST, "Insufficient args\n"); 3748 return -1; 3749 } 3750 3751 assert(name); 3752 assert(match); 3753 assert(output); 3754 3755 if (nvram_match_bitflag(name, bit, match)) 3756 return websWrite(wp, output); 3757 3758 return 0; 3759} 3760 3761/* 3762 * Example: 3763 * wl_u11en=0 3764 * <% nvram_get_bitflag("wl_hsflag", 1); %> produces "1" 3765 * <% nvram_get_bitflag("wl_hsflag", 0); %> produces "" 3766 */ 3767static int 3768ej_nvram_get_bitflag(int eid, webs_t wp, int argc, char_t ** argv) 3769{ 3770 char *name = NULL; 3771 char *ptr = NULL; 3772 int bit = 0, ret = 0; 3773 3774 if (ejArgs(argc, argv, "%s %d", &name, &bit) < 2) { 3775 websError(wp, HTTP_ERR_BAD_REQUEST, "Insufficient args\n"); 3776 return -1; 3777 } 3778 3779 assert(name); 3780 ptr = nvram_get_bitflag(name, bit); 3781 ret += websWrite(wp, (ptr ? ptr : "0")); 3782 return ret; 3783} 3784 3785static int 3786wl_print_chanspec_list(webs_t wp, char *name, char *abbrev, int band, int bw) 3787{ 3788 chanspec_t c = 0, *chanspec; 3789 char *buf = (char *)malloc(WLC_IOCTL_MAXLEN); 3790 int buflen; 3791 wl_uint32_list_t *list; 3792 int ret = 0, i = 0; 3793 uint16 bandwidth = 0; 3794 3795 if (buf == NULL) { 3796 ret = -1; 3797 goto exit; 3798 } 3799 3800 strcpy(buf, "chanspecs"); 3801 buflen = strlen(buf) + 1; 3802 3803 if (band == WLC_BAND_5G) 3804 c |= WL_CHANSPEC_BAND_5G; 3805 else 3806 c |= WL_CHANSPEC_BAND_2G; 3807 3808 if (bw == 80) { 3809 c |= WL_CHANSPEC_BW_80; 3810 bandwidth = WL_CHANSPEC_BW_80; 3811 } else if (bw == 40) { 3812 c |= WL_CHANSPEC_BW_40; 3813 bandwidth = WL_CHANSPEC_BW_40; 3814 } else { 3815 c |= WL_CHANSPEC_BW_20; 3816 bandwidth = WL_CHANSPEC_BW_20; 3817 } 3818 3819 chanspec = (chanspec_t *)(buf + buflen); 3820 *chanspec = c; 3821 buflen += (sizeof(chanspec_t)); 3822 strncpy(buf + buflen, abbrev, WLC_CNTRY_BUF_SZ); 3823 buflen += WLC_CNTRY_BUF_SZ; 3824 3825 /* Add list */ 3826 list = (wl_uint32_list_t *)(buf + buflen); 3827 list->count = WL_NUMCHANSPECS; 3828 buflen += sizeof(uint32)*(WL_NUMCHANSPECS + 1); 3829 3830 ret = wl_ioctl(name, WLC_GET_VAR, buf, buflen); 3831 if (ret < 0) { 3832 goto exit; 3833 } 3834 3835 list = (wl_uint32_list_t *)buf; 3836 3837 if (list->count > 0) { 3838 websWrite(wp, "\t\tif (country == \"%s\")\n\t\t\tchanspecs = new Array(\"0\"", abbrev); 3839 for (i = 0; i < list->count; i++) { 3840 char chanbuf[CHANSPEC_STR_LEN]; 3841 3842 c = (chanspec_t) list->element[i]; 3843 3844 if (bandwidth && CHSPEC_BW(c) != bandwidth) 3845 continue; 3846 3847 websWrite(wp, ", \"%s\"", wf_chspec_ntoa(c, chanbuf)); 3848 } 3849 websWrite(wp, ");\n"); 3850 } else { 3851 websWrite(wp, "\t\tif (country == \"%s\")\n\t\t\tchanspecs = new Array(\"N/A\");\n", abbrev); 3852 } 3853 3854exit: 3855 if (buf) 3856 free(buf); 3857 3858 return ret; 3859} 3860 3861static int 3862ej_wl_country_list(int eid, webs_t wp, int argc, char_t **argv) 3863{ 3864 int i =0, status = 0; 3865 char *name =NULL; 3866 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 3867 char *phytype = NULL; 3868 wl_country_list_t *cl = (wl_country_list_t *)malloc(WLC_IOCTL_MAXLEN); 3869 country_name_t *cntry=NULL; 3870 char *abbrev=NULL; 3871 int band = WLC_BAND_ALL, cur_phytype; 3872 3873 if (!cl) { 3874 status = -1; 3875 goto exit; 3876 } 3877 3878 if (ejArgs(argc, argv, "%s %d", &phytype, &band) < 1) { 3879 websError(wp, 400, "Insufficient args\n"); 3880 status = -1; 3881 goto exit; 3882 } 3883 3884 assert(phytype); 3885 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 3886 websError(wp, 400, "unit number variable doesn't exist\n"); 3887 status = -1; 3888 goto exit; 3889 } 3890 3891 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 3892 3893 /* Get configured phy type */ 3894 wl_ioctl(name, WLC_GET_PHYTYPE, &cur_phytype, sizeof(cur_phytype)); 3895 3896 cl->buflen = WLC_IOCTL_MAXLEN; 3897 cl->band_set = TRUE; 3898 3899 if (!strcmp(phytype, "a") && 3900 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 3901 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 3902 (cur_phytype != WLC_PHY_TYPE_AC)) { 3903 cl->band = WLC_BAND_5G; 3904 } else if (((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) && 3905 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 3906 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 3907 (cur_phytype != WLC_PHY_TYPE_AC)) { 3908 cl->band = WLC_BAND_2G; 3909 } else if ((!strcmp(phytype, "n") || !strcmp(phytype, "s") || !strcmp(phytype, "h") || !strcmp(phytype, "v")) && 3910 ((cur_phytype == WLC_PHY_TYPE_N) || (cur_phytype == WLC_PHY_TYPE_SSN) || 3911 (cur_phytype == WLC_PHY_TYPE_LCN) || (cur_phytype == WLC_PHY_TYPE_HT) || 3912 (cur_phytype == WLC_PHY_TYPE_AC))) { 3913 /* Need to have additional argument of the band */ 3914 if (argc < 2 || (band != WLC_BAND_2G && band != WLC_BAND_5G)) { 3915 status = -1; 3916 goto exit; 3917 } 3918 cl->band = band; 3919 } else if ((!strcmp(phytype, "l")) && (cur_phytype == WLC_PHY_TYPE_LP)) { 3920 wl_ioctl(name, WLC_GET_BAND, &band, sizeof(band)); 3921 cl->band = band; 3922 } else { 3923 status = -1; 3924 goto exit; 3925 } 3926 3927 if (wl_ioctl(name, WLC_GET_COUNTRY_LIST, cl, cl->buflen) == 0) { 3928 websWrite(wp, "\t\tvar countries = new Array("); 3929 for(i = 0; i < cl->count; i++) { 3930 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 3931 websWrite(wp, "\"%s\"", abbrev); 3932 if (i != (cl->count - 1)) 3933 websWrite(wp, ", "); 3934 } 3935 websWrite(wp, ");\n"); 3936 for(i = 0; i < cl->count; i++) { 3937 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 3938 for(cntry = country_names; 3939 cntry->name && strcmp(abbrev, cntry->abbrev); 3940 cntry++); 3941 websWrite(wp, "\t\tdocument.forms[0].wl_country_code[%d] = new Option(\"%s\", \"%s\");\n", 3942 i, cntry->name ? cntry->name : abbrev, abbrev); 3943 } 3944 } 3945 3946exit: 3947 if (cl) 3948 free((void *)cl); 3949 return status; 3950} 3951 3952static int 3953wl_print_country_rev_list(webs_t wp, char *name, char *abbrev) 3954{ 3955 char *buf = (char *)malloc(WLC_IOCTL_MAXLEN); 3956 int buflen; 3957 wl_uint32_list_t *list; 3958 int ret = 0, i = 0, c = 0; 3959 3960 if (buf == NULL) 3961 return -1; 3962 3963 strcpy(buf, "country_rev"); 3964 buflen = strlen(buf) + 1; 3965 3966 strncpy(buf + buflen, abbrev, WLC_CNTRY_BUF_SZ); 3967 buflen += WLC_CNTRY_BUF_SZ; 3968 3969 /* Add list */ 3970 list = (wl_uint32_list_t *)(buf + buflen); 3971 list->count = WLC_IOCTL_SMLEN; 3972 buflen += sizeof(uint32)*(WLC_IOCTL_SMLEN + 1); 3973 3974 ret = wl_ioctl(name, WLC_GET_VAR, buf, buflen); 3975 if (ret < 0) 3976 goto exit; 3977 3978 list = (wl_uint32_list_t *)buf; 3979 3980 if (list->count == 0) { 3981 ret = 0; 3982 goto exit; 3983 } 3984 3985 websWrite(wp, "\t\tif (country == \"%s\")\n\t\t\tcountry_revs = new Array(", 3986 abbrev); 3987 for (i = 0; i < list->count; i++) { 3988 c = list->element[i]; 3989 websWrite(wp, "\"%d\"", c); 3990 if (i != (list->count - 1)) 3991 websWrite(wp, ", "); 3992 } 3993 websWrite(wp,");\n"); 3994 3995exit: 3996 free((void *)buf); 3997 return ret; 3998} 3999 4000static int 4001ej_wl_country_rev_list(int eid, webs_t wp, int argc, char_t **argv) 4002{ 4003 /* country_rev from 0 to 99 */ 4004 int i =0, status = 0; 4005 char *name =NULL; 4006 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 4007 char *phytype = NULL; 4008 wl_country_list_t *cl = (wl_country_list_t *)malloc(WLC_IOCTL_MAXLEN); 4009 char *abbrev=NULL; 4010 int band = WLC_BAND_ALL, cur_phytype; 4011 4012 if (!cl) { 4013 status = -1; 4014 goto exit; 4015 } 4016 4017 if (ejArgs(argc, argv, "%s %d", &phytype, &band) < 1) { 4018 websError(wp, 400, "Insufficient args\n"); 4019 status = -1; 4020 goto exit; 4021 } 4022 4023 assert(phytype); 4024 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 4025 websError(wp, 400, "unit number variable doesn't exist\n"); 4026 status = -1; 4027 goto exit; 4028 } 4029 4030 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 4031 4032 /* Get configured phy type */ 4033 wl_ioctl(name, WLC_GET_PHYTYPE, &cur_phytype, sizeof(cur_phytype)); 4034 4035 cl->buflen = WLC_IOCTL_MAXLEN; 4036 cl->band_set = TRUE; 4037 4038 if (!strcmp(phytype, "a") && 4039 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 4040 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 4041 (cur_phytype != WLC_PHY_TYPE_AC)) { 4042 cl->band = WLC_BAND_5G; 4043 } else if (((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) && 4044 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 4045 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 4046 (cur_phytype != WLC_PHY_TYPE_AC)) { 4047 cl->band = WLC_BAND_2G; 4048 } else if ((!strcmp(phytype, "n") || !strcmp(phytype, "s") || !strcmp(phytype, "h") || 4049 !strcmp(phytype, "v")) && 4050 ((cur_phytype == WLC_PHY_TYPE_N) || (cur_phytype == WLC_PHY_TYPE_SSN) || 4051 (cur_phytype == WLC_PHY_TYPE_LCN) || (cur_phytype == WLC_PHY_TYPE_HT) || 4052 (cur_phytype == WLC_PHY_TYPE_AC))) { 4053 /* Need to have additional argument of the band */ 4054 if (argc < 2 || (band != WLC_BAND_2G && band != WLC_BAND_5G)) { 4055 status = -1; 4056 goto exit; 4057 } 4058 cl->band = band; 4059 } else if ((!strcmp(phytype, "l")) && (cur_phytype == WLC_PHY_TYPE_LP)) { 4060 wl_ioctl(name, WLC_GET_BAND, &band, sizeof(band)); 4061 cl->band = band; 4062 } else { 4063 status = -1; 4064 goto exit; 4065 } 4066 4067 if (wl_ioctl(name, WLC_GET_COUNTRY_LIST, cl, cl->buflen) == 0) { 4068 for(i = 0; i < cl->count; i++) { 4069 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 4070 wl_print_country_rev_list(wp, name, abbrev); 4071 } 4072 } 4073 4074exit: 4075 if (cl) 4076 free((void *)cl); 4077 return status; 4078 4079} 4080 4081static int 4082ej_wl_chanspec_list(int eid, webs_t wp, int argc, char_t **argv) 4083{ 4084 int i, status = 0; 4085 char *name=NULL; 4086 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 4087 char *phytype = NULL; 4088 int cur_phytype; 4089 wl_country_list_t *cl = (wl_country_list_t *)malloc(WLC_IOCTL_MAXLEN); 4090 char *abbrev=NULL; 4091 int band = WLC_BAND_ALL; 4092 int bw = 0; 4093 4094 if (!cl) { 4095 status = -1; 4096 goto exit; 4097 } 4098 4099 if (ejArgs(argc, argv, "%s %d %d", &phytype, &band, &bw) < 1) { 4100 websError(wp, 400, "Insufficient args\n"); 4101 status = -1; 4102 goto exit; 4103 } 4104 4105 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 4106 websError(wp, 400, "unit number variable doesn't exist\n"); 4107 status = -1; 4108 goto exit; 4109 } 4110 4111 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 4112 4113 /* Get configured phy type */ 4114 wl_ioctl(name, WLC_GET_PHYTYPE, &cur_phytype, sizeof(cur_phytype)); 4115 4116 cl->buflen = WLC_IOCTL_MAXLEN; 4117 cl->band_set = TRUE; 4118 4119 if (!strcmp(phytype, "a") && 4120 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 4121 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 4122 (cur_phytype != WLC_PHY_TYPE_AC)) { 4123 cl->band = WLC_BAND_5G; 4124 } else if (((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) && 4125 (cur_phytype != WLC_PHY_TYPE_N) && (cur_phytype != WLC_PHY_TYPE_SSN) && 4126 (cur_phytype != WLC_PHY_TYPE_LCN) && (cur_phytype != WLC_PHY_TYPE_HT) && 4127 (cur_phytype != WLC_PHY_TYPE_AC)) { 4128 cl->band = WLC_BAND_2G; 4129 } else if ((!strcmp(phytype, "l")) && (cur_phytype == WLC_PHY_TYPE_LP)) { 4130 wl_ioctl(name, WLC_GET_BAND, &band, sizeof(band)); 4131 cl->band = band; 4132 } else if ((!strcmp(phytype, "n") || !strcmp(phytype, "s") || !strcmp(phytype, "h") || !strcmp(phytype, "v")) && 4133 ((cur_phytype == WLC_PHY_TYPE_N) || (cur_phytype == WLC_PHY_TYPE_SSN) || 4134 (cur_phytype == WLC_PHY_TYPE_LCN) || (cur_phytype == WLC_PHY_TYPE_HT) || 4135 (cur_phytype == WLC_PHY_TYPE_AC))) { 4136 /* Need to have additional argument of the band */ 4137 if (argc < 2 || (band != WLC_BAND_2G && band != WLC_BAND_5G)) { 4138 status = -1; 4139 goto exit; 4140 } 4141 cl->band = band; 4142 } else { 4143 status = -1; 4144 goto exit; 4145 } 4146 4147 band = cl->band; 4148 4149 if (wl_ioctl(name, WLC_GET_COUNTRY_LIST, cl, cl->buflen) == 0) { 4150 for (i = 0; i < cl->count; i++) { 4151 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 4152 wl_print_chanspec_list(wp, name, abbrev, band, bw); 4153 } 4154 } 4155 4156exit: 4157 if (cl) 4158 free(cl); 4159 4160 return status; 4161} 4162 4163/* Output one row of the HTML authenticated STA list table */ 4164static void 4165auth_list_sta(webs_t wp, char *name, struct ether_addr *ea) 4166{ 4167 char buf[sizeof(sta_info_t)]; 4168 4169 assert(sizeof (buf) >= sizeof (sta_info_t)); 4170 strcpy(buf, "sta_info"); 4171 memcpy(buf + strlen(buf) + 1, (unsigned char *)ea, ETHER_ADDR_LEN); 4172 4173 if (!wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))) { 4174 char ea_str[ETHER_ADDR_STR_LEN]; 4175 sta_info_t *sta = (sta_info_t *)buf; 4176 uint32 f = sta->flags; 4177 4178 websWrite(wp, "<td>%s</td>", ether_etoa((unsigned char *)ea, ea_str)); 4179 websWrite(wp, "<td>%s</td>", (f & WL_STA_ASSOC) ? reltime_short(sta->in) : "-"); 4180 websWrite(wp, "<td>%s</td>", (f & WL_STA_AUTHO) ? "Yes" : "No"); 4181 websWrite(wp, "<td>%s</td>", (f & WL_STA_WME) ? "Yes" : "No"); 4182 websWrite(wp, "<td>%s</td>", (f & WL_STA_PS) ? "Yes" : "No"); 4183 websWrite(wp, "<td>%s%s%s%s </td>", 4184 (f & WL_STA_APSD_BE) ? "BE " : "", 4185 (f & WL_STA_APSD_BK) ? "BK " : "", 4186 (f & WL_STA_APSD_VI) ? "VI " : "", 4187 (f & WL_STA_APSD_VO) ? "VO " : ""); 4188 } 4189} 4190 4191static int 4192ej_wl_auth_list(int eid, webs_t wp, int argc, char_t **argv) 4193{ 4194 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 4195 char *name; 4196 struct maclist *mac_list; 4197 int mac_list_size; 4198 int i; 4199 char *wl_bssid = NULL; 4200 int mode = 0; 4201 4202 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))) 4203 mode=1; 4204 4205 if (!make_wl_prefix(prefix, sizeof(prefix), mode, NULL)) { 4206 websError(wp, 400, "unit number variable doesn't exist\n"); 4207 return -1; 4208 } 4209 4210 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 4211 4212 /* buffers and length */ 4213 mac_list_size = sizeof(mac_list->count) + MAX_STA_COUNT * sizeof(struct ether_addr); 4214 mac_list = malloc(mac_list_size); 4215 4216 if (!mac_list) 4217 return -1; 4218 4219 /* query wl for authenticated sta list */ 4220#ifndef __NetBSD__ 4221 strcpy((char*)mac_list, "authe_sta_list"); 4222 if (wl_ioctl(name, WLC_GET_VAR, mac_list, mac_list_size)) { 4223 free(mac_list); 4224 return -1; 4225 } 4226#else 4227 /* NetBSD TBD... */ 4228 mac_list->count=0; 4229#endif 4230 4231 /* query sta_info for each STA and output one table row each */ 4232 for (i = 0; i < mac_list->count; i++) { 4233 websWrite(wp, "<tr align=\"center\">"); 4234 auth_list_sta(wp, name, &mac_list->ea[i]); 4235 websWrite(wp, "</tr>"); 4236 } 4237 4238 free(mac_list); 4239 4240 return 0; 4241} 4242 4243/* 4244 * Example: 4245 * wan_proto=dhcp 4246 * <% nvram_invmatch("wan_proto", "dhcp", "disabled"); %> produces "" 4247 * <% nvram_invmatch("wan_proto", "static", "disabled"); %> produces "disabled" 4248 */ 4249static int 4250ej_nvram_invmatch(int eid, webs_t wp, int argc, char_t **argv) 4251{ 4252 char *name=NULL, *invmatch=NULL, *output=NULL; 4253 4254 if (ejArgs(argc, argv, "%s %s %s", &name, &invmatch, &output) < 3) { 4255 websError(wp, 400, "Insufficient args\n"); 4256 return -1; 4257 } 4258 4259 assert(name); 4260 assert(invmatch); 4261 assert(output); 4262 4263 if (nvram_invmatch(name, invmatch)) 4264 return websWrite(wp, output); 4265 4266 return 0; 4267} 4268 4269/* 4270 * Example: 4271 * filter_maclist=00:12:34:56:78:00 00:87:65:43:21:00 4272 * <% nvram_list("filter_maclist", 1); %> produces "00:87:65:43:21:00" 4273 * <% nvram_list("filter_maclist", 100); %> produces "" 4274 */ 4275static int 4276ej_nvram_list(int eid, webs_t wp, int argc, char_t **argv) 4277{ 4278 char *name=NULL; 4279 int which=0; 4280 char word[256], *next=NULL; 4281 4282 if (ejArgs(argc, argv, "%s %d", &name, &which) < 2) { 4283 websError(wp, 400, "Insufficient args\n"); 4284 return -1; 4285 } 4286 4287 foreach(word, nvram_safe_get(name), next) { 4288 if (which-- == 0) 4289 return websWrite(wp, word); 4290 } 4291 4292 return 0; 4293} 4294 4295static int 4296ej_nvram_inlist(int eid, webs_t wp, int argc, char_t **argv) 4297{ 4298 char *name, *item, *output; 4299 char word[256], *next; 4300 4301 if (ejArgs(argc, argv, "%s %s %s", &name, &item, &output) < 3) { 4302 websError(wp, 400, "Insufficient args\n"); 4303 return -1; 4304 } 4305 4306 foreach(word, nvram_safe_get(name), next) { 4307 if (!strcmp(word, item)) 4308 return websWrite(wp, output); 4309 } 4310 4311 return 0; 4312} 4313 4314static int 4315ej_nvram_invinlist(int eid, webs_t wp, int argc, char_t **argv) 4316{ 4317 char *name, *item, *output; 4318 char word[256], *next; 4319 4320 if (ejArgs(argc, argv, "%s %s %s", &name, &item, &output) < 3) { 4321 websError(wp, 400, "Insufficient args\n"); 4322 return -1; 4323 } 4324 4325 foreach(word, nvram_safe_get(name), next) { 4326 if (!strcmp(word, item)) 4327 return 0; 4328 } 4329 4330 return websWrite(wp, output); 4331} 4332 4333/* 4334 * Example: 4335 * wme_ap_bk=15 1023 7 0 0 on off 4336 * <% nvram_indexmatch("wme_ap_bk", 5, "on", "selected"); %> produces "selected" 4337 * <% nvram_indexmatch("wme_ap_bk", 6, "on", "selected"); %> produces "" 4338 */ 4339static int 4340ej_nvram_indexmatch(int eid, webs_t wp, int argc, char_t **argv) 4341{ 4342 char *name = NULL, *match = NULL, *output = NULL; 4343 char word[256], *next; 4344 int index; 4345 4346 if (ejArgs(argc, argv, "%s %d %s %s", &name, &index, &match, &output) < 3) { 4347 websError(wp, 400, "Insufficient args\n"); 4348 return -1; 4349 } 4350 4351 assert(name); 4352 assert(match); 4353 assert(output); 4354 4355 foreach(word, nvram_safe_get(name), next) 4356 if (index-- == 0 && !strcmp(word, match)) 4357 return websWrite(wp, output); 4358 4359 return 0; 4360} 4361 4362#ifdef __CONFIG_NAT__ 4363/* 4364 * Example: 4365 * <% filter_client(1, 10); %> produces a table of the first 10 client filter entries 4366 */ 4367static int 4368ej_filter_client(int eid, webs_t wp, int argc, char_t **argv) 4369{ 4370 int i, n, j, ret = 0; 4371 netconf_filter_t start, end; 4372 bool valid; 4373 char port[] = "XXXXX"; 4374 char *days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; 4375 char *hours[] = { 4376 "12:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", 4377 "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", 4378 "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", 4379 "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM" 4380 }; 4381 4382 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 4383 websError(wp, 400, "Insufficient args\n"); 4384 return -1; 4385 } 4386 4387 for (; i <= n; i++) { 4388 valid = get_filter_client(i, &start, &end); 4389 4390 ret += websWrite(wp, "<tr>"); 4391 ret += websWrite(wp, "<td></td>"); 4392 4393 /* Print address range */ 4394 ret += websWrite(wp, "<td><input name=\"filter_client_from_start%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 4395 i, valid ? inet_ntoa(start.match.src.ipaddr) : ""); 4396 ret += websWrite(wp, "<td>-</td>"); 4397 ret += websWrite(wp, "<td><input name=\"filter_client_from_end%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 4398 i, valid ? inet_ntoa(end.match.src.ipaddr) : ""); 4399 ret += websWrite(wp, "<td></td>"); 4400 4401 /* Print protocol */ 4402 ret += websWrite(wp, "<td>"); 4403 ret += websWrite(wp, "<select name=\"filter_client_proto%d\">", i); 4404 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 4405 valid && start.match.ipproto == IPPROTO_TCP ? "selected" : ""); 4406 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 4407 valid && start.match.ipproto == IPPROTO_UDP ? "selected" : ""); 4408 ret += websWrite(wp, "</select>"); 4409 ret += websWrite(wp, "</td>"); 4410 ret += websWrite(wp, "<td></td>"); 4411 4412 /* Print port range */ 4413 if (valid) 4414 snprintf(port, sizeof(port), "%d", ntohs(start.match.dst.ports[0])); 4415 else 4416 *port = '\0'; 4417 ret += websWrite(wp, "<td><input name=\"filter_client_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4418 i, port); 4419 ret += websWrite(wp, "<td>-</td>"); 4420 if (valid) 4421 snprintf(port, sizeof(port), "%d", ntohs(start.match.dst.ports[1])); 4422 else 4423 *port = '\0'; 4424 ret += websWrite(wp, "<td><input name=\"filter_client_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4425 i, port); 4426 ret += websWrite(wp, "<td></td>"); 4427 4428 /* Print day range */ 4429 ret += websWrite(wp, "<td>"); 4430 ret += websWrite(wp, "<select name=\"filter_client_from_day%d\">", i); 4431 for (j = 0; j < ARRAYSIZE(days); j++) 4432 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 4433 j, valid && start.match.days[0] == j ? "selected" : "", days[j]); 4434 ret += websWrite(wp, "</select>"); 4435 ret += websWrite(wp, "</td>"); 4436 ret += websWrite(wp, "<td>-</td>"); 4437 ret += websWrite(wp, "<td>"); 4438 ret += websWrite(wp, "<select name=\"filter_client_to_day%d\">", i); 4439 for (j = 0; j < ARRAYSIZE(days); j++) 4440 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 4441 j, valid && start.match.days[1] == j ? "selected" : "", days[j]); 4442 ret += websWrite(wp, "</select>"); 4443 ret += websWrite(wp, "</td>"); 4444 ret += websWrite(wp, "<td></td>"); 4445 4446 /* Print time range */ 4447 ret += websWrite(wp, "<td>"); 4448 ret += websWrite(wp, "<select name=\"filter_client_from_sec%d\">", i); 4449 for (j = 0; j < ARRAYSIZE(hours); j++) 4450 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 4451 j * 3600, valid && start.match.secs[0] == (j * 3600) ? "selected" : "", hours[j]); 4452 ret += websWrite(wp, "</select>"); 4453 ret += websWrite(wp, "</td>"); 4454 ret += websWrite(wp, "<td>-</td>"); 4455 4456 ret += websWrite(wp, "<td>"); 4457 ret += websWrite(wp, "<select name=\"filter_client_to_sec%d\">", i); 4458 for (j = 0; j < ARRAYSIZE(hours); j++) 4459 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 4460 j * 3600, valid && start.match.secs[1] == (j * 3600) ? "selected" : "", hours[j]); 4461 /* Special case for 11:59:59 PM */ 4462 ret += websWrite(wp, "<option value=\"%d\" %s>12:00 AM</option>", 4463 24 * 3600 - 1, valid && start.match.secs[1] == (24 * 3600 - 1) ? "selected" : ""); 4464 ret += websWrite(wp, "</select>"); 4465 ret += websWrite(wp, "</td>"); 4466 ret += websWrite(wp, "<td></td>"); 4467 4468 /* Print enable */ 4469 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"filter_client_enable%d\" %s></td>", 4470 i, valid && !(start.match.flags & NETCONF_DISABLED) ? "checked" : ""); 4471 4472 ret += websWrite(wp, "</tr>"); 4473 } 4474 4475 return ret; 4476} 4477 4478/* 4479 * Example: 4480 * <% filter_url(1, 10); %> produces a table of the first 10 client filter entries 4481 */ 4482static int 4483ej_filter_url(int eid, webs_t wp, int argc, char_t **argv) 4484{ 4485 int ret = 0; 4486 4487#ifdef __CONFIG_URLFILTER__ 4488 int i, n; 4489 netconf_urlfilter_t start, end; 4490 bool valid; 4491 4492 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 4493 websError(wp, 400, "Insufficient args\n"); 4494 return -1; 4495 } 4496 4497 /* Start of table */ 4498 ret += websWrite(wp, "<p>"); 4499 ret += websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"); 4500 ret += websWrite(wp, "<tr>"); 4501 ret += websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"11\" "); 4502 ret += websWrite(wp, "onMouseOver="); 4503 ret += websWrite(wp, 4504 "\"return overlib('Filter packets from IP addresses destined to certain URL.', LEFT);\" "); 4505 ret += websWrite(wp, "onMouseOut=\"return nd();\">"); 4506 ret += websWrite(wp, "<input type=\"hidden\" name=\"filter_url\" value=\"10\">"); 4507 ret += websWrite(wp, "URL Filters: "); 4508 ret += websWrite(wp, "</th>"); 4509 ret += websWrite(wp, "<td> </td>"); 4510 ret += websWrite(wp, "<td class=\"label\" colspan=\"3\">LAN IP Address Range</td>"); 4511 ret += websWrite(wp, "<td> </td>"); 4512 ret += websWrite(wp, "<td class=\"label\">URL filter string</td>"); 4513 ret += websWrite(wp, "<td class=\"label\">Enabled</td>"); 4514 ret += websWrite(wp, "</tr>"); 4515 4516 /* Entries */ 4517 for (; i <= n; i++) { 4518 valid = get_filter_url(i, &start, &end); 4519 4520 ret += websWrite(wp, "<tr>"); 4521 ret += websWrite(wp, "<td></td>"); 4522 4523 /* Print address range */ 4524 ret += websWrite(wp, "<td><input name=\"filter_url_from_start%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 4525 i, valid ? inet_ntoa(start.match.src.ipaddr) : ""); 4526 ret += websWrite(wp, "<td>-</td>"); 4527 ret += websWrite(wp, "<td><input name=\"filter_url_from_end%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 4528 i, valid ? inet_ntoa(end.match.src.ipaddr) : ""); 4529 ret += websWrite(wp, "<td></td>"); 4530 4531 /* Print URL string */ 4532 ret += websWrite(wp, "<td><input name=\"filter_url_addr%d\" value=\"%s\" size=\"40\" maxlength=\"128\"></td>", 4533 i, valid ? start.url : ""); 4534 4535 /* Print enable */ 4536 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"filter_url_enable%d\" %s></td>", 4537 i, valid && !(start.match.flags & NETCONF_DISABLED) ? "checked" : ""); 4538 4539 ret += websWrite(wp, "</tr>"); 4540 } 4541 4542 /* End of table */ 4543 ret += websWrite(wp, "</table>"); 4544#endif /* __CONFIG_URLFILTER__ */ 4545 4546 return ret; 4547} 4548 4549/* 4550 * Example: 4551 * <% forward_port(1, 10); %> produces a table of the first 10 port forward entries 4552 */ 4553static int 4554ej_forward_port(int eid, webs_t wp, int argc, char_t **argv) 4555{ 4556 int i, n, ret = 0; 4557 netconf_nat_t nat; 4558 bool valid; 4559 char port[] = "XXXXX"; 4560 4561 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 4562 websError(wp, 400, "Insufficient args\n"); 4563 return -1; 4564 } 4565 4566 for (; i <= n; i++) { 4567 valid = get_forward_port(i, &nat); 4568 4569 ret += websWrite(wp, "<tr>"); 4570 ret += websWrite(wp, "<td></td>"); 4571 4572 /* Print protocol */ 4573 ret += websWrite(wp, "<td>"); 4574 ret += websWrite(wp, "<select name=\"forward_port_proto%d\">", i); 4575 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 4576 valid && nat.match.ipproto == IPPROTO_TCP ? "selected" : ""); 4577 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 4578 valid && nat.match.ipproto == IPPROTO_UDP ? "selected" : ""); 4579 ret += websWrite(wp, "</select>"); 4580 ret += websWrite(wp, "</td>"); 4581 ret += websWrite(wp, "<td></td>"); 4582 4583 /* Print WAN destination port range */ 4584 if (valid) 4585 snprintf(port, sizeof(port), "%d", ntohs(nat.match.dst.ports[0])); 4586 else 4587 *port = '\0'; 4588 ret += websWrite(wp, "<td><input name=\"forward_port_from_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4589 i, port); 4590 ret += websWrite(wp, "<td>-</td>"); 4591 if (valid) 4592 snprintf(port, sizeof(port), "%d", ntohs(nat.match.dst.ports[1])); 4593 else 4594 *port = '\0'; 4595 ret += websWrite(wp, "<td><input name=\"forward_port_from_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4596 i, port); 4597 ret += websWrite(wp, "<td>></td>"); 4598 4599 /* Print address range */ 4600 ret += websWrite(wp, "<td><input name=\"forward_port_to_ip%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 4601 i, valid ? inet_ntoa(nat.ipaddr) : ""); 4602 ret += websWrite(wp, "<td>:</td>"); 4603 4604 /* Print LAN destination port range */ 4605 if (valid) 4606 snprintf(port, sizeof(port), "%d", ntohs(nat.ports[0])); 4607 else 4608 *port = '\0'; 4609 ret += websWrite(wp, "<td><input name=\"forward_port_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4610 i, port); 4611 ret += websWrite(wp, "<td>-</td>"); 4612 if (valid) 4613 snprintf(port, sizeof(port), "%d", ntohs(nat.ports[1])); 4614 else 4615 *port = '\0'; 4616 ret += websWrite(wp, "<td><input name=\"forward_port_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4617 i, port); 4618 ret += websWrite(wp, "<td></td>"); 4619 4620 /* Print enable */ 4621 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"forward_port_enable%d\" %s></td>", 4622 i, valid && !(nat.match.flags & NETCONF_DISABLED) ? "checked" : ""); 4623 4624 ret += websWrite(wp, "</tr>"); 4625 } 4626 4627 return ret; 4628} 4629 4630static int 4631ej_autofw_port_display(int eid, webs_t wp, int argc, char_t **argv) 4632{ 4633 int ret = 0; 4634 4635#if !defined(AUTOFW_PORT_DEPRECATED) 4636 int i, n; 4637 netconf_app_t app; 4638 bool valid; 4639 char port[] = "XXXXX"; 4640 4641 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 4642 websError(wp, 400, "Insufficient args\n"); 4643 return -1; 4644 } 4645 4646 /* Display table layout */ 4647 ret += websWrite(wp, "<p>\n"); 4648 ret += websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n"); 4649 ret += websWrite(wp, "<tr>\n"); 4650 ret += websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"11\" onMouseOver=\"return overlib('Automatically forward connections.', LEFT);\" onMouseOut=\"return nd();\">\n"); 4651 ret += websWrite(wp, "<input type=\"hidden\" name=\"autofw_port\" value=\"5\">Application Specific Port Forwards: \n"); 4652 ret += websWrite(wp, "</th>\n"); 4653 ret += websWrite(wp, "<td> </td>\n"); 4654 ret += websWrite(wp, "<td class=\"label\">Outbound<br>Protocol</td>\n"); 4655 ret += websWrite(wp, "<td> </td>\n"); 4656 ret += websWrite(wp, "<td class=\"label\">Outbound<br>Port Start</td>\n"); 4657 ret += websWrite(wp, "<td> </td>\n"); 4658 ret += websWrite(wp, "<td class=\"label\">Outbound<br>Port End</td>\n"); 4659 ret += websWrite(wp, "<td> </td>\n"); 4660 ret += websWrite(wp, "<td class=\"label\">Inbound<br>Protocol</td>\n"); 4661 ret += websWrite(wp, "<td> </td>\n"); 4662 ret += websWrite(wp, "<td class=\"label\">Inbound<br>Port Start</td>\n"); 4663 ret += websWrite(wp, "<td></td>\n"); 4664 ret += websWrite(wp, "<td class=\"label\">Inbound<br>Port End</td>\n"); 4665 ret += websWrite(wp, "<td> </td>\n"); 4666 ret += websWrite(wp, "<td class=\"label\">To<br>Port Start</td>\n"); 4667 ret += websWrite(wp, "<td></td>\n"); 4668 ret += websWrite(wp, "<td class=\"label\">To<br>Port End</td>\n"); 4669 ret += websWrite(wp, "<td> </td>\n"); 4670 ret += websWrite(wp, "<td class=\"label\">Enabled</td>\n"); 4671 ret += websWrite(wp, "</tr>\n"); 4672 4673 for (; i <= n; i++) { 4674 valid = get_autofw_port(i, &app); 4675 4676 /* Parse out_proto:out_port,in_proto:in_start-in_end>to_start-to_end,enable,desc */ 4677 ret += websWrite(wp, "<tr>"); 4678 ret += websWrite(wp, "<td></td>"); 4679 4680 /* Print outbound protocol */ 4681 ret += websWrite(wp, "<td>"); 4682 ret += websWrite(wp, "<select name=\"autofw_port_out_proto%d\">", i); 4683 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 4684 valid && app.match.ipproto == IPPROTO_TCP ? "selected" : ""); 4685 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 4686 valid && app.match.ipproto == IPPROTO_UDP ? "selected" : ""); 4687 ret += websWrite(wp, "</select>"); 4688 ret += websWrite(wp, "</td>"); 4689 ret += websWrite(wp, "<td></td>"); 4690 4691 /* Print outbound port */ 4692 if (valid) 4693 snprintf(port, sizeof(port), "%d", ntohs(app.match.dst.ports[0])); 4694 else 4695 *port = '\0'; 4696 ret += websWrite(wp, "<td><input name=\"autofw_port_out_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4697 i, port); 4698 ret += websWrite(wp, "<td>-</td>"); 4699 if (valid) 4700 snprintf(port, sizeof(port), "%d", ntohs(app.match.dst.ports[1])); 4701 else 4702 *port = '\0'; 4703 ret += websWrite(wp, "<td><input name=\"autofw_port_out_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4704 i, port); 4705 ret += websWrite(wp, "<td></td>"); 4706 4707 /* Print related protocol */ 4708 ret += websWrite(wp, "<td>"); 4709 ret += websWrite(wp, "<select name=\"autofw_port_in_proto%d\">", i); 4710 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 4711 valid && app.proto == IPPROTO_TCP ? "selected" : ""); 4712 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 4713 valid && app.proto == IPPROTO_UDP ? "selected" : ""); 4714 ret += websWrite(wp, "</select>"); 4715 ret += websWrite(wp, "</td>"); 4716 ret += websWrite(wp, "<td></td>"); 4717 4718 /* Print related destination port range */ 4719 if (valid) 4720 snprintf(port, sizeof(port), "%d", ntohs(app.dport[0])); 4721 else 4722 *port = '\0'; 4723 ret += websWrite(wp, "<td><input name=\"autofw_port_in_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4724 i, port); 4725 ret += websWrite(wp, "<td>-</td>"); 4726 if (valid) 4727 snprintf(port, sizeof(port), "%d", ntohs(app.dport[1])); 4728 else 4729 *port = '\0'; 4730 ret += websWrite(wp, "<td><input name=\"autofw_port_in_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4731 i, port); 4732 ret += websWrite(wp, "<td></td>"); 4733 4734 /* Print mapped destination port range */ 4735 if (valid) 4736 snprintf(port, sizeof(port), "%d", ntohs(app.to[0])); 4737 else 4738 *port = '\0'; 4739 ret += websWrite(wp, "<td><input name=\"autofw_port_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4740 i, port); 4741 ret += websWrite(wp, "<td>-</td>"); 4742 if (valid) 4743 snprintf(port, sizeof(port), "%d", ntohs(app.to[1])); 4744 else 4745 *port = '\0'; 4746 ret += websWrite(wp, "<td><input name=\"autofw_port_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 4747 i, port); 4748 ret += websWrite(wp, "<td></td>"); 4749 4750 /* Print enable */ 4751 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"autofw_port_enable%d\" %s></td>", 4752 i, valid && !(app.match.flags & NETCONF_DISABLED) ? "checked" : ""); 4753 4754 ret += websWrite(wp, "</tr>"); 4755 } 4756 4757 ret += websWrite(wp, "</table>\n"); 4758 4759#endif /* !AUTOFW_PORT_DEPRECATE */ 4760 4761 return ret; 4762} 4763#endif /* __CONFIG_NAT__ */ 4764 4765/* 4766 * Example: 4767 * lan_route=192.168.2.0:255.255.255.0:192.168.2.1:1 4768 * <% lan_route("ipaddr", 0); %> produces "192.168.2.0" 4769 */ 4770static int 4771ej_lan_route(int eid, webs_t wp, int argc, char_t **argv) 4772{ 4773 char *arg; 4774 int which; 4775 char word[256], *next; 4776 char *ipaddr, *netmask, *gateway, *metric; 4777 4778 if (ejArgs(argc, argv, "%s %d", &arg, &which) < 2) { 4779 websError(wp, 400, "Insufficient args\n"); 4780 return -1; 4781 } 4782 4783 foreach(word, nvram_safe_get("lan_route"), next) { 4784 if (which-- == 0) { 4785 netmask = word; 4786 ipaddr = strsep(&netmask, ":"); 4787 if (!ipaddr || !netmask) 4788 continue; 4789 gateway = netmask; 4790 netmask = strsep(&gateway, ":"); 4791 if (!netmask || !gateway) 4792 continue; 4793 metric = gateway; 4794 gateway = strsep(&metric, ":"); 4795 if (!gateway || !metric) 4796 continue; 4797 if (!strcmp(arg, "ipaddr")) 4798 return websWrite(wp, ipaddr); 4799 else if (!strcmp(arg, "netmask")) 4800 return websWrite(wp, netmask); 4801 else if (!strcmp(arg, "gateway")) 4802 return websWrite(wp, gateway); 4803 else if (!strcmp(arg, "metric")) 4804 return websWrite(wp, metric); 4805 } 4806 } 4807 4808 return 0; 4809} 4810 4811#ifdef __CONFIG_NAT__ 4812/* 4813 * Example: 4814 * wan_route=192.168.10.0:255.255.255.0:192.168.10.1:1 4815 * <% wan_route("ipaddr", 0); %> produces "192.168.10.0" 4816 */ 4817static int 4818ej_wan_route(int eid, webs_t wp, int argc, char_t **argv) 4819{ 4820 char *arg; 4821 int which; 4822 char word[256], *next; 4823 char *ipaddr, *netmask, *gateway, *metric; 4824 int unit; 4825 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 4826 4827 4828 if (ejArgs(argc, argv, "%s %d", &arg, &which) < 2) { 4829 websError(wp, 400, "Insufficient args\n"); 4830 return -1; 4831 } 4832 4833 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 4834 unit = 0; 4835 WAN_PREFIX(unit, prefix); 4836 4837 foreach(word, nvram_safe_get(strcat_r(prefix, "route", tmp)), next) { 4838 if (which-- == 0) { 4839 netmask = word; 4840 ipaddr = strsep(&netmask, ":"); 4841 if (!ipaddr || !netmask) 4842 continue; 4843 gateway = netmask; 4844 netmask = strsep(&gateway, ":"); 4845 if (!netmask || !gateway) 4846 continue; 4847 metric = gateway; 4848 gateway = strsep(&metric, ":"); 4849 if (!gateway || !metric) 4850 continue; 4851 if (!strcmp(arg, "ipaddr")) 4852 return websWrite(wp, ipaddr); 4853 else if (!strcmp(arg, "netmask")) 4854 return websWrite(wp, netmask); 4855 else if (!strcmp(arg, "gateway")) 4856 return websWrite(wp, gateway); 4857 else if (!strcmp(arg, "metric")) 4858 return websWrite(wp, metric); 4859 } 4860 } 4861 4862 return 0; 4863} 4864#endif /* __CONFIG_NAT__ */ 4865 4866#ifdef PLC 4867static void cgi(webs_t wp, const char * const cmd) 4868{ 4869 static char line[512]; 4870 FILE *f; 4871 4872 snprintf(line, sizeof line, 4873 "/usr/sbin/gigle_util cgi %s", cmd); 4874 4875 system(line); 4876 f = fopen("/tmp/cgi.out", "rt"); 4877 if (f) 4878 { 4879 while (fgets(line, sizeof line, f)) 4880 { 4881 websWrite(wp, "%s", line); 4882 } 4883 fclose(f); 4884 } 4885 unlink("/tmp/cgi.out"); 4886} 4887 4888static int 4889ej_ggl_plc_get_autoconf_root(int eid, webs_t wp, int argc, char_t **argv) 4890{ 4891 cgi(wp, "get plc_cfg_root"); 4892 return 0; 4893} 4894 4895static int 4896ej_ggl_plc_get_info(int eid, webs_t wp, int argc, char_t **argv) 4897{ 4898 cgi(wp, "get info"); 4899 return 0; 4900} 4901 4902static int 4903ej_ggl_plc_get_mac(int eid, webs_t wp, int argc, char_t **argv) 4904{ 4905 cgi(wp, "get mac"); 4906 return 0; 4907} 4908 4909static int 4910ej_ggl_plc_get_nets(int eid, webs_t wp, int argc, char_t **argv) 4911{ 4912 cgi(wp, "get nw_info"); 4913 return 0; 4914} 4915 4916static int 4917ej_ggl_plc_get_nick(int eid, webs_t wp, int argc, char_t **argv) 4918{ 4919 cgi(wp, "get nick"); 4920 return 0; 4921} 4922 4923static int 4924ej_ggl_plc_get_role(int eid, webs_t wp, int argc, char_t **argv) 4925{ 4926 cgi(wp, "get role"); 4927 return 0; 4928} 4929 4930static int 4931ej_ggl_plc_get_stas(int eid, webs_t wp, int argc, char_t **argv) 4932{ 4933 cgi(wp, "get stas"); 4934 return 0; 4935} 4936 4937static int 4938ej_ggl_plc_get_uptime(int eid, webs_t wp, int argc, char_t **argv) 4939{ 4940 cgi(wp, "get uptime"); 4941 return 0; 4942} 4943 4944static int 4945ej_ggl_cgi_version(int eid, webs_t wp, int argc, char_t **argv) 4946{ 4947 cgi(wp, "get version"); 4948 return 0; 4949} 4950 4951static int 4952ej_ggl_get_avln_list(int eid, webs_t wp, int argc, char_t **argv) 4953{ 4954 int i; 4955 char mac[] = "00:1F:84:00:00:00"; 4956 char nid[] = "00 11 22 33 44 55"; 4957 4958 printf("ej_ggl_get_avln_list()\n"); 4959 4960 // TODO: Query apcm_get_newsta 4961 4962 for (i = 0; i<4; i++) { 4963 websWrite(wp, "<tr align=\"center\">"); 4964 websWrite(wp, "<td>%s</td>", mac); 4965 websWrite(wp, "<td>%s</td>", nid); 4966 websWrite(wp, "<td>%u</td>", 5); 4967 websWrite(wp, "</tr>"); 4968 } 4969 return 0; 4970} 4971 4972/************************************************** 4973 * Function name : static void do_plc_cgi_restart(char *url, FILE *stream) 4974 * Created by : Toni Homedes i Saun 4975 * Date created : 06-10-2010 4976 * Notes : Public function 4977 * Restrictions (pre-conditions) 4978 * Odd modes (post-conditions) 4979 **************************************************/ 4980/** \brief Restarts the modem 4981 * 4982 * \param[in] url unused 4983 * \param[in] stream socket to write to 4984 * 4985 **************************************************/ 4986static void do_plc_cgi_restart(char *url, FILE *stream) 4987{ 4988 assert(url); 4989 assert(stream); 4990 4991 DictFree(BcmPostArgs); /* Ignoring any argument */ 4992 4993 websHeader(stream); 4994 websWrite(stream, (char_t *) apply_header); 4995 4996 cgi(stream, "restart"); 4997 4998 websWrite(stream, (char_t *) apply_footer, "plc.asp"); 4999 websFooter(stream); 5000 websDone(stream, 200); 5001} 5002 5003/************************************************** 5004 * Function name : static void do_plc_cgi(char *url, FILE *stream) 5005 * Created by : Toni Homedes i Saun 5006 * Date created : 06-10-2010 5007 * Notes : Public function 5008 * Restrictions (pre-conditions) 5009 * Odd modes (post-conditions) 5010 **************************************************/ 5011/** \brief Generates the plc.cgi page 5012 * 5013 * \param[in] url unused 5014 * \param[in] stream socket to write to 5015 * 5016 **************************************************/ 5017static void do_plc_cgi(char *url, FILE *stream) 5018{ 5019 dict_iterator_t iterator = DictIteratorNew(BcmPostArgs); 5020 5021 assert(url); 5022 assert(stream); 5023 5024 websHeader(stream); 5025 websWrite(stream, (char_t *) apply_header); 5026 5027 websWrite(stream, "\n<p>Processing the following values:</p>"); 5028 5029 websWrite(stream, "<table border=\"1\" cellpadding=\"2\">\n"); 5030 do 5031 { 5032 char command[512]; 5033 const char *key = DictIteratorKey(iterator); 5034 if (key) 5035 { 5036 const char *value = DictGet(BcmPostArgs, key); 5037 5038 websWrite(stream, " <tr><td>%s</td><td>%s</td><td>", key, value); 5039 sprintf(command, "set \"%s\" \"%s\"", key, value); 5040 cgi(stream, command); 5041 websWrite(stream, "</td></tr>\n"); 5042 } 5043 } 5044 while (DictIteratorAdvance(iterator)); 5045 5046 websWrite(stream, "</table>\n"); 5047 5048 websWrite(stream, (char_t *) apply_footer, "plc.asp"); 5049 websFooter(stream); 5050 websDone(stream, 200); 5051 DictIteratorFree(iterator); 5052 DictFree(BcmPostArgs); 5053 5054 sleep(1); 5055} 5056#endif 5057 5058/* Return a list of the currently present wireless interfaces */ 5059static int 5060ej_wl_list(int eid, webs_t wp, int argc, char_t **argv) 5061{ 5062 char name[IFNAMSIZ], *next=NULL; 5063 char wl_name[IFNAMSIZ],os_name[IFNAMSIZ]; 5064 int unit=-1,subunit=-1, ret = 0; 5065 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5066 char unit_str[]="000000"; 5067 char *hwaddr=NULL, *ssid=NULL, *virtual=NULL; 5068 char ifnames[256]; 5069 char *str_to_compare=NULL; 5070 char *is_ssid_required=NULL; 5071 5072 if (ejArgs(argc, argv, "%s %s", &is_ssid_required, &virtual) > 0) { 5073 if (strcmp(virtual,"INCLUDE_VIFS")){ 5074 websError(wp, 400, "Unknown argument %s\n",virtual); 5075 return -1; 5076 } 5077 } 5078 5079 5080 snprintf(ifnames, sizeof(ifnames), "%s %s %s", 5081 nvram_safe_get("lan_ifnames"), 5082 nvram_safe_get("wan_ifnames"), 5083 nvram_safe_get("lan1_ifnames")); 5084 5085 if (!remove_dups(ifnames,sizeof(ifnames))){ 5086 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 5087 return -1; 5088 } 5089 5090 foreach(name, ifnames, next) { 5091 5092 if ( nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0 ) 5093 continue; 5094 5095 if (wl_probe(os_name) || 5096 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))) 5097 continue; 5098 5099 /* Convert eth name to wl name */ 5100 5101 if( osifname_to_nvifname( name, wl_name, sizeof(wl_name) ) != 0 ) 5102 { 5103 websError(wp, 400, "wl name for interface:%s not found\n",name); 5104 return -1; 5105 } 5106 5107 /* Get configured ethernet MAC address */ 5108 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 5109 5110 /* Slave intefaces have a '.' in the name. assume the MAC address 5111 is the same as the primary interface*/ 5112 if (strchr(wl_name,'.')) { 5113 /* If Physical interfaces are specified do not 5114 process the slave interfaces skip writing out the info 5115 */ 5116 if (virtual) 5117 snprintf(prefix, sizeof(prefix),"%s_",wl_name); 5118 else 5119 continue; 5120 } 5121 5122 if (get_ifname_unit(wl_name,&unit,&subunit) < 0) { 5123 websError(wp, 400, "Error extracting unit and subunit name from %s\n",wl_name); 5124 return -1; 5125 } 5126 5127 hwaddr = nvram_get(strcat_r(prefix, "hwaddr", tmp)); 5128 5129 /* Should not need to test if pysical interfaces flag is set, 5130 since that the code above will skip this portion. However 5131 it guards against future problems if this gets reworked 5132 in the future as the explicit checks here prevent any 5133 ambiguity 5134 */ 5135 5136 if ((subunit > 0 ) && (virtual) ) 5137 snprintf(unit_str,sizeof(unit_str),"%d.%d",unit,subunit); 5138 else 5139 snprintf(unit_str,sizeof(unit_str),"%d",unit); 5140 5141 ssid = nvram_get(strcat_r(prefix, "ssid", tmp)); 5142 5143 if (!hwaddr || !*hwaddr || !ssid || !*ssid) 5144 continue; 5145 5146 /* The following code is for ssid.asp , used to highlight the physical interface */ 5147 if (websGetVar(wp, "wl_bssid", NULL)) { 5148 str_to_compare = websGetVar(wp, "wl_unit", NULL); 5149 } 5150 else { 5151 str_to_compare = nvram_safe_get("wl_unit"); 5152 } 5153 if (is_ssid_required) { 5154 ret += websWrite(wp, "<option value=\"%s\" %s>%s(%s)</option>\n", unit_str, 5155 (!strncmp(unit_str,str_to_compare,sizeof(unit_str))) ? "selected" : "", 5156 translate_ssid(ssid), hwaddr); 5157 } 5158 else { 5159 ret += websWrite(wp, "<option value=\"%s\" %s>(%s)</option>\n", unit_str, 5160 (!strncmp(unit_str,str_to_compare,sizeof(unit_str))) ? "selected" : "", 5161 hwaddr); 5162 } 5163 } 5164 5165 if (!ret) 5166 ret += websWrite(wp, "<option value=\"-1\" selected>None</option>"); 5167 5168 return ret; 5169} 5170 5171/* Return a list of the supported bands on the currently selected wireless interface */ 5172static int 5173ej_wl_phytypes(int eid, webs_t wp, int argc, char_t **argv) 5174{ 5175 int ret = 0; 5176 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5177 char *phytype=NULL, *name; 5178 char *phylist=NULL; 5179 int i=0; 5180 int bandtype, error; 5181 int list[WLC_BAND_ALL]; 5182 5183 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 5184 return websWrite(wp, "None"); 5185 5186 /* Get configured phy type */ 5187 phytype = nvram_safe_get("wl_phytype"); 5188 5189 if (phytype[i] == 'n' || phytype[i] == 'l' || phytype[i] == 's' || phytype[i] == 'c' || phytype[i] == 'h' || phytype[i] == 'v') { 5190 bandtype = atoi(nvram_safe_get(strcat_r(prefix, "nband", tmp))); 5191 5192 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5193 5194 /* Get band list. Assume both the bands in case of error */ 5195 if ((error = wl_ioctl(name, WLC_GET_BANDLIST, list, sizeof(list))) < 0) { 5196 for (i = 1; i < 3; i++) 5197 ret += websWrite(wp, "<option value=\"%d\" %s> %s GHz</option>\n", 5198 i, 5199 (bandtype == i)? "selected": "", 5200 (i == WLC_BAND_5G)? "5":"2.4"); 5201 return ret; 5202 } 5203 if (list[0] > 2) 5204 list[0] = 2; 5205 5206 for (i = 1; i <= list[0]; i++) { 5207 if ((phytype[0] == 'n') || (phytype[0] == 's')|| (phytype[0] == 'c') || (phytype[0] == 'h') || phytype[0] == 'v') 5208 ret += websWrite(wp, "<option value=\"%d\" %s> %s GHz</option>", 5209 list[i], (bandtype == list[i])? "selected": "", 5210 (list[i] == WLC_BAND_5G)? "5":"2.4"); 5211 else /* if lpphy */ { 5212 if (list[i] == WLC_BAND_5G) 5213 sprintf(tmp, "802.11%c (%s GHz)",'a',"5"); 5214 else 5215 sprintf(tmp, "802.11%c (%s GHz)",'g',"2.4"); 5216 ret += websWrite(wp, "<option value=\"%c\" %s>%s</option>", 5217 ((list[i] == WLC_BAND_5G)? 'a':'g'), 5218 bandtype == list[i] ? "selected" : "", tmp); 5219 } 5220 } 5221 return ret; 5222 } 5223 /* Get available phy types of the currently selected wireless interface */ 5224 phylist = nvram_safe_get(strcat_r(prefix, "phytypes", tmp)); 5225 5226 for (i = 0; i < strlen(phylist); i++) { 5227 sprintf(tmp, "802.11%c (%s GHz)", phylist[i], 5228 phylist[i] == 'a' ? "5" : "2.4"); 5229 ret += websWrite(wp, "<option value=\"%c\" %s>%s</option>", 5230 phylist[i], phylist[i] == *phytype ? "selected" : "", tmp); 5231 } 5232 5233 return ret; 5234} 5235 5236static int 5237ej_wl_nmode_enabled(int eid, webs_t wp, int argc, char_t **argv) 5238{ 5239 char *temp; 5240 int unit = -1; 5241 int sub_unit = -1; 5242 char nv_param[NVRAM_MAX_PARAM_LEN]; 5243 5244 temp = nvram_get("wl_unit"); 5245 if (strlen(temp) == 0) { 5246 websError(wp, 400, "Error getting wl_unit\n"); 5247 return EINVAL; 5248 } 5249 5250 if (get_ifname_unit(temp, &unit, &sub_unit) != 0) { 5251 websError(wp, 400, "Error getting unit/subunit\n"); 5252 return EINVAL; 5253 } 5254 5255 sprintf(nv_param, "wl%d_nmode", unit); 5256 temp = nvram_safe_get(nv_param); 5257 if (strncmp(temp, "0", 1) == 0) 5258 websWrite(wp, "\"0\""); 5259 else 5260 websWrite(wp, "\"1\""); 5261 5262 return 0; 5263} 5264 5265/* Return a list of the supported bands on the currently selected wireless interface */ 5266static int 5267ej_wl_nphyrates(int eid, webs_t wp, int argc, char_t **argv) 5268{ 5269 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5270 int phytype; 5271 int ret = 0, i; 5272 /* -2 is for Legacy rate 5273 * -1 is placeholder for 'Auto' 5274 */ 5275 int mcsidxs[]= { -1, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32}; 5276 int selected_idx, selected_bw, nbw, rate; 5277 5278 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 5279 websError(wp, 400, "unit number variable doesn't exist\n"); 5280 return -1; 5281 } 5282 5283 /* Get configured phy type */ 5284 if ((ret = wl_phytype_get(wp, &phytype)) != 0) 5285 return ret; 5286 5287 if ((phytype != WLC_PHY_TYPE_N) && (phytype != WLC_PHY_TYPE_SSN) && 5288 (phytype != WLC_PHY_TYPE_LCN) && (phytype != WLC_PHY_TYPE_HT) && 5289 (phytype != WLC_PHY_TYPE_AC)) 5290 return ret; 5291 5292 if (ejArgs(argc, argv, "%d", &nbw) < 1) { 5293 websError(wp, 400, "BW does not exist \n"); 5294 return -1; 5295 } 5296 /* nbw: 0 - Good Neighbor, 20 - 20MHz, 40 - 40MHz */ 5297 5298 selected_idx = atoi(nvram_safe_get(strcat_r(prefix, "nmcsidx", tmp))); 5299 selected_bw = atoi(nvram_safe_get(strcat_r(prefix, "nbw", tmp))); 5300 rate = atoi(nvram_safe_get(strcat_r(prefix, "rate", tmp))); 5301 5302 /* Zero out the length of options */ 5303 ret += websWrite(wp, "\t\tdocument.forms[0].wl_nmcsidx.length = 0; \n"); 5304 5305 ret += websWrite(wp, "\t\tdocument.forms[0].wl_nmcsidx[0] = " 5306 "new Option(\"Auto\", \"-1\");\n"); 5307 5308 if (selected_idx == -1 || rate == 0) 5309 ret += websWrite(wp, "\t\tdocument.forms[0].wl_nmcsidx.selectedIndex = 0;\n"); 5310 5311 for (i = 1; i < ARRAYSIZE(mcsidxs); i++) { 5312 /* Limit MCS rates based on number of user selected TxChains 5313 * This block of code adds an "if" statement into the NPHY Rates List 5314 * which surrounds the MCS indexes greater than 7 5315 */ 5316 if (mcsidxs[i] == 8) { 5317 ret += websWrite(wp, "\t\tif(document.forms[0].wl_txchain.selectedIndex > 0) {\n"); 5318 } 5319 5320 /* MCS IDX 32 is valid only for 40 Mhz */ 5321 if (mcsidxs[i] == 32 && (nbw == 20 || nbw == 0)) 5322 continue; 5323 ret += websWrite(wp, "\t\tdocument.forms[0].wl_nmcsidx[%d] = new Option(\"", i); 5324 if (mcsidxs[i] == -2) { 5325 ret += websWrite(wp, "Use Legacy Rate\", \"-2\");\n"); 5326 if (selected_idx == -2 && nbw == selected_bw) 5327 ret += websWrite(wp, 5328 "\t\tdocument.forms[0].wl_nmcsidx.selectedIndex =" 5329 "%d;\n", i); 5330 } else { 5331 uint mcs_rate = MCS_TABLE_RATE(mcsidxs[i], (nbw == 40)); 5332 ret += websWrite(wp, "%2d: %d", mcsidxs[i], mcs_rate/1000); 5333 /* Handle floating point generation */ 5334 if (mcs_rate % 1000) 5335 ret += websWrite(wp, ".%d", (mcs_rate % 1000)/100); 5336 ret += websWrite(wp, " Mbps"); 5337 if (nbw == 0) { 5338 mcs_rate = MCS_TABLE_RATE(mcsidxs[i], TRUE); 5339 ret += websWrite(wp, " or %d", mcs_rate/1000); 5340 /* Handle floating point generation */ 5341 if (mcs_rate % 1000) 5342 ret += websWrite(wp, ".%d", (mcs_rate % 1000)/100); 5343 ret += websWrite(wp, " Mbps"); 5344 } 5345 ret += websWrite(wp, "\", \"%d\");\n", mcsidxs[i]); 5346 5347 if (selected_idx == mcsidxs[i] && selected_bw == nbw) 5348 ret += websWrite(wp, 5349 "\t\tdocument.forms[0].wl_nmcsidx.selectedIndex =" 5350 "%d;\n", i); 5351 } 5352 } 5353 5354 /* terminate the "if" condition for txchains */ 5355 ret += websWrite(wp, "\t\t}\n"); 5356 5357 return ret; 5358} 5359 5360/* Return a list of the available number of txchains */ 5361static int 5362ej_wl_txchains_list(int eid, webs_t wp, int argc, char_t **argv) 5363{ 5364 int ret = 0; 5365 int count; 5366 int txchain_cnt = 0; /* Default */ 5367 int txchains = txchain_cnt; 5368 char *str; 5369 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5370 5371 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 5372 websError(wp, 400, "unit number variable doesn't exist\n"); 5373 return -1; 5374 } 5375 5376 /* # of TX chains supported by device */ 5377 str = nvram_get(strcat_r(prefix, "hw_txchain", tmp)); 5378 if (str) { 5379 txchain_cnt = atoi(str); 5380 if (txchain_cnt == 2) 5381 txchain_cnt = 1; 5382 else if (txchain_cnt == 3) 5383 txchain_cnt = 2; 5384 else if (txchain_cnt == 7) 5385 txchain_cnt = 3; 5386 } 5387 5388 /* User configured # of TX streams */ 5389 str = nvram_get("wl_txchain"); 5390 if (str) { 5391 txchains = atoi(str); 5392 if (txchains == 2) 5393 txchains = 1; 5394 else if (txchains == 3) 5395 txchains = 2; 5396 else if (txchains == 7) 5397 txchains = 3; 5398 } 5399 for (count=1; count <= txchain_cnt; count++) { 5400 ret += websWrite(wp, "\t<option value=%d %s>%d</option>\n", 5401 (count == 1) ? 1 : (count == 2) ? 3 : 7, 5402 (count == txchains) ? "selected" : "", count); 5403 } 5404 5405 return ret; 5406} 5407 5408/* Return a list of the available number of rxchains */ 5409static int 5410ej_wl_rxchains_list(int eid, webs_t wp, int argc, char_t **argv) 5411{ 5412 int ret = 0; 5413 int count; 5414 int rxchain_cnt = 0; /* Default */ 5415 int rxchains = rxchain_cnt; 5416 char *str; 5417 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5418 5419 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 5420 websError(wp, 400, "unit number variable doesn't exist\n"); 5421 return -1; 5422 } 5423 5424 /* # of RX chains supported by device */ 5425 str = nvram_get(strcat_r(prefix, "hw_rxchain", tmp)); 5426 if (str) { 5427 rxchain_cnt = atoi(str); 5428 if (rxchain_cnt == 2) 5429 rxchain_cnt = 1; 5430 else if (rxchain_cnt == 3) 5431 rxchain_cnt = 2; 5432 else if (rxchain_cnt == 7) 5433 rxchain_cnt = 3; 5434 } 5435 5436 /* User configured # of RX streams */ 5437 str = nvram_get("wl_rxchain"); 5438 if (str) { 5439 rxchains = atoi(str); 5440 if (rxchains == 2) 5441 rxchains = 1; 5442 else if (rxchains == 3) 5443 rxchains = 2; 5444 else if (rxchains == 7) 5445 rxchains = 3; 5446 } 5447 for (count=1; count <= rxchain_cnt; count++) { 5448 ret += websWrite(wp, "\t<option value=%d %s>%d</option>\n", 5449 (count == 1) ? 1 : (count == 2) ? 3 : 7, 5450 (count == rxchains) ? "selected" : "", count); 5451 } 5452 return ret; 5453} 5454 5455/* Return a radio ID given a phy type */ 5456static int 5457ej_wl_radioid(int eid, webs_t wp, int argc, char_t **argv) 5458{ 5459 char *phytype=NULL, var[NVRAM_BUFSIZE], *next; 5460 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5461 int which; 5462 5463 if (ejArgs(argc, argv, "%s", &phytype) < 1) { 5464 websError(wp, 400, "Insufficient args\n"); 5465 return -1; 5466 } 5467 5468 assert(phytype); 5469 5470 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 5471 return websWrite(wp, "None"); 5472 5473 which = strcspn(nvram_safe_get(strcat_r(prefix, "phytypes", tmp)), phytype); 5474 foreach(var, nvram_safe_get(strcat_r(prefix, "radioids", tmp)), next) { 5475 if (which == 0) 5476 return websWrite(wp, var); 5477 which--; 5478 } 5479 5480 return websWrite(wp, "None"); 5481} 5482 5483/* Return current core revision */ 5484static int 5485ej_wl_corerev(int eid, webs_t wp, int argc, char_t **argv) 5486{ 5487 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5488 5489 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 5490 return websWrite(wp, "None"); 5491 5492 return websWrite(wp, nvram_safe_get(strcat_r(prefix, "corerev", tmp))); 5493} 5494 5495/* Return current wireless channel specification */ 5496static int 5497ej_wl_cur_chanspec(int eid, webs_t wp, int argc, char_t **argv) 5498{ 5499 char *name=NULL; 5500 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5501 channel_info_t ci; 5502 int phytype; 5503 uint32 chanspec; 5504 int channel; 5505 int chan_adj = 0; 5506 int status; 5507 uint32 chanim_enab = 0; 5508 uint32 interference = 0; 5509 const char CHANIM_S[] = "***Interference Level: Severe"; 5510 const char CHANIM_A[] = "***Interference Level: Acceptable"; 5511 static union { 5512 char bufdata[WLC_IOCTL_SMLEN]; 5513 uint32 alignme; 5514 } bufstruct; 5515 char *retbuf = (char*) &bufstruct.bufdata; 5516 char chanbuf[CHANSPEC_STR_LEN]; 5517#define CHANIMSTR(a, b, c, d) ((a) ? ((b) ? c : d) : "") 5518 5519 (void) chan_adj; 5520 (void) channel; 5521 (void) ci; 5522 5523 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5524 websError(wp, 400, "unit number variable doesn't exist\n"); 5525 return -1; 5526 } 5527 5528 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5529 5530 /* Get configured phy type */ 5531 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5532 return status; 5533 5534 if (wl_iovar_getint(name, "chanim_enab", (int*)(void*)&chanim_enab)) 5535 chanim_enab = 0; 5536 5537 if (wl_iovar_getint(name, "chanspec", (int*)(void *)&chanspec)) 5538 return -1; 5539 5540 if (chanim_enab) { 5541 if (wl_iovar_getbuf(name, "chanim_state", &chanspec, sizeof(chanspec), 5542 retbuf, WLC_IOCTL_SMLEN)) 5543 return -1; 5544 5545 interference = *(int*)retbuf; 5546 } 5547 5548 return websWrite(wp, "Current: %s %s", 5549 wf_chspec_ntoa(chanspec, chanbuf), 5550 CHANIMSTR(chanim_enab, interference, CHANIM_S, CHANIM_A)); 5551 5552#undef CHANIMSTR 5553} 5554 5555/* Return current wireless channel */ 5556static int 5557ej_wl_cur_channel(int eid, webs_t wp, int argc, char_t **argv) 5558{ 5559 char *name=NULL; 5560 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5561 channel_info_t ci; 5562 int phytype; 5563 uint32 chanspec; 5564 int channel; 5565 int chan_adj = 0; 5566 int status; 5567 uint32 chanim_enab = 0; 5568 uint32 interference = 0; 5569 const char CHANIM_S[] = "***Interference Level: Severe"; 5570 const char CHANIM_A[] = "***Interference Level: Acceptable"; 5571 char retbuf[WLC_IOCTL_SMLEN]; 5572#define CHANIMSTR(a, b, c, d) ((a) ? ((b) ? c : d) : "") 5573 5574 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5575 websError(wp, 400, "unit number variable doesn't exist\n"); 5576 return -1; 5577 } 5578 5579 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5580 5581 /* Get configured phy type */ 5582 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5583 return status; 5584 5585 if (wl_iovar_getint(name, "chanim_enab", (int*)(void*)&chanim_enab)) 5586 chanim_enab = 0; 5587 5588 if ((phytype != WLC_PHY_TYPE_N) && (phytype != WLC_PHY_TYPE_SSN) && 5589 (phytype != WLC_PHY_TYPE_LCN) && (phytype != WLC_PHY_TYPE_HT)) { 5590 wl_ioctl(name, WLC_GET_CHANNEL, &ci, sizeof(ci)); 5591 channel = ci.target_channel; 5592 chanspec = CH20MHZ_CHSPEC(channel); 5593 } else { 5594 if (wl_iovar_getint(name, "chanspec", (int*)(void *)&chanspec)) 5595 return -1; 5596 if ((chanspec & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) { 5597 int sb = chanspec & WL_CHANSPEC_CTL_SB_MASK; 5598 if (sb == WL_CHANSPEC_CTL_SB_LOWER) 5599 chan_adj = -2; 5600 else 5601 chan_adj = 2; 5602 } 5603 5604 channel = CHSPEC_CHANNEL(chanspec); 5605 } 5606 5607 if (chanim_enab) { 5608 if (wl_iovar_getbuf(name, "chanim_state", &chanspec, sizeof(chanspec), 5609 retbuf, WLC_IOCTL_SMLEN)) 5610 return -1; 5611 5612 interference = *(int*)retbuf; 5613 } 5614 5615 return websWrite(wp, "Current: %d %s", 5616 (channel + chan_adj), 5617 CHANIMSTR(chanim_enab, interference, CHANIM_S, CHANIM_A)); 5618 5619#undef CHANIMSTR 5620} 5621 5622/* Return current 802.11n channel bandwidth */ 5623static int 5624ej_wl_cur_bw(int eid, webs_t wp, int argc, char_t **argv) 5625{ 5626 char *name=NULL; 5627 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5628 chanspec_t chanspec; 5629 5630 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5631 websError(wp, 400, "unit number variable doesn't exist\n"); 5632 return -1; 5633 } 5634 5635 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5636 5637 if (wl_iovar_getint(name, "chanspec", (int*)(void *)&chanspec)) 5638 return -1; 5639 5640 return websWrite(wp, "Current: %s", 5641 (CHSPEC_BW(chanspec) == WL_CHANSPEC_BW_80) ? "80MHz" : 5642 (CHSPEC_BW(chanspec) == WL_CHANSPEC_BW_40) ? "40MHz" : "20MHz"); 5643} 5644 5645/* Return current 802.11n control sideband */ 5646static int 5647ej_wl_cur_nctrlsb(int eid, webs_t wp, int argc, char_t **argv) 5648{ 5649 char *name=NULL; 5650 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5651 chanspec_t chanspec; 5652 5653 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5654 websError(wp, 400, "unit number variable doesn't exist\n"); 5655 return -1; 5656 } 5657 5658 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5659 5660 if (wl_iovar_getint(name, "chanspec", (int*)(void *)&chanspec)) 5661 return -1; 5662 5663 return websWrite(wp, "Current: %s", (chanspec & WL_CHANSPEC_CTL_SB_MASK) == 5664 WL_CHANSPEC_CTL_SB_LOWER ? "lower" : 5665 WL_CHANSPEC_CTL_SB_UPPER ? "upper" : "none"); 5666} 5667 5668/* Return current country */ 5669static int 5670ej_wl_cur_country(int eid, webs_t wp, int argc, char_t **argv) 5671{ 5672 char *name=NULL; 5673 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5674 wl_country_t cspec = {{0}, 0, {0}}; 5675 5676 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5677 websError(wp, 400, "unit number variable doesn't exist\n"); 5678 return -1; 5679 } 5680 5681 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5682 5683 if (wl_iovar_get(name, "country", &cspec, sizeof(cspec))) 5684 return -1; 5685 return websWrite(wp, "%s", cspec.ccode); 5686} 5687 5688static int 5689ej_wl_cur_regrev(int eid, webs_t wp, int argc, char_t **argv) 5690{ 5691 char *name=NULL; 5692 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5693 wl_country_t cspec = {{0}, 0, {0}}; 5694 5695 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5696 websError(wp, 400, "unit number variable doesn't exist\n"); 5697 return -1; 5698 } 5699 5700 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5701 5702 /* country_rev is not in the nvram get it from the driver */ 5703 if (wl_iovar_get(name, "country", &cspec, sizeof(cspec))) 5704 return -1; 5705 return websWrite(wp, "%d", cspec.rev); 5706} 5707 5708/* Return current phytype */ 5709static int 5710ej_wl_cur_phytype(int eid, webs_t wp, int argc, char_t **argv) 5711{ 5712 char *name; 5713 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5714 int phytype; 5715 5716 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5717 websError(wp, 400, "unit number variable doesn't exist\n"); 5718 return -1; 5719 } 5720 5721 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5722 5723 /* Get configured phy type */ 5724 wl_ioctl(name, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); 5725 5726 if ((phytype != WLC_PHY_TYPE_N) && (phytype != WLC_PHY_TYPE_SSN) && 5727 (phytype != WLC_PHY_TYPE_LCN) && (phytype != WLC_PHY_TYPE_HT) && 5728 (phytype != WLC_PHY_TYPE_AC)) 5729 if (phytype == WLC_PHY_TYPE_LP) { 5730 wl_ioctl(name, WLC_GET_BAND, &phytype, sizeof(phytype)); 5731 return websWrite(wp, "Current: %s", phytype == WLC_BAND_5G ? "5 GHz" : 5732 phytype == WLC_BAND_2G ? "2.4 GHz" : "Auto"); 5733 } else 5734 return websWrite(wp, "Current: 802.11%s", phytype == WLC_PHY_TYPE_A ? "a" : 5735 phytype == WLC_PHY_TYPE_B ? "b" : "g"); 5736 else { 5737 wl_ioctl(name, WLC_GET_BAND, &phytype, sizeof(phytype)); 5738 return websWrite(wp, "Current: %s", phytype == WLC_BAND_5G ? "5 GHz" : 5739 phytype == WLC_BAND_2G ? "2.4 GHz" : "Auto"); 5740 } 5741 return 0; 5742} 5743 5744/* Return whether the current phytype is NPHY */ 5745static int 5746ej_wl_nphy_set(int eid, webs_t wp, int argc, char_t **argv) 5747{ 5748 int phytype, status; 5749 5750 /* Get configured phy type */ 5751 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5752 return status; 5753 5754 return websWrite(wp, "%d", ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5755 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5756 (phytype == WLC_PHY_TYPE_AC))); 5757} 5758 5759/* Generate the whole protection rows */ 5760static int 5761ej_wl_protection(int eid, webs_t wp, int argc, char_t **argv) 5762{ 5763 int phytype, status; 5764 int ret =0; 5765 char *prot_str; 5766 5767 /* Get configured phy type */ 5768 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5769 return status; 5770 5771 prot_str = ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5772 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5773 (phytype == WLC_PHY_TYPE_AC))? 5774 "wl_nmode_protection":"wl_gmode_protection"; 5775 5776 ret += websWrite(wp, "<th width=\"310\"\n\tonMouseOver=\"return overlib('In <b>Auto</b>" 5777 "mode the AP will use RTS/CTS to improve"); 5778 ret += websWrite(wp, " %s performance in mixed %s networks. Turn protection <b>Off</b> to " 5779 "maximize %s througput under most conditions.', LEFT);\"\n", 5780 ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5781 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5782 (phytype == WLC_PHY_TYPE_AC))? 5783 "802.11n":"802.11g", 5784 ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5785 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5786 (phytype == WLC_PHY_TYPE_AC))? 5787 "802.11n/a/b/g":"802.11g/b", 5788 ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5789 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5790 (phytype == WLC_PHY_TYPE_AC))? 5791 "802.11n":"802.11g"); 5792 ret += websWrite(wp, "\tonMouseOut=\"return nd();\">\n\t%s Protection: " 5793 "\n\t</th>\n\t<td> </td>\n\t<td>\n", 5794 ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5795 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5796 (phytype == WLC_PHY_TYPE_AC))? 5797 "802.11n":"54g"); 5798 ret += websWrite(wp, "\t\t<select name=\"%s\">\n", 5799 prot_str); 5800 ret += websWrite(wp, "\t\t\t<option value=\"auto\" %s>Auto</option>\n", 5801 nvram_match(prot_str, "auto")?"selected":""); 5802 ret += websWrite(wp, "\t\t\t<option value=\"off\" %s>Off</option>\n", 5803 nvram_match(prot_str, "off")?"selected":""); 5804 ret += websWrite(wp, "\t\t</select>\n\t</td>"); 5805 5806 return ret; 5807} 5808 5809/* Generate the whole mimo preamble rows */ 5810static int 5811ej_wl_mimo_preamble(int eid, webs_t wp, int argc, char_t **argv) 5812{ 5813 int ret =0, mode = 0; 5814 char *prot_str; 5815 char prefix[] = "wlXXXXXXXXXX_"; 5816 char *name = NULL; 5817 char wlif[64]; 5818 wlc_rev_info_t rev; 5819 5820 if (!make_wl_prefix(prefix, sizeof(prefix), mode, NULL)) { 5821 websError(wp, 400, "unit number variable doesn't exist\n"); 5822 return -1; 5823 } 5824 5825 name = nvram_safe_get(strcat_r(prefix, "ifname",wlif)); 5826 5827 wl_ioctl(name, WLC_GET_REVINFO, &rev, sizeof(rev)); 5828 5829 if (!((rev.chipnum == BCM4716_CHIP_ID) || 5830 (rev.chipnum == BCM47162_CHIP_ID) || 5831 (rev.chipnum == BCM4748_CHIP_ID) || 5832 (rev.chipnum == BCM4331_CHIP_ID) || 5833 (rev.chipnum == BCM43431_CHIP_ID))) 5834 return -1; 5835 5836 5837 prot_str = "wl_mimo_preamble"; 5838 5839 ret += websWrite(wp, "<th width=\"310\"\n\tonMouseOver=\"return overlib('Force to use Green-Field or Mixed-Mode preamble. in<b>Auto</b>" 5840 "mode the AP will use GF or MM based on required protection ', LEFT);\"\n"); 5841 ret += websWrite(wp, "\tonMouseOut=\"return nd();\">\n\t%s Mimo PrEamble: " 5842 "\n\t</th>\n\t<td> </td>\n\t<td>\n","802.11n"); 5843 ret += websWrite(wp, "\t\t<select name=\"%s\">\n", prot_str); 5844 ret += websWrite(wp, "\t\t\t<option value=\"gfbcm\" %s>GF-BRCM</option>\n", 5845 nvram_match(prot_str, "gfbcm")?"selected":""); 5846 ret += websWrite(wp, "\t\t\t<option value=\"auto\" %s>Auto</option>\n", 5847 nvram_match(prot_str, "auto")?"selected":""); 5848 ret += websWrite(wp, "\t\t\t<option value=\"gf\" %s>Green Field</option>\n", 5849 nvram_match(prot_str, "gf")?"selected":""); 5850 ret += websWrite(wp, "\t\t\t<option value=\"mm\" %s>Mixed Mode</option>\n", 5851 nvram_match(prot_str, "mm")?"selected":""); 5852 ret += websWrite(wp, "\t\t</select>\n\t</td>"); 5853 5854 return ret; 5855} 5856 5857/* If current phytype is nphy, the print string 'legacy' for Rate drop down */ 5858static int 5859ej_wl_legacy_string(int eid, webs_t wp, int argc, char_t **argv) 5860{ 5861 int phytype, status; 5862 5863 /* Get configured phy type */ 5864 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5865 return status; 5866 5867 return websWrite(wp, "%s", ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5868 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT))? "Legacy":""); 5869} 5870 5871/* If current phytype is NOT nphy, the print start of comment <!-- 5872 * in the HTML for the concerned fields to prevent them from appearing on the page 5873 */ 5874static int 5875ej_wl_nphy_comment_beg(int eid, webs_t wp, int argc, char_t **argv) 5876{ 5877 int phytype, status; 5878 5879 /* Get configured phy type */ 5880 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5881 return status; 5882 return websWrite(wp, "%s", ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5883 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5884 (phytype == WLC_PHY_TYPE_AC))? "":"<!--"); 5885} 5886 5887static int 5888ej_wl_nphy_comment_end(int eid, webs_t wp, int argc, char_t **argv) 5889{ 5890 int phytype, status; 5891 5892 /* Get configured phy type */ 5893 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5894 return status; 5895 return websWrite(wp, "%s", ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5896 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5897 (phytype == WLC_PHY_TYPE_AC))? "":"-->"); 5898} 5899 5900/* Return the variable for the Band field. 5901 * For 11n, its wl_nband, while for a/b/g, it's wl_phytype 5902 */ 5903static int 5904ej_wl_phytype_name(int eid, webs_t wp, int argc, char_t **argv) 5905{ 5906 int phytype, status; 5907 5908 /* Get configured phy type */ 5909 if ((status = wl_phytype_get(wp, &phytype)) != 0) 5910 return status; 5911 5912 return websWrite(wp, "%s", ((phytype == WLC_PHY_TYPE_N) || (phytype == WLC_PHY_TYPE_SSN) || 5913 (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_HT) || 5914 (phytype == WLC_PHY_TYPE_AC))? "\"wl_nband\"":"\"wl_phytype\""); 5915} 5916 5917/* Return current band */ 5918static int 5919ej_wl_cur_band(int eid, webs_t wp, int argc, char_t **argv) 5920{ 5921 char *name; 5922 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5923 int bandtype; 5924 5925 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 5926 websError(wp, 400, "unit number variable doesn't exist\n"); 5927 return -1; 5928 } 5929 5930 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 5931 5932 /* Get configured phy type */ 5933 wl_ioctl(name, WLC_GET_BAND, &bandtype, sizeof(bandtype)); 5934 5935 return websWrite(wp, "Current: %s ", bandtype == WLC_BAND_5G ? "5 GHz" : 5936 bandtype == WLC_BAND_2G? "2.4 GHz" : "Auto"); 5937} 5938 5939static int 5940ej_wl_crypto(int eid, webs_t wp, int argc, char_t **argv) 5941{ 5942 char *temp; 5943 int unit = -1; 5944 int sub_unit = -1; 5945 char nv_param[NVRAM_MAX_PARAM_LEN]; 5946 5947 temp = nvram_get("wl_unit"); 5948 if (strlen(temp) == 0) { 5949 websError(wp, 400, "Error getting wl_unit\n"); 5950 return EINVAL; 5951 } 5952 5953 if (get_ifname_unit(temp, &unit, &sub_unit) != 0) { 5954 websError(wp, 400, "Error getting unit/subunit\n"); 5955 return EINVAL; 5956 } 5957 5958 sprintf(nv_param, "wl%d_crypto", unit); 5959 5960 websWrite(wp, nvram_safe_get(nv_param)); 5961 5962 return 0; 5963} 5964 5965static int 5966ej_wl_wep(int eid, webs_t wp, int argc, char_t **argv) 5967{ 5968 char *temp; 5969 int unit = -1; 5970 int sub_unit = -1; 5971 char nv_param[NVRAM_MAX_PARAM_LEN]; 5972 5973 temp = nvram_get("wl_unit"); 5974 if (strlen(temp) == 0) { 5975 websError(wp, 400, "Error getting wl_unit\n"); 5976 return EINVAL; 5977 } 5978 5979 if (get_ifname_unit(temp, &unit, &sub_unit) != 0) { 5980 websError(wp, 400, "Error getting unit/subunit\n"); 5981 return EINVAL; 5982 } 5983 5984 sprintf(nv_param, "wl%d_wep", unit); 5985 5986 websWrite(wp, nvram_safe_get(nv_param)); 5987 5988 return 0; 5989} 5990 5991static unsigned int bits_count(unsigned int n) 5992{ 5993 unsigned int count = 0; 5994 5995 while (n > 0) { 5996 if (n & 1) 5997 count++; 5998 n >>= 1; 5999 } 6000 6001 return count; 6002} 6003 6004/* Writes "1" if Tx beamforming is supported. Otherwise, "0" */ 6005static int 6006ej_wl_txbf_capable(int eid, webs_t wp, int argc, char_t **argv) 6007{ 6008 char *name = NULL; 6009 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 6010 int txbf_capable = 0; 6011 wlc_rev_info_t revinfo; 6012 6013 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 6014 websError(wp, 400, "unit number variable doesn't exist\n"); 6015 return -1; 6016 } 6017 6018 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 6019 6020 /* Get revision info */ 6021 wl_ioctl(name, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)); 6022 6023 /* 6024 * Beamforming is available on core revs >= 40. Currently, 1-2 6025 * streams have beamforming. 6026 */ 6027 if (revinfo.corerev >= 40) { 6028 int txchain; 6029 6030 if (wl_iovar_getint(name, "txchain", &txchain)) 6031 return -1; 6032 6033 if (bits_count((unsigned int)txchain) > 1) { 6034 txbf_capable = 1; 6035 } 6036 } 6037 6038 return websWrite(wp, "%d", txbf_capable); 6039} 6040 6041/* 6042*/ 6043#ifdef __CONFIG_WFI__ 6044#define WPSM_WFI_CMD_NVNAME "wfi_cmd" 6045 6046/* Return WFI enabled STA list */ 6047static int 6048ej_wl_invite_list(int eid, webs_t wp, int argc, char_t **argv) 6049{ 6050 int i; 6051 char *sta_list, *wl_unit, *tmp1= NULL; 6052 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 6053 char *dest_ptr, *dest, *src_ptr; 6054 int count = 0, len = 0; 6055 6056 if(!nvram_match("wl_wfi_enable", "1" )) 6057 return 0; 6058 6059 nvram_set(WPSM_WFI_CMD_NVNAME, "list 0 1"); 6060 for (i = 0; i < 3; i++) { 6061 SLEEP(1); 6062 if (nvram_match(WPSM_WFI_CMD_NVNAME , "")) 6063 break; 6064 } 6065 6066 wl_unit = nvram_safe_get("wl_unit"); 6067 tmp1 = strchr(wl_unit, '.'); 6068 if (tmp1) { 6069 strncpy( tmp, wl_unit, (strlen(wl_unit) - strlen(tmp1)) ); 6070 tmp[strlen(wl_unit) - strlen(tmp1)]='\0'; 6071 sprintf(prefix,"wl%s_", tmp); 6072 } 6073 else 6074 sprintf(prefix,"wl%s_", wl_unit); 6075 6076 strcat_r(prefix, "wfi_list", tmp); 6077 sta_list = nvram_safe_get(tmp); 6078 6079 /* change '"' to '\''"' */ 6080 while(sta_list[len]) 6081 if (sta_list[len++] == '"') ++count; 6082 src_ptr = sta_list; 6083 dest = (char *) malloc(sizeof(char) * (count + len + 1)); 6084 if (dest == NULL) /* malloc failed */ 6085 return 0; 6086 dest_ptr = dest; 6087 6088 while(tmp1 = strchr(src_ptr, '"')) { 6089 int chunk_len = tmp1 - src_ptr; /* length of current chunk without " in it */ 6090 memcpy(dest_ptr, src_ptr, chunk_len); 6091 dest_ptr[chunk_len++] = '\\'; 6092 dest_ptr[chunk_len++] = '"'; 6093 dest_ptr += chunk_len; 6094 src_ptr = tmp1 +1; /* skip " too */ 6095 } 6096 strcpy(dest_ptr,src_ptr); /* yes, strcpy, copy rest of the string there is no " in it */ 6097 6098 len = websWrite(wp, dest); 6099 free(dest); 6100 return len; 6101 6102} 6103 6104static int 6105ej_wl_wfi_mode(int eid, webs_t wp, int argc, char_t **argv) 6106{ 6107 char tmp[32], *wl_unit, *wfi_mode; 6108 6109 wl_unit = nvram_safe_get("wl_unit"); 6110 sprintf(tmp, "wl%s_wps_mode", wl_unit); 6111 wfi_mode = nvram_safe_get(tmp); 6112 if(nvram_match("wl_wfi_enable", "1" )){ 6113 if (!strcmp("enabled", wfi_mode)) 6114 return websWrite(wp, "WPS mode is enabled on this BSS."); 6115 else 6116 return websWrite(wp, "WPS mode is not enabled on this BSS."); 6117 } 6118 return 0; 6119} 6120#endif /* __CONFIG_WFI__ */ 6121/* 6122*/ 6123 6124#ifdef __CONFIG_NAT__ 6125static char * 6126wan_name(int unit, char *prefix, char *name, int len) 6127{ 6128 char tmp[NVRAM_BUFSIZE], *desc; 6129 desc = nvram_safe_get(strcat_r(prefix, "desc", tmp)); 6130 snprintf(tmp, sizeof(tmp), "Connection %d", unit + 1); 6131 snprintf(name, len, "%s", !strcmp(desc, "") ? tmp : desc); 6132 return name; 6133} 6134 6135/* Return a list of wan connections (Connection <N>/<Connection Name>) */ 6136static int 6137ej_wan_list(int eid, webs_t wp, int argc, char_t **argv) 6138{ 6139 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 6140 int unit, ret = 0; 6141 6142 /* build wan connection name list */ 6143 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 6144 WAN_PREFIX(unit, prefix); 6145 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 6146 continue; 6147 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", unit, 6148 unit == atoi(nvram_safe_get("wan_unit")) ? "selected" : "", 6149 wan_name(unit, prefix, tmp, sizeof(tmp))); 6150 } 6151 6152 return ret; 6153} 6154#endif /* __CONFIG_NAT__ */ 6155 6156#ifdef __CONFIG_WPS__ 6157static int 6158ej_wps_current_mode(int eid, webs_t wp, int argc, char_t **argv, int wps_sta) 6159{ 6160 if (nvram_match( "wl_wps_mode", "enabled" )) 6161 { 6162 if (wps_sta) 6163 websWrite(wp, "Station"); 6164 else if (wps_is_oob() && !nvram_match("wps_oob_configured", "1")) 6165 websWrite(wp, "Unconfiged AP"); 6166 else if (wps_is_reg()) 6167 websWrite(wp, "AP with Built-in Registrar"); 6168 else 6169 websWrite(wp, "Proxing"); 6170 } 6171 else { 6172 if (wps_sta) 6173 { 6174 websWrite(wp, "Station Disabled"); 6175 return 0; 6176 } 6177 else { 6178 websWrite(wp, "AP Disabled"); 6179 return 0; 6180 } 6181 } 6182 6183 return 0; 6184} 6185 6186static int 6187ej_wps_process(int eid, webs_t wp, int argc, char_t **argv) 6188{ 6189 6190 char *status; 6191 6192 if (!nvram_match( "wl_wps_mode", "enabled" )) 6193 return 0; 6194 6195 status = nvram_safe_get("wps_proc_status"); 6196 6197 switch (atoi(status)) { 6198 case WPS_UI_ASSOCIATED: 6199 websWrite(wp, "Processing WPS start..."); 6200 break; 6201 case WPS_UI_OK: 6202 case WPS_UI_MSGDONE: 6203 websWrite(wp, "Success"); 6204 break; 6205 case WPS_UI_MSG_ERR: 6206 websWrite(wp, "Fail due to WPS message exchange error!"); 6207 break; 6208 case WPS_UI_TIMEOUT: 6209 websWrite(wp, "Fail due to WPS time out!"); 6210 break; 6211 case WPS_UI_PBCOVERLAP: 6212 websWrite(wp, "Fail due to WPS session overlap!"); 6213 break; 6214#ifdef __CONFIG_NFC__ 6215 case WPS_UI_NFC_WR_CFG: 6216 case WPS_UI_NFC_WR_PW: 6217 case WPS_UI_NFC_RD_CFG: 6218 case WPS_UI_NFC_RD_PW: 6219 websWrite(wp, "Please place your NFC token now."); 6220 break; 6221 case WPS_UI_NFC_WR_CPLT: 6222 websWrite(wp, "NFC write token successful, please remove the tag."); 6223 break; 6224 case WPS_UI_NFC_RD_CPLT: 6225 websWrite(wp, "NFC read token successful, please remove the tag."); 6226 break; 6227 case WPS_UI_NFC_HO_S: 6228 websWrite(wp, "Handover as selector."); 6229 break; 6230 case WPS_UI_NFC_HO_R: 6231 websWrite(wp, "Handover as requester."); 6232 break; 6233 case WPS_UI_NFC_HO_NDEF: 6234 websWrite(wp, "Handover done, please remove the peer."); 6235 break; 6236 case WPS_UI_NFC_HO_CPLT: 6237 websWrite(wp, "Handover successful."); 6238 break; 6239 case WPS_UI_NFC_OP_ERROR: 6240 websWrite(wp, "NFC operation fail. Code %d", wps_nfc_err_code); 6241 break; 6242 case WPS_UI_NFC_OP_STOP: 6243 websWrite(wp, "NFC operation stop."); 6244 break; 6245 case WPS_UI_NFC_OP_TO: 6246 websWrite(wp, "NFC operation timeout."); 6247 break; 6248 case WPS_UI_NFC_FM: 6249 websWrite(wp, "Formating NFC, please place your NFC token now!."); 6250 break; 6251 case WPS_UI_NFC_FM_CPLT: 6252 websWrite(wp, "Format NFC successful, please remove the tag."); 6253 break; 6254#endif /* __CONFIG_NFC__ */ 6255 default: 6256 websWrite(wp, "Init"); 6257 } 6258 6259 if (strcmp(wps_unit, nvram_safe_get("wl_unit"))== 0) { 6260 if (wps_config_command == WPS_UI_CMD_START) { 6261 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"STOPWPS\">"); 6262 6263 /* Add in PF #3, show "PBC Again" */ 6264 if (wps_method == WPS_UI_METHOD_PBC) { 6265 websWrite(wp, "<input type=\"hidden\" name=\"wps_action\" value=\"AddEnrollee\">"); 6266 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"PBC Again\">"); 6267 } 6268 } 6269#ifdef __CONFIG_NFC__ 6270 else if (wps_config_command == WPS_UI_CMD_NFC_WR_CFG || 6271 wps_config_command == WPS_UI_CMD_NFC_WR_PW) { 6272 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Write\">"); 6273 } 6274 else if (wps_config_command == WPS_UI_CMD_NFC_RD_CFG || 6275 wps_config_command == WPS_UI_CMD_NFC_RD_PW) { 6276 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Read\">"); 6277 } 6278 else if (wps_config_command == WPS_UI_CMD_NFC_HO_S || 6279 wps_config_command == WPS_UI_CMD_NFC_HO_R) { 6280 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Hand Over\">"); 6281 } 6282#endif /* __CONFIG_NFC__ */ 6283 } 6284 return 0; 6285} 6286 6287extern void RAND_bytes(unsigned char *buf, int num); 6288 6289/* generate a printable key string */ 6290static int 6291wps_gen_key(char *key, int key_len) 6292{ 6293 unsigned short key_length; 6294 unsigned char random_key[64] = {0}; 6295 int i = 0; 6296 6297 if (key == NULL || key_len == 0) 6298 return -1; 6299 6300 /* key_length < 16 */ 6301 RAND_bytes((unsigned char *)&key_length, sizeof(key_length)); 6302 key_length = (unsigned short)((((long)key_length + 56791)*13579)%8) + 8; 6303 6304 while (i < key_length) { 6305 RAND_bytes(&random_key[i], 1); 6306 if ((islower(random_key[i]) || isdigit(random_key[i])) && 6307 (random_key[i] < 0x7f)) { 6308 i++; 6309 } 6310 } 6311 memcpy(key, random_key, key_len); 6312 return 0; 6313} 6314 6315static int 6316wps_gen_ssid(char *ssid, int ssid_len) 6317{ 6318 int i; 6319 char mac[18] = {0}; 6320 unsigned short ssid_length; 6321 unsigned char random_ssid[33] = {0}; 6322 char prefix[] = "wlXXXXXXXXXX_"; 6323 char vif[64]; 6324 char *value; 6325 6326 if (ssid == NULL || ssid_len == 0) 6327 return -1; 6328 6329 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 6330 return -1; 6331 } 6332 snprintf(vif, sizeof(vif), "%shwaddr", prefix); 6333 value = nvram_get(vif); 6334 strncpy(mac, value, sizeof(mac) - 1); 6335 6336 RAND_bytes((unsigned char *)&ssid_length, sizeof(ssid_length)); 6337 ssid_length = (unsigned short)((((long)ssid_length + 56791)*13579)%8) + 1; 6338 6339 RAND_bytes((unsigned char *)random_ssid, ssid_length); 6340 6341 for (i = 0; i < ssid_length; i++) { 6342 if ((random_ssid[i] < 48) || (random_ssid[i] > 57)) 6343 random_ssid[i] = random_ssid[i]%9 + 48; 6344 } 6345 6346 random_ssid[ssid_length++] = tolower(mac[6]); 6347 random_ssid[ssid_length++] = tolower(mac[7]); 6348 random_ssid[ssid_length++] = tolower(mac[9]); 6349 random_ssid[ssid_length++] = tolower(mac[10]); 6350 random_ssid[ssid_length++] = tolower(mac[12]); 6351 random_ssid[ssid_length++] = tolower(mac[13]); 6352 random_ssid[ssid_length++] = tolower(mac[15]); 6353 random_ssid[ssid_length++] = tolower(mac[16]); 6354 6355 memset(ssid, 0, ssid_len); 6356 sprintf(ssid, "Broadcom_"); 6357 6358 strncat(ssid, (char *)random_ssid, 33 - strlen(ssid) - 1); 6359 6360 return 0; 6361} 6362 6363static int 6364ej_wps_credentials(int eid, webs_t wp, int argc, char_t **argv, int wps_sta) 6365{ 6366 int oob; 6367 char prefix[] = "wlXXXXXXXXXX_"; 6368 char *value, *next; 6369 char tmp[64]; 6370 int configable = FALSE; 6371 char ssid[33] = {0}; 6372 char psk[65] = {0}; 6373 int akm = 0, crypto = 0; 6374 6375 oob = wps_is_oob(); 6376 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 6377 websError(wp, 400, "unit number variable doesn't exist\n"); 6378 return -1; 6379 } 6380 6381 if (wps_action == WPS_UI_ACT_ADDENROLLEE || wps_action == WPS_UI_ACT_STA_CONFIGAP) 6382 configable = TRUE; 6383 6384 /* Get current SSID */ 6385 snprintf(tmp, sizeof(tmp), "%sssid", prefix); 6386 value = nvram_safe_get(tmp); 6387 strncpy(ssid, value, sizeof(ssid)-1); 6388 ssid[sizeof(ssid) - 1] = '\0'; 6389 6390 /* Get current AKM */ 6391 snprintf(tmp, sizeof(tmp), "%sakm", prefix); 6392 value = nvram_safe_get(tmp); 6393 foreach(tmp, value, next) { 6394 if (!strcmp(tmp, "psk")) 6395 akm |= 1; 6396 if (!strcmp(tmp, "psk2")) 6397 akm |= 2; 6398 } 6399 6400 /* Encryption type */ 6401 snprintf(tmp, sizeof(tmp), "%scrypto", prefix); 6402 value = nvram_safe_get(tmp); 6403 if (!strcmp(value, "aes")) 6404 crypto = 1; 6405 else if (!strcmp(value, "tkip+aes")) 6406 crypto = 2; 6407 /* psk */ 6408 snprintf(tmp, sizeof(tmp), "%swpa_psk", prefix); 6409 value = nvram_safe_get(tmp); 6410 strncpy(psk, value, sizeof(psk) - 1); 6411 psk[sizeof(psk) - 1] = '\0'; 6412 6413 /* If the credentials can be configured, also display the current credentials. */ 6414 if (configable) { 6415 /* SSID */ 6416 websWrite(wp, "<tr>"); 6417 websWrite(wp, "<th width=\"310\">Current SSID: </th><td> </td>\n"); 6418 websWrite(wp, "<td>%s</td>\n", translate_ssid(ssid)); 6419 /* AKM */ 6420 websWrite(wp, "<tr>"); 6421 websWrite(wp, "<th width=\"310\">Current Authentication Type: </th>\n"); 6422 websWrite(wp, "<td> </td>\n"); 6423 websWrite(wp, "<td>%s</td>\n", (akm == 0) ? "Open" : (akm == 2) ? "WPA2-PSK" : "WPA/WPA2-PSK"); 6424 /* Crypto */ 6425 websWrite(wp, "<tr>"); 6426 websWrite(wp, "<th width=\"310\">Current Encryption Type: </th>\n"); 6427 websWrite(wp, "<td> </td>\n"); 6428 websWrite(wp, "<td>%s</td>\n", (akm == 0) ? "" : (crypto == 1) ? "AES" : "TKIP+AES"); 6429 /* PSK */ 6430 websWrite(wp, "<tr>"); 6431 websWrite(wp, "<th width=\"310\">Current PSK: </th><td> </td>\n"); 6432 websWrite(wp, "<td><A HREF=\"javascript:wps_current_psk_window();\">Click here to display</A></td>\n"); 6433 websWrite(wp, "<tr><th width=\"310\"></th><td> </td><td></td></tr>\n"); 6434 } 6435 6436 /* Show SSID */ 6437 if (oob && configable) { 6438 if ((value = nvram_get("wps_randomssid"))) { 6439 strncpy(random_ssid, value, sizeof(random_ssid) - 1 ); 6440 random_ssid[sizeof(random_ssid) - 1] = '\0'; 6441 } 6442 else if (random_ssid[0] == 0) 6443 wps_gen_ssid(random_ssid, sizeof(random_ssid)); 6444 strcpy(ssid, random_ssid); 6445 akm = 2; /* Default to WPA2 */ 6446 6447 /* When I test with WSC 1.0 NXP NFC STA, APUT send crypto type in AES 6448 * but APUT will save in tkip+aes because in wpsap_close_session() it said 6449 * " Set AES+TKIP in OOB mode, otherwise in WPS test plan 4.2.4 the 6450 * Broadcom legacy is not able to associate in TKIP". 6451 * It results the NXP STA cannot authenticate with APUT. So, I change 6452 * the Default to TKIP+AES, but I'm not sure is it have other side effect. 6453 */ 6454 crypto = 2; /* Default to TKIP + AES */ 6455 6456 if ((value = nvram_get("wps_randomkey"))) { 6457 strncpy(random_psk, value, sizeof(random_psk) - 1); 6458 random_psk[sizeof(random_psk) - 1] = '\0'; 6459 } 6460 else if (random_psk[0] == 0) 6461 wps_gen_key(random_psk, sizeof(random_psk)); 6462 strcpy(psk, random_psk); 6463 } 6464 6465 /* Config SSID */ 6466 websWrite(wp, "<tr><th width=\"310\""); 6467 websWrite(wp, "onMouseOver=\"return overlib(\'Sets the Network Name (also known as SSID) of this network.\', LEFT);\""); 6468 websWrite(wp, "onMouseOut=\"return nd();\">SSID: </th>\n"); 6469 websWrite(wp, "<td> </td>\n"); 6470 websWrite(wp, "<td><input name=\"wps_ssid\" value=\"%s\" size=\"32\" maxlength=\"32\"%s></td></tr>\n", 6471 translate_ssid(ssid), (configable ? "" : " disabled")); 6472 6473 /* Config AKM */ 6474 websWrite(wp, "<tr><th onmouseover=\"return overlib(\'Select WPS Authentication Type\', LEFT);\" onmouseout=\"return nd();\" width=\"310\">"); 6475 websWrite(wp, "Authentication Type: </th><td> </td>\n"); 6476 websWrite(wp, "<td><select name=\"wps_akm\" onClick=\"wps_akm_change()\"%s>", configable ? "" : "disabled"); 6477 websWrite(wp, "<option value=\"\"%s>Open</option>", 6478 akm == 0 ? " selected=\"selected\"" : ""); 6479 websWrite(wp, "<option value=\"psk2\"%s>WPA2-PSK</option>", 6480 akm == 2 ? " selected=\"selected\"" : ""); 6481 websWrite(wp, "<option value=\"psk psk2\"%s>WPA/WPA2-PSK</option></select>\n", 6482 akm == 3 ? " selected=\"selected\"" : ""); 6483 websWrite(wp, "</td></tr>\n"); 6484 /* Config Encryption */ 6485 websWrite(wp, "<tr><th onmouseover=\"return overlib(\'Select WPS Encryption Type\', LEFT);\" onmouseout=\"return nd();\" width=\"310\">"); 6486 websWrite(wp, "Encryption Type: </th><td> </td>\n"); 6487 websWrite(wp, "<td><select name=\"wps_crypto\"%s>", configable ? "" : "disabled"); 6488 websWrite(wp, "<option value=\"aes\"%s>AES</option>", 6489 crypto == 1 ? " selected=\"selected\"" : ""); 6490 websWrite(wp, "<option value=\"tkip+aes\"%s>TKIP+AES</option></select>\n", 6491 crypto == 2 ? " selected=\"selected\"" : ""); 6492 websWrite(wp, "</td></tr>\n"); 6493 6494 /* Config PSK */ 6495 websWrite(wp, "<tr><th width=\"310\""); 6496 websWrite(wp, " onMouseOver=\"return overlib(\'Sets the WPA passphrase.\', LEFT);\"onMouseOut=\"return nd();\">"); 6497 websWrite(wp, "WPA passphrase: </th>\n"); 6498 websWrite(wp, "<td> </td>\n"); 6499 websWrite(wp, "<td><input name=\"wps_psk\" value=\"%s\" size=\"32\"" 6500 " maxlength=\"32\" type=\"password\"%s><A HREF=\"javascript:wps_psk_window();\">Click here to display</A></td>\n", 6501 psk, (configable ? "" : "disabled")); 6502 websWrite(wp, "</tr>\n"); 6503 6504 if (!wps_sta && wps_config_command == WPS_UI_CMD_NONE) { 6505 websWrite(wp, "<tr><th width=\"310\"></th><td> </td>\n"); 6506 websWrite(wp, "<td><input type=\"submit\" name=\"action\" value=\"Save Credentials\"" 6507 " onClick=\"return pre_submit();\">" 6508 "  <input type=\"submit\" name=\"action\" value=\"Reset To OOB\"></td></tr>\n"); 6509 } 6510 return 0; 6511} 6512static int 6513ej_wps_start(int eid, webs_t wp, int argc, char_t **argv, int wps_sta) 6514{ 6515 if (wps_config_command == WPS_UI_CMD_NONE) { 6516 if (!wps_sta) { 6517 websWrite(wp, "<tr><th width=\"310\"></th><td> </td>"); 6518 websWrite(wp, "<td><input type=\"submit\" name=\"action\" value=\"Add Enrollee\">"); 6519 websWrite(wp, "</td> </tr>\n"); 6520 } 6521 else { 6522 websWrite(wp, "<tr><th width=\"310\"></th><td> </td>"); 6523 websWrite(wp, "<td><input type=\"submit\" name=\"action\" value=\"Start\" onClick=\"return pre_submit();\"></td></tr>\n"); 6524 } 6525 } 6526 6527 return 0; 6528} 6529 6530static int 6531wps_enr_display_aplist(wps_ap_list_info_t *ap) 6532{ 6533 char eastr[ETHER_ADDR_STR_LEN]; 6534 int i=0; 6535 6536 if(!ap) 6537 return 0; 6538 6539 printf("-------------------------------------\n"); 6540 while(ap->used == TRUE ) { 6541 printf(" %d : ", i); 6542 printf("SSID:%s ", ap->ssid); 6543 printf("BSSID:%s ", ether_etoa(ap->BSSID, eastr)); 6544 printf("Channel:%d ", ap->channel); 6545 printf("Configured:%s ", ap->scstate?"True":"False"); 6546 if(ap->wep) 6547 printf("WEP"); 6548 printf("\n"); 6549 ap++; 6550 i++; 6551 } 6552 6553 printf("-------------------------------------\n"); 6554 return 0; 6555} 6556 6557static uint8* 6558wps_enr_parse_wsc_tlvs(uint8 *tlv_buf, int buflen, uint16 type) 6559{ 6560 uint8 *cp; 6561 uint16 *tag; 6562 int totlen; 6563 uint16 len; 6564 uint8 buf[4]; 6565 6566 cp = tlv_buf; 6567 totlen = buflen; 6568 6569 /* TLV: 2 bytes for T, 2 bytes for L */ 6570 while (totlen >= 4) { 6571 memcpy(buf, cp, 4); 6572 tag = (uint16 *)buf; 6573 6574 if (ntohs(tag[0]) == type) 6575 return (cp + 4); 6576 len = ntohs(tag[1]); 6577 cp += (len + 4); 6578 totlen -= (len + 4); 6579 } 6580 6581 return NULL; 6582} 6583 6584static uint8 * 6585wps_enr_parse_ie_tlvs(uint8 *tlv_buf, int buflen, uint key) 6586{ 6587 uint8 *cp; 6588 int totlen; 6589 6590 cp = tlv_buf; 6591 totlen = buflen; 6592 6593 /* find tagged parameter */ 6594 while (totlen >= 2) { 6595 uint tag; 6596 int len; 6597 6598 tag = *cp; 6599 len = *(cp +1); 6600 6601 /* validate remaining totlen */ 6602 if ((tag == key) && (totlen >= (len + 2))) 6603 return (cp); 6604 6605 cp += (len + 2); 6606 totlen -= (len + 2); 6607 } 6608 6609 return NULL; 6610} 6611 6612static bool 6613wps_enr_wl_is_wps_ie(uint8 **wpaie, uint8 **tlvs, uint *tlvs_len, char *configured) 6614{ 6615 uint8 *ie = *wpaie; 6616 uint8 *data; 6617 6618 /* If the contents match the WPA_OUI and type=1 */ 6619 if ((ie[1] >= 6) && !memcmp(&ie[2], WPA_OUI "\x04", 4)) { 6620 ie += 6; 6621 data = wps_enr_parse_wsc_tlvs(ie, *tlvs_len-6, 0x1044); 6622 if (data && *data == 0x01) 6623 *configured = FALSE; 6624 else 6625 *configured = TRUE; 6626 return TRUE; 6627 } 6628 6629 /* point to the next ie */ 6630 ie += ie[1] + 2; 6631 /* calculate the length of the rest of the buffer */ 6632 *tlvs_len -= (int)(ie - *tlvs); 6633 /* update the pointer to the start of the buffer */ 6634 *tlvs = ie; 6635 6636 return FALSE; 6637} 6638 6639static bool 6640wps_enr_is_wps_ies(uint8* cp, uint len, char *configured) 6641{ 6642 uint8 *parse = cp; 6643 uint parse_len = len; 6644 uint8 *wpaie; 6645 6646 while ((wpaie = wps_enr_parse_ie_tlvs(parse, parse_len, DOT11_MNG_WPA_ID))) 6647 if (wps_enr_wl_is_wps_ie(&wpaie, &parse, &parse_len, configured)) 6648 break; 6649 if (wpaie) 6650 return TRUE; 6651 else 6652 return FALSE; 6653} 6654 6655static int 6656wps_enr_get_aplist(wps_ap_list_info_t *list_in, wps_ap_list_info_t *list_out ) 6657{ 6658 wps_ap_list_info_t *ap_in = &list_in[0]; 6659 wps_ap_list_info_t *ap_out = &list_out[0]; 6660 int i=0, wps_apcount = 0; 6661 char configured; 6662 6663 /* ignore hidden SSID AP */ 6664 while(ap_in->used == TRUE && ap_in->ssidLen && i < WPS_ENR_MAX_AP_SCAN_LIST_LEN) { 6665 if(TRUE == wps_enr_is_wps_ies(ap_in->ie_buf, ap_in->ie_buflen, &configured)) { 6666 ap_in->scstate = configured; 6667 memcpy(ap_out, ap_in, sizeof(wps_ap_list_info_t)); 6668 wps_apcount++; 6669 ap_out = &list_out[wps_apcount]; 6670 } 6671 i++; 6672 ap_in = &list_in[i]; 6673 } 6674 /* in case of on-the-spot filtering, make sure we stop the list */ 6675 if(wps_apcount < WPS_ENR_MAX_AP_SCAN_LIST_LEN) 6676 ap_out->used = 0; 6677 6678 return wps_apcount; 6679} 6680 6681/* WL_NUMCHANNELS is deemed a "bad word", define a local one */ 6682#define NUMCHANS 64 6683 6684static char * 6685wps_enr_get_scan_results(char *ifname) 6686{ 6687 int ret, retry_times = 0; 6688 wl_scan_params_t *params; 6689 wl_scan_results_t *list = (wl_scan_results_t*)scan_result; 6690 int params_size = WL_SCAN_PARAMS_FIXED_SIZE + NUMCHANS * sizeof(uint16); 6691 int org_scan_time = 20, scan_time = 40; 6692 6693 params = (wl_scan_params_t*)malloc(params_size); 6694 if (params == NULL) { 6695 return NULL; 6696 } 6697 6698 memset(params, 0, params_size); 6699 params->bss_type = DOT11_BSSTYPE_ANY; 6700 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); 6701 params->scan_type = -1; 6702 params->nprobes = -1; 6703 params->active_time = -1; 6704 params->passive_time = -1; 6705 params->home_time = -1; 6706 params->channel_num = 0; 6707 6708 /* extend scan channel time to get more AP probe resp */ 6709 wl_ioctl(ifname, WLC_GET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 6710 if (org_scan_time < scan_time) 6711 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &scan_time, sizeof(scan_time)); 6712 6713retry: 6714 ret = wl_ioctl(ifname, WLC_SCAN, params, params_size); 6715 if (ret < 0) { 6716 if (retry_times++ < WPS_ENR_SCAN_RETRY_TIMES) { 6717 printf("set scan command failed, retry %d\n", retry_times); 6718 SLEEP(1); 6719 goto retry; 6720 } 6721 } 6722 6723 SLEEP(2); 6724 6725 list->buflen = WPS_ENR_DUMP_BUF_LEN; 6726 ret = wl_ioctl(ifname, WLC_SCAN_RESULTS, scan_result, WPS_ENR_DUMP_BUF_LEN); 6727 if (ret < 0 && retry_times++ < WPS_ENR_SCAN_RETRY_TIMES) { 6728 printf("get scan result failed, retry %d\n", retry_times); 6729 SLEEP(1); 6730 goto retry; 6731 } 6732 6733 free(params); 6734 6735 /* restore original scan channel time */ 6736 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 6737 6738 if (ret < 0) 6739 return NULL; 6740 6741 return scan_result; 6742} 6743 6744static wps_ap_list_info_t * 6745wps_enr_create_aplist() 6746{ 6747 char *name = NULL; 6748 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 6749 wl_scan_results_t *list = (wl_scan_results_t*)scan_result; 6750 wl_bss_info_t *bi; 6751 wl_bss_info_107_t *old_bi; 6752 uint i, wps_ap_count = 0; 6753 6754 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) 6755 return NULL; 6756 6757 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 6758 6759 if (wps_enr_get_scan_results(name) == NULL) 6760 return NULL; 6761 6762 selected_ap = NULL; 6763 6764 memset(ap_list, 0, sizeof(ap_list)); 6765 if (list->count == 0) 6766 return 0; 6767 else if (list->version != WL_BSS_INFO_VERSION && 6768 list->version != LEGACY_WL_BSS_INFO_VERSION) { 6769 /* fprintf(stderr, "Sorry, your driver has bss_info_version %d " 6770 "but this program supports only version %d.\n", 6771 list->version, WL_BSS_INFO_VERSION); */ 6772 return NULL; 6773 } 6774 6775 bi = list->bss_info; 6776 for (i = 0; i < list->count; i++) { 6777 /* Convert version 107 to 108 */ 6778 if (bi->version == LEGACY_WL_BSS_INFO_VERSION) { 6779 old_bi = (wl_bss_info_107_t *)bi; 6780 bi->chanspec = CH20MHZ_CHSPEC(old_bi->channel); 6781 bi->ie_length = old_bi->ie_length; 6782 bi->ie_offset = sizeof(wl_bss_info_107_t); 6783 } 6784 if (bi->ie_length) { 6785 if(wps_ap_count < WPS_ENR_MAX_AP_SCAN_LIST_LEN){ 6786 ap_list[wps_ap_count].used = TRUE; 6787 memcpy(ap_list[wps_ap_count].BSSID, (uint8 *)&bi->BSSID, 6); 6788 strncpy((char *)ap_list[wps_ap_count].ssid, (char *)bi->SSID, bi->SSID_len); 6789 ap_list[wps_ap_count].ssid[bi->SSID_len] = '\0'; 6790 ap_list[wps_ap_count].ssidLen= bi->SSID_len; 6791 ap_list[wps_ap_count].ie_buf = (uint8 *)(((uint8 *)bi) + bi->ie_offset); 6792 ap_list[wps_ap_count].ie_buflen = bi->ie_length; 6793 ap_list[wps_ap_count].channel = (uint8)(bi->chanspec & WL_CHANSPEC_CHAN_MASK); 6794 ap_list[wps_ap_count].wep = bi->capability & DOT11_CAP_PRIVACY; 6795 wps_ap_count++; 6796 } 6797 } 6798 bi = (wl_bss_info_t*)((int8*)bi + bi->length); 6799 } 6800 6801 scanned = 1; 6802 return ap_list; 6803} 6804 6805static int 6806wl_wpsEnrScan() 6807{ 6808 if (wps_config_command == WPS_UI_CMD_NONE) 6809 wps_enr_create_aplist(); 6810 6811 return 0; 6812} 6813 6814static wps_ap_list_info_t * 6815wps_enr_get_selected_ap(int index) 6816{ 6817 int i = 0; 6818 wps_ap_list_info_t *ap; 6819 6820 ap = ap_list; 6821 while(ap->used == TRUE ) { 6822 if (i == index) 6823 return ap; 6824 ap++; 6825 i++; 6826 } 6827 return NULL; 6828} 6829 6830static int 6831ej_wps_enr_scan_result(int eid, webs_t wp, int argc, char_t **argv) 6832{ 6833 int i = 0, ret = 0; 6834 unsigned char macstr[18]; 6835 wps_ap_list_info_t *wpsaplist, *ap; 6836 6837 if (!scanned && nvram_match( "wl_wps_mode", "disabled" )) { 6838 websWrite(wp, "<option value=\"-1\" selected>None</option>"); 6839 wps_ap_num = 0; 6840 return 0; 6841 } 6842 else if (!scanned) 6843 wps_enr_create_aplist(); 6844 6845 wpsaplist = ap_list; 6846 wps_enr_get_aplist(wpsaplist, wpsaplist); 6847 wps_enr_display_aplist(wpsaplist); 6848 6849 ap = wpsaplist; 6850 while(ap->used == TRUE ) { 6851 sprintf((char *)macstr, "%02X:%02X:%02X:%02X:%02X:%02X", 6852 ap->BSSID[0], ap->BSSID[1], ap->BSSID[2], 6853 ap->BSSID[3], ap->BSSID[4], ap->BSSID[5]); 6854 if (selected_ap == NULL) { 6855 ret += websWrite(wp, "<option value=\"%d\" %s>%s (%s)</option>\n", i, 6856 (i == 0) ? "selected" : "", 6857 translate_ssid((char *)ap->ssid), 6858 macstr); 6859 } 6860 else { 6861 ret += websWrite(wp, "<option value=\"%d\" %s>%s (%s)</option>\n", i, 6862 (selected_ap == ap) ? "selected" : "", 6863 translate_ssid((char *)ap->ssid), 6864 macstr); 6865 } 6866 ap++; 6867 i++; 6868 } 6869 6870 if (!ret) 6871 websWrite(wp, "<option value=\"-1\" selected>None</option>"); 6872 6873 wps_ap_num = i; 6874 return 0; 6875} 6876 6877static int 6878ej_wps_enr_process(int eid, webs_t wp, int argc, char_t **argv) 6879{ 6880 6881 char *status; 6882 6883 status = nvram_safe_get("wps_proc_status"); 6884 6885 switch (atoi(status)) { 6886 case WPS_UI_ASSOCIATED: 6887 websWrite(wp, "Start enrolling..."); 6888 break; 6889 case WPS_UI_OK: 6890 websWrite(wp, "Succeeded..."); 6891 break; 6892 case WPS_UI_MSG_ERR: 6893 websWrite(wp, "Failed..."); 6894 break; 6895 case WPS_UI_TIMEOUT: 6896 websWrite(wp, "Failed (timeout)..."); 6897 break; 6898 case WPS_UI_PBCOVERLAP: 6899 websWrite(wp, "Failed (pbc overlap)..."); 6900 break; 6901 case WPS_UI_FIND_PBC_AP: 6902 websWrite(wp, "Finding a pbc access point..."); 6903 break; 6904 case WPS_UI_ASSOCIATING: 6905 websWrite(wp, "Assciating with access point..."); 6906 break; 6907#ifdef __CONFIG_NFC__ 6908 case WPS_UI_NFC_WR_CFG: 6909 case WPS_UI_NFC_WR_PW: 6910 case WPS_UI_NFC_RD_CFG: 6911 case WPS_UI_NFC_RD_PW: 6912 websWrite(wp, "Please place your NFC token now."); 6913 break; 6914 case WPS_UI_NFC_WR_CPLT: 6915 websWrite(wp, "NFC write token successful, please remove the tag."); 6916 break; 6917 case WPS_UI_NFC_RD_CPLT: 6918 websWrite(wp, "NFC read token successful, please remove the tag."); 6919 break; 6920 case WPS_UI_NFC_HO_S: 6921 websWrite(wp, "Handover as selector."); 6922 break; 6923 case WPS_UI_NFC_HO_R: 6924 websWrite(wp, "Handover as requester."); 6925 break; 6926 case WPS_UI_NFC_HO_NDEF: 6927 websWrite(wp, "Handover done, please remove the peer."); 6928 break; 6929 case WPS_UI_NFC_HO_CPLT: 6930 websWrite(wp, "Handover successful."); 6931 break; 6932 case WPS_UI_NFC_OP_ERROR: 6933 websWrite(wp, "NFC operation fail. Code %d", wps_nfc_err_code); 6934 break; 6935 case WPS_UI_NFC_OP_STOP: 6936 websWrite(wp, "NFC operation stop."); 6937 break; 6938 case WPS_UI_NFC_OP_TO: 6939 websWrite(wp, "NFC operation timeout."); 6940 break; 6941 case WPS_UI_NFC_FM: 6942 websWrite(wp, "Formating NFC, please place your NFC token now!"); 6943 break; 6944 case WPS_UI_NFC_FM_CPLT: 6945 websWrite(wp, "Format NFC successful, please remove the tag."); 6946 break; 6947#endif /* __CONFIG_NFC__ */ 6948 default: 6949 websWrite(wp, "Init"); 6950 break; 6951 } 6952 6953 if (strcmp(wps_unit, nvram_safe_get("wl_unit"))== 0) { 6954 if (wps_config_command == WPS_UI_CMD_START) { 6955 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"STOPWPS\">"); 6956 6957 /* WPS 2.0, test plan 5.1.7, show "STA PBC Again" */ 6958 if (wps_method == WPS_UI_METHOD_PBC) { 6959 websWrite(wp, "<input type=\"hidden\" name=\"wps_action\" value=\"Enroll\">"); 6960 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"PBC Again\">"); 6961 } 6962 } 6963#ifdef __CONFIG_NFC__ 6964 else if (wps_config_command == WPS_UI_CMD_NFC_WR_CFG || 6965 wps_config_command == WPS_UI_CMD_NFC_WR_PW) { 6966 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Write\">"); 6967 } 6968 else if (wps_config_command == WPS_UI_CMD_NFC_RD_CFG || 6969 wps_config_command == WPS_UI_CMD_NFC_RD_PW) { 6970 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Read\">"); 6971 } 6972 else if (wps_config_command == WPS_UI_CMD_NFC_HO_S || 6973 wps_config_command == WPS_UI_CMD_NFC_HO_R) { 6974 websWrite(wp, " <input type=\"submit\" name=\"action\" value=\"Stop NFC Hand Over\">"); 6975 } 6976#endif /* __CONFIG_NFC__ */ 6977 } 6978 6979 return 0; 6980} 6981#endif /* __CONFIG_WPS__ */ 6982 6983/* write "selected" to page if the argument matches the current 6984 wl_ure setting */ 6985static int 6986ej_ure_list(int eid, webs_t wp, int argc, char_t **argv) 6987{ 6988 char *temp; 6989 int match_value; 6990 int nv_value; 6991 6992 if (ejArgs(argc, argv, "%d", &match_value) < 1) { 6993 websError(wp, 400, "Insufficient args\n"); 6994 return EINVAL; 6995 } 6996 6997 temp = nvram_safe_get("wl_ure"); 6998 if(strlen( temp ) == 0) { 6999 if( match_value == 0 ) 7000 { 7001 /* treat empty string as "0" */ 7002 websWrite(wp, "selected" ); 7003 } 7004 return 0; 7005 } 7006 7007 nv_value = atoi( temp ); 7008 if( nv_value == match_value) { 7009 websWrite(wp, "selected" ); 7010 } 7011 7012 return 0; 7013} 7014 7015/* Return wlX_ure setting for the current wireless interface. If 7016 the current wireless interface is a virtual interface, return 7017 the value of the parent interface 7018*/ 7019static int 7020ej_ure_enabled(int eid, webs_t wp, int argc, char_t **argv) 7021{ 7022 char *temp; 7023 int unit = -1; 7024 int sub_unit = -1; 7025 char nv_param[NVRAM_MAX_PARAM_LEN]; 7026 7027 temp = nvram_get("wl_unit"); 7028 if(strlen( temp ) == 0) { 7029 websError(wp, 400, "Error getting wl_unit\n"); 7030 return EINVAL; 7031 } 7032 7033 if( get_ifname_unit( temp, &unit, &sub_unit ) != 0 ) { 7034 websError(wp, 400, "Error getting unit/subunit\n"); 7035 return EINVAL; 7036 } 7037 7038 sprintf( nv_param, "wl%d_ure", unit ); 7039 temp = nvram_safe_get( nv_param ); 7040 if( strncmp( temp, "1", 1 ) == 0 ) { 7041 websWrite(wp, "\"1\""); 7042 } 7043 else { 7044 websWrite(wp, "\"0\""); 7045 } 7046 7047 return 0; 7048} 7049 7050/* Write "1" or "0" for URE enabled on any interface to the web page 7051 1 - URE enabled for an interface 7052 0 - URE not enabled for any interface 7053 7054 This is currently used on the Basic web page for helping to decide 7055 whether "router_disable" should be greyed-out or not. We prevent 7056 changing the router mode while in URE to minimize the complexity of 7057 mode changes that require network interfaces to move from the LAN to the 7058 WAN and vice-versa. 7059*/ 7060static int 7061ej_ure_any_enabled(int eid, webs_t wp, int argc, char_t **argv) 7062{ 7063 if( ure_any_enabled() ) 7064 websWrite(wp, "\"1\""); 7065 else 7066 websWrite(wp, "\"0\""); 7067 7068 return 0; 7069} 7070 7071/* Write "1" for IBSS mode, "0" for Infrastructure based on wlX_infra NVRAM setting. 7072 * This will always write "0" for a virtual/secondary interface. We don't currently support 7073 * IBSS mode for a non-primary BSS config. 7074 */ 7075static int 7076ej_wl_ibss_mode(int eid, webs_t wp, int argc, char_t **argv) 7077{ 7078 char *temp; 7079 int unit = -1; 7080 int sub_unit = -1; 7081 int sta_mode = FALSE; 7082 char nv_param[NVRAM_MAX_PARAM_LEN]; 7083 7084 temp = nvram_get("wl_unit"); 7085 if(strlen( temp ) == 0) { 7086 websError(wp, 400, "Error getting wl_unit\n"); 7087 return EINVAL; 7088 } 7089 7090 if( get_ifname_unit( temp, &unit, &sub_unit ) != 0 ) { 7091 websError(wp, 400, "Error getting unit/subunit\n"); 7092 return EINVAL; 7093 } 7094 7095 /* In order for wlX_infra setting to be meaningful, we must be in a valid STA mode. */ 7096 sprintf( nv_param, "wl%d_mode", unit ); 7097 temp = nvram_safe_get( nv_param ); 7098 if ((strncmp(temp, "wet", 3) == 0) || (strncmp(temp, "mac_spoof", 3) == 0) || 7099 (strncmp(temp, "sta", 3) == 0)) { 7100 sta_mode = TRUE; 7101 } 7102 7103 sprintf( nv_param, "wl%d_infra", unit ); 7104 temp = nvram_safe_get( nv_param ); 7105 7106 /* Write "0" if non-STA mode OR Infrastructure STA */ 7107 if (!sta_mode || (strncmp(temp, "1", 1) == 0)) { 7108 websWrite(wp, "\"0\""); 7109 } else if (strncmp(temp, "0", 1) == 0) { 7110 websWrite(wp, "\"1\""); 7111 } else { 7112 websError(wp, 400, "Invalid wl%d_infra setting in NVRAM\n", unit); 7113 return EINVAL; 7114 } 7115 7116 return 0; 7117} 7118 7119/* Display DFS Reentry parameters */ 7120static int 7121ej_dfs_reentry_display(int eid, webs_t wp, int argc, char_t **argv) 7122{ 7123#define NWINS 3 7124 static struct { 7125 const char *keyword; 7126 const char *description; 7127 } wins[NWINS] = { 7128 { "acs_dfsr_immediate", "Immediate Reentry" }, 7129 { "acs_dfsr_deferred", "Deferred Reentry" }, 7130 { "acs_dfsr_activity", "Channel Active" } 7131 }; 7132 static char *table_start = 7133 "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n" 7134 "<tr>" 7135 "<th width=\"310\"" 7136 " onMouseOver=\"return overlib('DFS Reentry Window parameters', LEFT);\"" 7137 " onMouseOut=\"return nd();\">" 7138 "DFS Reentry Window Settings " 7139 "</th>" 7140 "<td> </td>" 7141 "<td class=\"label\">Seconds</td>" 7142 "<td class=\"label\">Threshold</td>" 7143 "</tr>\n"; 7144 static char *table_entry = 7145 "<tr>" 7146 "<th width=\"310\"" 7147 " onMouseOver=\"return overlib('DFS %s window parameters', LEFT);\"" 7148 " onMouseOut=\"return nd();\">" 7149 "%s: " 7150 "</th>" 7151 "<input type=\"hidden\" name=\"wl_%s\" value=\"1\">" /* needed to call validateFn */ 7152 "<td> </td>" 7153 "<td>" 7154 "<input name=\"wl_%s_sec\" " 7155 " onMouseOver=\"return overlib('Window size in seconds', LEFT);\"" 7156 " onMouseOut=\"return nd();\"" 7157 " value=\"%u\" size=\"8\" maxlength=\"8\">" 7158 "</td>" 7159 "<td>" 7160 "<input name=\"wl_%s_thr\" " 7161 " onMouseOver=\"return overlib('Window threshold value', LEFT);\"" 7162 " onMouseOut=\"return nd();\"" 7163 " value=\"%u\" size=\"8\" maxlength=\"8\">" 7164 "</td>" 7165 "</tr>\n"; 7166 static char *table_end = "</table>\n"; 7167 char tmp[NVRAM_BUFSIZE], prefix[16]; /* "wlXXXXXXXXXX_" */ 7168 unsigned sec, thr; 7169 int i; 7170 7171 if (!make_wl_prefix(prefix, sizeof(prefix), 0, NULL)) { 7172 strcpy(prefix, "wl_"); 7173 } 7174 7175 websWrite(wp, table_start); 7176 7177 for (i = 0; i < NWINS; ++i) { 7178 if (sscanf(nvram_safe_get(strcat_r(prefix, wins[i].keyword, tmp)), "%u %u", 7179 &sec, &thr) != 2) { 7180 sec = thr = 0; 7181 } 7182 websWrite(wp, table_entry, wins[i].description, wins[i].description, 7183 wins[i].keyword, 7184 wins[i].keyword, sec, 7185 wins[i].keyword, thr ); 7186 } 7187 websWrite(wp, table_end); 7188 return 0; 7189} 7190 7191/* Fill HTML input form with traffic management filters data stored in NVRAM */ 7192static int 7193ej_trf_mgmt_display(int eid, webs_t wp, int argc, char_t **argv) 7194{ 7195 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 7196 char cap[WLC_IOCTL_SMLEN]; 7197 char caps[WLC_IOCTL_MEDLEN]; 7198 char *name = NULL; 7199 char *next = NULL; 7200 int trf_mgmt_cap = 0; 7201 int i, n = 9, ret = 0; 7202 netconf_trmgmt_t trm; 7203 bool valid; 7204 char port[] = "XXXXX"; 7205 char eastr[ETHER_ADDR_STR_LEN]; 7206 unsigned char *hwaddr; 7207 7208 if (!make_wl_prefix(prefix, sizeof(prefix), 0, NULL)) { 7209 websError(wp, 400, "unit number variable doesn't exist\n"); 7210 return -1; 7211 } 7212 7213 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 7214#ifdef __CONFIG_DHDAP__ 7215 /* Traffic Management Setting is not supported on DHD/PCIEFD driver */ 7216 if (!dhd_probe(name)) { 7217 return -1; 7218 } 7219#endif 7220 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 7221 return -1; 7222 7223 foreach(cap, caps, next) { 7224 if (!strcmp(cap, "traffic-mgmt")) { 7225 trf_mgmt_cap = 1; 7226 break; 7227 } 7228 } 7229 if (trf_mgmt_cap == 0) 7230 return -1; 7231 7232 websWrite(wp, "<p>"); 7233 websWrite(wp, "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"); 7234 websWrite(wp, "<tr>"); 7235 websWrite(wp, "<th width=\"310\" valign=\"top\" rowspan=\"11\""); 7236 websWrite(wp, "onMouseOver=\"return overlib('Adds up to 10 traffic management filters which specifies the TCP/UDP port, MAC and priority.', LEFT);\""); 7237 websWrite(wp, "onMouseOut=\"return nd();\">"); 7238 websWrite(wp, "<input type=\"hidden\" name=\"trf_mgmt_port\" value=\"10\">"); 7239 websWrite(wp, "Traffic Management Settings: "); 7240 websWrite(wp, "</th>"); 7241 websWrite(wp, "<td> </td>"); 7242 websWrite(wp, "<td class=\"label\">Protocol</td>"); 7243 websWrite(wp, "<td></td>"); 7244 websWrite(wp, "<td class=\"label\">Src Port</td>"); 7245 websWrite(wp, "<td></td>"); 7246 websWrite(wp, "<td class=\"label\">Dst Port</td>"); 7247 websWrite(wp, "<td></td>"); 7248 websWrite(wp, "<td class=\"label\">Dst Mac Addr</td>"); 7249 websWrite(wp, "<td></td>"); 7250 websWrite(wp, "<td class=\"label\">Priority</td>"); 7251 websWrite(wp, "<td></td>"); 7252 websWrite(wp, "<td class=\"label\">Favored</td>"); 7253 websWrite(wp, "<td></td>"); 7254 websWrite(wp, "<td class=\"label\">Enabled</td>"); 7255 websWrite(wp, "</tr>"); 7256 7257 for (i = 0; i <= n; i++) { 7258 valid = get_trf_mgmt_port(prefix, i, &trm); 7259 7260 ret += websWrite(wp, "<tr>"); 7261 ret += websWrite(wp, "<td></td>"); 7262 7263 /* Print protocol */ 7264 ret += websWrite(wp, "<td>"); 7265 ret += websWrite(wp, "<select name=\"%strf_mgmt_port_proto%d\">", prefix, i); 7266 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 7267 valid && trm.match.ipproto == IPPROTO_TCP ? "selected" : ""); 7268 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 7269 valid && trm.match.ipproto == IPPROTO_UDP ? "selected" : ""); 7270 ret += websWrite(wp, "<option value=\"mac\" %s>MAC</option>", 7271 valid && trm.match.ipproto == IPPROTO_IP ? "selected" : ""); 7272 ret += websWrite(wp, "</select>"); 7273 ret += websWrite(wp, "</td>"); 7274 ret += websWrite(wp, "<td></td>"); 7275 7276 7277 /* Print source port number, map source port value zero to NULL */ 7278 if ((valid) && (trm.match.ipproto != IPPROTO_IP) && trm.match.src.ports[0]) 7279 snprintf(port, sizeof(port), "%d", ntohs(trm.match.src.ports[0])); 7280 else 7281 *port = '\0'; 7282 ret += websWrite(wp, "<td><input name=\"%strf_mgmt_port_sport%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 7283 prefix, i, port); 7284 ret += websWrite(wp, "<td></td>"); 7285 7286 /* Print destination port number, map dest port value zero to NULL */ 7287 if ((valid) && (trm.match.ipproto != IPPROTO_IP) && trm.match.dst.ports[0]) 7288 snprintf(port, sizeof(port), "%d", ntohs(trm.match.dst.ports[0])); 7289 else 7290 *port = '\0'; 7291 ret += websWrite(wp, "<td><input name=\"%strf_mgmt_port_dport%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 7292 prefix, i, port); 7293 ret += websWrite(wp, "<td></td>"); 7294 7295 /* Print mac address */ 7296 hwaddr = (unsigned char *)&trm.match.mac; 7297 /* Check for bad, multicast, broadcast, or null address */ 7298 if ((hwaddr[0] & 1) || 7299 (hwaddr[0] & hwaddr[1] & hwaddr[2] & hwaddr[3] & hwaddr[4] & hwaddr[5]) == 0xff || 7300 (hwaddr[0] | hwaddr[1] | hwaddr[2] | hwaddr[3] | hwaddr[4] | hwaddr[5]) == 0x00) { 7301 ret += websWrite(wp, "<td><input name=\"%strf_mgmt_port_macaddr%d\" value=\"%s\" size=\"17\" maxlength=\"17\"></td>", 7302 prefix, i, ""); 7303 } else { 7304 ret += websWrite(wp, "<td><input name=\"%strf_mgmt_port_macaddr%d\" value=\"%s\" size=\"17\" maxlength=\"17\"></td>", 7305 prefix, i, valid ? ether_etoa((const unsigned char *)&trm.match.mac, eastr) : ""); 7306 } 7307 ret += websWrite(wp, "<td></td>"); 7308 7309 /* Print priority */ 7310 ret += websWrite(wp, "<td>"); 7311 ret += websWrite(wp, "<select name=\"%strf_mgmt_port_prio%d\">", prefix, i); 7312 ret += websWrite(wp, "<option value=\"0\" %s>BK</option>", 7313 valid && trm.prio == 0 ? "selected" : ""); 7314 ret += websWrite(wp, "<option value=\"1\" %s>BE</option>", 7315 valid && trm.prio == 1 ? "selected" : ""); 7316 ret += websWrite(wp, "<option value=\"2\" %s>VI</option>", 7317 valid && trm.prio == 2 ? "selected" : ""); 7318 ret += websWrite(wp, "<option value=\"3\" %s>NOCHANGE</option>", 7319 valid && trm.prio == 3 ? "selected" : ""); 7320 7321 ret += websWrite(wp, "</select>"); 7322 ret += websWrite(wp, "</td>"); 7323 ret += websWrite(wp, "<td></td>"); 7324 7325 /* Print Favored */ 7326 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"%strf_mgmt_port_favored%d\" %s></td>", 7327 prefix, i, valid && (trm.favored) ? "checked" : ""); 7328 7329 /* Print enable */ 7330 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"%strf_mgmt_port_enable%d\" %s></td>", 7331 prefix, i, valid && !(trm.match.flags & NETCONF_DISABLED) ? "checked" : ""); 7332 7333 ret += websWrite(wp, "</tr>\n"); 7334 } 7335 7336 websWrite(wp, "</table>"); 7337 7338 return ret; 7339} 7340 7341char *webs_buf=NULL; 7342int webs_buf_offset=0; 7343 7344/* This routine extracts the index variable in the string 7345 format 7346 eg get_string_index("lan_","lan0_ifname",buf,sizeof(buf)) 7347 returns the string "0" in buf. 7348 7349 In the case of where there is no index 7350 eg get_string_index("lan_","lan_ifname",buf,sizeof(buf)) 7351 returns NULL in buf[0]. 7352 7353 Inputs : 7354 - prefix: prefix to start of index string 7355 - varname: value to process 7356 - outbuf: output buffer 7357 - bufsize: output buffer size 7358 7359 Returns: 7360 -string null terminated string in output buffer 7361 -pointer to output buffer or NULL if error 7362*/ 7363char * 7364get_index_string(char *prefix, char *varname, char *outbuf, int bufsize) 7365{ 7366 int offset, len; 7367 7368 if (!prefix) return NULL; 7369 if (!varname) return NULL; 7370 if (!outbuf) return NULL; 7371 if (!bufsize) return NULL; 7372 7373 memset(outbuf,0,bufsize); 7374 7375 /* offset is the start of the index number eg 7376 * offset of dhcp0 is 4. prefix contains the "dhcp" as 7377 * the prefix 7378 */ 7379 7380 offset = strlen(prefix); 7381 7382 /* This calculates the string length of the index 7383 * ie the index value represented as a string 7384 * strchr(varname,'_') is the end of the index string. 7385 * strchr(varname,'_') - varname is the length of the var including 7386 * the index string but before the underscore "_" 7387 */ 7388 len = strchr(varname,'_') - varname - offset ; 7389 7390 if (len > bufsize) return NULL; 7391 7392 if (len) strncpy(outbuf,&varname[offset],len); 7393 outbuf[len]='\0'; 7394 7395 return outbuf; 7396} 7397 7398/* 7399 * DFS Reentry Window parameters (seconds and threshold) are saved in a single nvram variable, 7400 * separated by a blank, ie, wlX_acs_dfsr_immediate="300 2". This unfortunately requires us to 7401 * do some specialised web page display and parsing. 7402 */ 7403static int 7404validate_dfs_window(webs_t wp, char *value, struct variable *v, char *varname) 7405{ 7406 char name[40]; /* wl_xxxxxxxxx_acs_dfsr_immediate_sec */ 7407 unsigned sec,thr; 7408 7409 snprintf(name, sizeof(name), "%s_sec", v->name ); 7410 value = websGetVar(wp, name, NULL); 7411 sec = (value && *value) ? atoi(value) : 0; 7412 7413 snprintf(name, sizeof(name), "%s_thr", v->name ); 7414 value = websGetVar(wp, name, NULL); 7415 thr = (value && *value) ? atoi(value) : 0; 7416 7417 /* A zero threshold is valid, but a zero window size is not. */ 7418 if (!sec) { 7419 /* Only complain if a zero value is in there and the field is not disabled. */ 7420 if (value) { 7421 websBufferWrite(wp, "Invalid <b>%s</b>: Seconds may be not zero<br>", 7422 v->longname ); 7423 } 7424 return FALSE; 7425 } 7426 7427 sprintf(name, "%u %u", sec, thr); 7428 nvram_set((varname) ? varname : v->name, name); 7429 7430 return TRUE; 7431} 7432 7433static void 7434validate_list(webs_t wp, char *value, struct variable *v, 7435 int (*valid)(webs_t, char *, struct variable *), char *varname ) 7436{ 7437 int n, i; 7438 char name[100]; 7439 char buf[1000] = "", *cur = buf; 7440 7441 assert(v); 7442 7443 ret_code = EINVAL; 7444 n = atoi(value); 7445 7446 for (i = 0; i < n; i++) { 7447 snprintf(name, sizeof(name), "%s%d", v->name, i); 7448 if (!(value = websGetVar(wp, name, NULL))) 7449 return; 7450 7451 if (!*value && v->nullok) 7452 continue; 7453 if (!valid(wp, value, v )) 7454 continue; 7455 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s", 7456 cur == buf ? "" : " ", value); 7457 } 7458 7459 /* Use varname override if specified. Used to make the routine 7460 multiinstance compatible */ 7461 if (varname) 7462 nvram_set(varname, buf); 7463 else 7464 nvram_set(v->name, buf); 7465 7466 ret_code = 0; 7467} 7468 7469static int 7470valid_ipaddr(webs_t wp, char *value, struct variable *v) 7471{ 7472 unsigned int buf[4]; 7473 struct in_addr ipaddr, netaddr, broadaddr, netmask; 7474 7475 assert(v); 7476 7477 if (sscanf(value, "%d.%d.%d.%d", &buf[0], &buf[1], &buf[2], &buf[3]) != 4) { 7478 websBufferWrite(wp, "Invalid <b>%s</b> %s: not an IP address<br>", 7479 v->longname, value); 7480 return FALSE; 7481 } 7482 7483 ipaddr.s_addr = htonl((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); 7484 7485 if (v->argv) { 7486 (void) inet_aton(nvram_safe_get(v->argv[0]), &netaddr); 7487 (void) inet_aton(nvram_safe_get(v->argv[1]), &netmask); 7488 netaddr.s_addr &= netmask.s_addr; 7489 broadaddr.s_addr = netaddr.s_addr | ~netmask.s_addr; 7490 if (netaddr.s_addr != (ipaddr.s_addr & netmask.s_addr)) { 7491 websBufferWrite(wp, "Invalid <b>%s</b> %s: not in the %s/", 7492 v->longname, value, inet_ntoa(netaddr)); 7493 websBufferWrite(wp, "%s network<br>", inet_ntoa(netmask)); 7494 return FALSE; 7495 } 7496 if (ipaddr.s_addr == netaddr.s_addr) { 7497 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the network address<br>", 7498 v->longname, value); 7499 return FALSE; 7500 } 7501 if (ipaddr.s_addr == broadaddr.s_addr) { 7502 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the broadcast address<br>", 7503 v->longname, value); 7504 return FALSE; 7505 } 7506 } 7507 7508 return TRUE; 7509} 7510 7511static void 7512validate_ipaddr(webs_t wp, char *value, struct variable *v , char *varname) 7513{ 7514 7515 assert(v); 7516 7517 ret_code = EINVAL; 7518 7519 if (!valid_ipaddr(wp, value, v) ) return; 7520 7521 if (varname) 7522 nvram_set(varname,value) ; 7523 else 7524 nvram_set(v->name, value); 7525 7526 ret_code = 0; 7527 7528} 7529 7530static void 7531validate_ipaddrs(webs_t wp, char *value, struct variable *v, char *varname) 7532{ 7533 ret_code = EINVAL; 7534 validate_list(wp, value, v, valid_ipaddr, varname); 7535} 7536 7537int 7538valid_choice(webs_t wp, char *value, struct variable *v) 7539{ 7540 char **choice=NULL; 7541 7542 assert(v); 7543 7544 for (choice = v->argv; *choice; choice++) { 7545 if (!strcmp(value, *choice)) 7546 return TRUE; 7547 } 7548 7549 websBufferWrite(wp, "Invalid <b>%s</b> %s: not one of ", v->longname, value); 7550 for (choice = v->argv; *choice; choice++) 7551 websBufferWrite(wp, "%s%s", choice == v->argv ? "" : "/", *choice); 7552 websBufferWrite(wp, "<br>"); 7553 7554 return FALSE; 7555} 7556 7557static void 7558validate_choice(webs_t wp, char *value, struct variable *v, char *varname) 7559{ 7560 7561 assert(v); 7562 7563 ret_code = EINVAL; 7564 7565 if (!valid_choice(wp, value, v)) return; 7566 7567 if (varname ) 7568 nvram_set(varname, value); 7569 else 7570 nvram_set(v->name, value); 7571 ret_code = 0; 7572 7573} 7574 7575static void 7576validate_router_disable(webs_t wp, char *value, struct variable *v, 7577 char *varname) 7578{ 7579 char *temp = NULL; 7580 7581 assert(v); 7582 7583 ret_code = EINVAL; 7584 7585 if (!valid_choice(wp, value, v)) return; 7586 7587 /* we need to find out if we're changing the router mode or not. if 7588 we're really changing the setting, we need to reboot */ 7589 temp = nvram_safe_get( v->name ); 7590 7591 if( strcmp( temp, value ) ) 7592 action = REBOOT; 7593 7594 if (varname ) 7595 nvram_set(varname,value) ; 7596 else 7597 nvram_set(v->name, value); 7598 ret_code = 0; 7599 7600} 7601 7602int 7603valid_range(webs_t wp, char *value, struct variable *v) 7604{ 7605 int n, start, end; 7606 7607 assert(v); 7608 7609 n = atoi(value); 7610 start = atoi(v->argv[0]); 7611 end = atoi(v->argv[1]); 7612 7613 if (n < start || n > end) { 7614 websBufferWrite(wp, "Invalid <b>%s</b> %s: out of range %d-%d<br>", 7615 v->longname, value, start, end); 7616 return FALSE; 7617 } 7618 7619 return TRUE; 7620} 7621 7622static void 7623validate_range(webs_t wp, char *value, struct variable *v , char *varname) 7624{ 7625 7626 assert(v); 7627 7628 ret_code = EINVAL; 7629 7630 if (!valid_range(wp, value, v)) return ; 7631 7632 if (varname ) 7633 nvram_set(varname,value) ; 7634 else 7635 nvram_set(v->name, value); 7636 7637 ret_code = 0; 7638} 7639 7640int 7641valid_octet(webs_t wp, char *value, struct variable *v) 7642{ 7643 int n, start, end; 7644 assert(v); 7645 7646 n = atoi(value); 7647 start = atoi(v->argv[0]); 7648 end = atoi(v->argv[1]); 7649 7650 if (n == 255) { 7651 return TRUE; 7652 } else if (n < start || n > end) { 7653 websBufferWrite(wp, "Invalid <b>%s</b> %s: out of range %d-%d<br>", 7654 v->longname, value, start, end); 7655 return FALSE; 7656 } 7657 7658 return TRUE; 7659} 7660 7661 7662#ifdef BCMQOS 7663static void 7664valid_qos_var(webs_t wp, char *value, struct variable *v, char *varname ) 7665{ 7666 ret_code = EINVAL; 7667 printf("\nIN valid_qos_varvalid_name()"); 7668 if (varname ) 7669 nvram_set(varname,value) ; 7670 else 7671 nvram_set(v->name, value); 7672 ret_code = 0; 7673} 7674#endif /* BCMQOS */ 7675int 7676valid_name(webs_t wp, char *value, struct variable *v) 7677{ 7678 int n, min, max; 7679 7680 assert(v); 7681 7682 n = strlen(value); 7683 min = atoi(v->argv[0]); 7684 max = atoi(v->argv[1]); 7685 7686 if (n > max) { 7687 websBufferWrite(wp, "Invalid <b>%s</b> %s: longer than %d characters<br>", 7688 v->longname, value, max); 7689 return FALSE; 7690 } 7691 else if (n < min) { 7692 websBufferWrite(wp, "Invalid <b>%s</b> %s: shorter than %d characters<br>", 7693 v->longname, value, min); 7694 return FALSE; 7695 } 7696 7697 return TRUE; 7698} 7699 7700int 7701valid_hex(webs_t wp, char *value, struct variable *v) 7702{ 7703 int n, min, max; 7704 char *c=NULL; 7705 7706 assert(v); 7707 7708 n = strlen(value); 7709 min = atoi(v->argv[0]); 7710 max = atoi(v->argv[1]); 7711 7712 if (n > max) { 7713 websBufferWrite(wp, "Invalid <b>%s</b> %s: longer than %d characters<br>", 7714 v->longname, value, max); 7715 return FALSE; 7716 } 7717 else if (n < min) { 7718 websBufferWrite(wp, "Invalid <b>%s</b> %s: shorter than %d characters<br>", 7719 v->longname, value, min); 7720 return FALSE; 7721 } 7722 else if(n%2) 7723 { 7724 websBufferWrite(wp, "Invalid <b>%s</b> %s: must be in even length<br>", 7725 v->longname, value); 7726 return FALSE; 7727 } 7728 7729 for (c = value; *c; c++) { 7730 if (!isxdigit((int) *c)) { 7731 websBufferWrite(wp, "Invalid <b>%s</b>: character %c is not a hexadecimal digit<br>", 7732 v->longname, *c); 7733 return FALSE; 7734 } 7735 } 7736 7737 return TRUE; 7738} 7739 7740 7741static void 7742validate_guest_lan_ifname(webs_t wp, char *value, struct variable *v, char *varname ) 7743{ 7744 int index,unit; 7745 char ifname[IFNAMSIZ],os_name[IFNAMSIZ]; 7746 7747 assert(v); 7748 assert(value); 7749 7750 ret_code = EINVAL; 7751 7752 if (!*value){ 7753 websBufferWrite(wp, "Guest LAN interface must be specified.<br>"); 7754 return; 7755 } 7756 7757 if (!v->argv[0]){ 7758 websBufferWrite(wp, "Guest LAN interface index must be specified.<br>"); 7759 return; 7760 } 7761 7762 index = atoi (v->argv[0]); 7763 7764 if ((index < 1 ) || (index > 4)) 7765 if (!v->argv[0]){ 7766 websBufferWrite(wp, "Guest LAN interface index must be between 1 and 4.<br>"); 7767 return; 7768 } 7769 7770 if (nvifname_to_osifname( value, os_name, sizeof(os_name) ) < 0){ 7771 websBufferWrite(wp, "Unable to translate Guest LAN interface name: %s.<br>",value); 7772 return; 7773 } 7774 7775 if (wl_probe(os_name) || 7776 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))){ 7777 websBufferWrite(wp, "Guest LAN interface %s is not a Wireless Interface.<br>",value); 7778 return; 7779 } 7780 7781 /* Guest SSID are not part of a bridge, unset lanX_ifnames */ 7782 7783 snprintf(ifname,sizeof(ifname),"lan%d_ifname",index); 7784 nvram_set(ifname,value); 7785 7786 snprintf(ifname,sizeof(ifname),"lan%d_ifnames",index); 7787 nvram_unset(ifname); 7788 7789 ret_code=0; 7790} 7791static void 7792validate_vif_ssid(webs_t wp, char *value, struct variable *v, char *varname ) 7793{ 7794/* Validation of the guest ssids does 3 things 7795 * 1)adds the wlX.Y_ssid field 7796 * 2)updates the wlX_vif list 7797 * 3)removes entry from wlX_vif if the interface is empty 7798*/ 7799 7800 char *wl_unit=NULL; 7801 char wl_vif[]="wlXXXXXXXXX_vifs",*wl_vif_value=NULL; 7802 char wl_ssid[]="wlXXXXXXXXX_ssid"; 7803 char wl_radio[]="wlXXXXXXXXX_radio"; 7804 char wl_mode[]="wlXXXXXXXXX_mode"; 7805 char buf[100]; 7806 char prefix[]="wlXXXXX"; 7807 int p=-1; 7808 char *subunit=NULL,unit[]="0000"; 7809 char *argv[3]; 7810 7811 assert(v); 7812 assert(value); 7813 7814 ret_code = EINVAL; 7815 7816 7817 if (varname) 7818 wl_unit=varname; 7819 else 7820 wl_unit=websGetVar(wp, "wl_unit", NULL); 7821 7822 if (!wl_unit || get_ifname_unit(wl_unit,&p,NULL) < 0) return ; 7823 7824 if (p < 0) return; 7825 7826 7827 snprintf(unit,sizeof(unit),"%d",p); 7828 subunit = v->argv[0]; 7829 7830 /* If SSID is not null try to validate it for correct range */ 7831 if (*value){ 7832 struct variable local; 7833 7834 memcpy(&local,v,sizeof(local)); 7835 argv[0]="1"; 7836 argv[1]="32"; 7837 argv[2]=NULL; 7838 local.argv=argv; 7839 if (!valid_name(wp, value, &local)) return; 7840 } 7841 7842 snprintf(wl_ssid,sizeof(wl_ssid),"wl_ssid"); 7843 snprintf(wl_vif,sizeof(wl_vif),"wl%s_vifs",unit); 7844 7845 memset(buf,0,sizeof(buf)); 7846 7847 /* This logic here decides if updates to virtual interface list on the 7848 parent is required */ 7849 7850 wl_vif_value = nvram_get(wl_vif); 7851 7852 if (wl_vif_value ){ 7853 char vif[]="wlXXXXXXXXX"; 7854 int found = 0; 7855 char name[IFNAMSIZ], *next = NULL; 7856 7857 snprintf(vif,sizeof(vif),"wl%s.%s",unit,subunit); 7858 7859 /* virtual interface on the list already? */ 7860 foreach(name,wl_vif_value,next) { 7861 if (!strcmp(name, vif)) { 7862 found = 1; 7863 break; 7864 } 7865 } 7866 7867 if (*value){ 7868 /* New interface , non-NULL SSID add to wl_vifs */ 7869 if (!found) 7870 snprintf(buf,sizeof(buf),"%s wl%s.%s",wl_vif_value,unit,subunit); 7871 else 7872 /* Interface present ,non-NULL SSID copy entire vifs string */ 7873 snprintf(buf,sizeof(buf),"%s",wl_vif_value); 7874 }else{ 7875 /* Purge interface from wl_vifs as the SSID is now NULL */ 7876 7877 /* vif present , delete from wl_vifs */ 7878 if ((found)){ 7879 7880 memset(buf,0,sizeof(buf)); 7881 7882 foreach(name,wl_vif_value,next) 7883 /* Copy all interfaces except the one to be removed*/ 7884 if (strcmp(name,vif)){ 7885 int len; 7886 7887 len = strlen(buf); 7888 if (*buf) 7889 strncat(buf," ",1); 7890 strncat(buf,name,strlen(name)); 7891 } 7892 }else 7893 /* Interface absent from wl_vifs, just copy vifs string */ 7894 snprintf(buf,sizeof(buf),"%s",wl_vif_value); 7895 } 7896 }else 7897 if (*value) snprintf(buf,sizeof(buf),"wl%s.%s",unit,subunit); 7898 7899 /* Regenerate virtual interface list */ 7900 if (*buf) 7901 nvram_set(wl_vif,buf); 7902 else 7903 nvram_unset(wl_vif); 7904 7905 7906 /* Update/clean up wlX.Y_guest flag and wlX.Y_ssid */ 7907 7908 snprintf(prefix,sizeof(prefix),"wl%s.%s",unit,subunit); 7909 snprintf(wl_radio,sizeof(wl_radio),"wl_radio"); 7910 snprintf(wl_mode,sizeof(wl_mode),"wl_mode"); 7911 7912 if (*value){ 7913 nvram_set(wl_mode,"ap"); 7914#ifdef __CONFIG_WPS__ 7915 if (!nvram_match(wl_ssid, value)) 7916 ssid_update = 1; 7917#endif 7918 nvram_set(wl_ssid,value); 7919 nvram_set(wl_radio,"1"); 7920 }else{ 7921 nvram_unset(wl_ssid); 7922 nvram_unset(wl_radio); 7923 nvram_unset(wl_mode); 7924 nvram_unset("wl_bss_enabled"); 7925 } 7926 7927 ret_code = 0; 7928} 7929static void 7930validate_name(webs_t wp, char *value, struct variable *v, char *varname ) 7931{ 7932 ret_code = EINVAL; 7933 7934 assert(v); 7935 7936 if (!valid_name(wp, value, v)) return; 7937 7938 if (varname ) 7939 nvram_set(varname,value) ; 7940 else 7941 nvram_set(v->name, value); 7942 7943 ret_code = 0; 7944} 7945 7946static void 7947validate_names(webs_t wp, char *value, struct variable *v, char *varname ) 7948{ 7949 7950 assert(v); 7951 7952 ret_code = EINVAL; 7953 7954 validate_list(wp, value, v, valid_name, varname); 7955} 7956 7957static void 7958validate_bridge(webs_t wp, char *value, struct variable *v, char *varname ) 7959{ 7960 char prefix[] = "wlXXXXXXXXXX_"; 7961 char *wl_bssid = NULL; 7962 int mode = 0; 7963 char vif[sizeof(prefix)]; 7964 char add_br[] = "xxxxxxxxxxxxx_" ; 7965 char del_br[] = "xxxxxxxxxxxxx_" ; 7966#ifdef __CONFIG_GMAC3__ 7967 char fwd_wlandevs[NVRAM_MAX_VALUE_LEN]; 7968#endif 7969 char name[IFNAMSIZ], *next = NULL; 7970 int need_to_add = 1; 7971 char buf[NVRAM_MAX_VALUE_LEN]; 7972 unsigned int len; 7973 7974 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))) 7975 mode=1; 7976 7977 if(!mode) { 7978 /* primary configuration, , so no choice for bridge ,always at br0 */ 7979 ret_code = 0 ; 7980 return ; 7981 } 7982 7983 if (!make_wl_prefix(prefix, sizeof(prefix), mode, NULL)) { 7984 websError(wp, 400, "unit number variable doesn't exist\n"); 7985 return ; 7986 } 7987 7988 /* interface name is prefix less the trailing '_' */ 7989 strcpy(vif, prefix); 7990 len = strlen(vif); 7991 len--; 7992 vif[len] = 0; 7993 7994 /* add the interface to bridge br1, and delete it from br0 */ 7995 if(atoi(value)){ 7996 snprintf(add_br, sizeof(add_br), "lan1_ifnames") ; 7997 snprintf(del_br, sizeof(del_br), "lan_ifnames") ; 7998#ifdef __CONFIG_GMAC3__ 7999 /* in theory we should have three Network Bridge type "LAN", "Guest" and 8000 * "Forwarder" in GMAC3 platform, for now we assume all "LAN" wireless 8001 * interfaces are belong to Forwarder too. Customer can change the 8002 * fwd_wlandevs NVRAM to configure a "LAN" virtual interface to bind to 8003 * sw br0 in order to apply layer 2 filter in sw bridge. For now our GUI we 8004 * don't support this of configuration. 8005 */ 8006 /* remove vif from fwd_wlandevs if any */ 8007 strncpy(fwd_wlandevs, nvram_safe_get("fwd_wlandevs"), sizeof(fwd_wlandevs)-1); 8008 if (remove_from_list(vif, fwd_wlandevs, sizeof(fwd_wlandevs)) == 0) 8009 nvram_set("fwd_wlandevs", fwd_wlandevs); 8010#endif 8011 } 8012 /* add the interface to bridge br0, and delete it from br1 */ 8013 else { 8014 snprintf(add_br, sizeof(add_br), "lan_ifnames") ; 8015 snprintf(del_br, sizeof(del_br), "lan1_ifnames") ; 8016#ifdef __CONFIG_GMAC3__ 8017 /* add vif to fwd_wlandevs. */ 8018 strncpy(fwd_wlandevs, nvram_safe_get("fwd_wlandevs"), sizeof(fwd_wlandevs)-1); 8019 if (!find_in_list(fwd_wlandevs, vif) && 8020 add_to_list(vif, fwd_wlandevs, sizeof(fwd_wlandevs)-1) == 0) 8021 nvram_set("fwd_wlandevs", fwd_wlandevs); 8022#endif 8023 } 8024 8025 memset(buf,0,sizeof(buf)); 8026 /* Copy all the interfaces except the the one we want to remove*/ 8027 foreach(name, nvram_get(del_br),next) { 8028 if (strcmp(name,vif)){ 8029 int len; 8030 len = strlen(buf); 8031 if (*buf) 8032 strncat(buf," ",1); 8033 strncat(buf,name,strlen(name)); 8034 } 8035 } 8036 nvram_set(del_br, buf); 8037 memset(buf,0,sizeof(buf)); 8038 strncpy(buf, nvram_get(add_br),sizeof(buf) - 1); 8039 foreach(name, buf, next) { 8040 if (!strcmp(name,vif)){ 8041 need_to_add = 0; 8042 break; 8043 } 8044 } 8045 8046 if (need_to_add) { 8047 /* the first entry ? */ 8048 if (*buf) 8049 strncat(buf," ",1); 8050 strncat(buf, vif, strlen(vif)); 8051 } 8052 8053 nvram_set(add_br, buf); 8054 8055 ret_code = 0; 8056} 8057static void 8058validate_ssid(webs_t wp, char *value, struct variable *v, char *varname ) 8059{ 8060 char *wl_bssid = NULL; 8061 8062 ret_code = EINVAL ; 8063 8064 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))){ 8065 v->argv[0] = wl_bssid; 8066 validate_vif_ssid(wp, value, v,varname); 8067 } 8068 else { 8069#ifdef __CONFIG_WPS__ 8070 char *name; 8071 if (!valid_name(wp, value, v)) 8072 return; 8073 if (varname) 8074 name = varname; 8075 else 8076 name = v->name; 8077 8078 if (!nvram_match(name, value)) 8079 ssid_update = 1; 8080#endif 8081 validate_name(wp, value, v, varname); 8082 } 8083#ifdef __CONFIG_WPS__ 8084 if (ssid_update) { 8085 wps_disable_oob(); 8086 ssid_update = 0; 8087 } 8088#endif 8089 ret_code = 0; 8090} 8091 8092static void 8093validate_wl_closed(webs_t wp, char *value, struct variable *v, char *varname ) 8094{ 8095 validate_choice(wp, value, v, varname); 8096 8097#ifdef __CONFIG_WPS__ 8098 if (ret_code == 0 && strcmp(value, "1" /* Closed */) == 0) { 8099 char *wl_wps_mode = NULL; 8100 8101 /* Disabled WPS if it is enabled */ 8102 wl_wps_mode = nvram_get("wl_wps_mode"); 8103 if (strcmp(wl_wps_mode, "enabled") == 0) 8104 nvram_set("wl_wps_mode", "disabled"); 8105 } 8106#endif /* __CONFIG_WPS__ */ 8107} 8108 8109static void 8110validate_wl_macmode(webs_t wp, char *value, struct variable *v, char *varname ) 8111{ 8112 validate_choice(wp, value, v, varname); 8113 8114#ifdef __CONFIG_WPS__ 8115 if (ret_code == 0 && strcmp(value, "allow") == 0) { 8116 int i; 8117 char *wl_wps_mode = NULL; 8118 char wl_maclist[] = "wl_maclistxxx"; 8119 char *wl_mac; 8120 unsigned char hwaddr[6]; 8121 8122 /* Disabled WPS if it is enabled */ 8123 wl_wps_mode = nvram_get("wl_wps_mode"); 8124 if (strcmp(wl_wps_mode, "enabled") == 0) { 8125 for (i = 0; i < MACLIST_MAX_NUM; i++) { 8126 sprintf(wl_maclist, "wl_maclist%d", i); 8127 wl_mac = websGetVar(wp, wl_maclist, ""); 8128 /* a legal non-empty mac check */ 8129 if (strlen(wl_mac) && ether_atoe(wl_mac, hwaddr) && 8130 !(hwaddr[0] & 1) && 8131 (hwaddr[0] & hwaddr[1] & hwaddr[2] & hwaddr[3] & hwaddr[4] & hwaddr[5]) != 0xff && 8132 (hwaddr[0] | hwaddr[1] | hwaddr[2] | hwaddr[3] | hwaddr[4] | hwaddr[5]) != 0x00) 8133 break; 8134 } 8135 /* All maclist are empty */ 8136 if (i == MACLIST_MAX_NUM) { 8137 nvram_set("wl_wps_mode", "disabled"); 8138 websBufferWrite(wp, "Selecting <b>allow</b> with <b>empty</b> " 8139 "MAC Address will disable the WPS.<br>"); 8140 } 8141 } 8142 } 8143#endif /* __CONFIG_WPS__ */ 8144} 8145 8146#ifdef __CONFIG_WPS__ 8147#ifdef WFA_WPS_20_TESTBED 8148static void 8149validate_wps2_range(webs_t wp, char *value, struct variable *v , char *varname) 8150{ 8151 int n; 8152 8153 assert(v); 8154 8155 ret_code = EINVAL; 8156 8157 /* 0 is mean unset it */ 8158 n = atoi(value); 8159 if (n == 0) { 8160 if (varname ) 8161 nvram_unset(varname) ; 8162 else 8163 nvram_unset(v->name); 8164 8165 ret_code = 0; 8166 return; 8167 } 8168 8169 if (!valid_range(wp, value, v)) return ; 8170 8171 if (varname ) 8172 nvram_set(varname, value) ; 8173 else 8174 nvram_set(v->name, value); 8175 8176 ret_code = 0; 8177} 8178#endif /* WFA_WPS_20_TESTBED */ 8179 8180static void 8181validate_wps_reg(webs_t wp, char *value, struct variable *v, char *varname) 8182{ 8183 char *temp = NULL; 8184 char tmp[NVRAM_BUFSIZE]; 8185 int lan_idx; 8186 8187 if((temp = websGetVar(wp, "wps_reg", NULL))) { 8188 if(*temp) { 8189 /* set lanx_wps_reg according to wl_unit */ 8190 lan_idx = wps_get_lan_idx(); 8191 8192 if (lan_idx == 0) 8193 snprintf(tmp, sizeof(tmp), "lan_wps_reg"); 8194 else 8195 snprintf(tmp, sizeof(tmp), "lan%d_wps_reg", lan_idx); 8196 8197 if (!strcmp(value,"enabled")) 8198 nvram_set(tmp, "enabled"); /* Built-in Reg */ 8199 else 8200 nvram_set(tmp, "disabled"); 8201 8202 ret_code = 0; 8203 return; 8204 } 8205 } 8206 8207 websError(wp, 400, "Insufficient args\n"); 8208 ret_code = EINVAL; 8209 return; 8210} 8211 8212static void 8213validate_wps_oob(webs_t wp, char *value, struct variable *v, char *varname) 8214{ 8215 char tmp[NVRAM_BUFSIZE]; 8216 8217 ret_code = 0; 8218 if(wps_get_oob_name(tmp, NVRAM_BUFSIZE) != 0) 8219 return; 8220 8221 if (!strcmp(value, "enabled")) { 8222 nvram_set(tmp, "enabled"); /* OOB (Unconfigued) */ 8223 } 8224 else 8225 nvram_set(tmp, "disabled"); /* Configured */ 8226 return; 8227} 8228 8229static void 8230validate_wps_mode(webs_t wp, char *value, struct variable *v, char *varname) 8231{ 8232 char *auth = NULL, *crypto = NULL, *wep = NULL; 8233 char *wpa = NULL, *psk = NULL; 8234 char *wpa2 = NULL, *psk2 = NULL; 8235 char *vname = NULL; 8236 bool b_wps_version2 = FALSE; 8237 8238 int i; 8239 char *wl_mac, wl_maclist[] = "wl_maclistxxx"; 8240 unsigned char hwaddr[6]; 8241 8242 8243 assert(v); 8244 8245 ret_code = EINVAL; 8246 8247 if (varname) 8248 vname = varname; 8249 else 8250 vname = v->name; 8251 8252 /* WSC 2.0, support WPS V2 or not */ 8253 if (strcmp(nvram_safe_get("wps_version2"), "enabled") == 0) 8254 b_wps_version2 = TRUE; 8255 8256 /* Do not check AKM and Crypto in OOB */ 8257 8258 /* Do AKM and Crypto checking when WPS enabled */ 8259 if (!strcmp(value, "enabled")) { 8260 if (b_wps_version2) { 8261 /* Check Auth, deprecated "Shared" mode */ 8262 if((auth = websGetVar(wp, "wl_auth", NULL)) && (strcmp(auth, "1") == 0)) { 8263 websBufferWrite(wp, "WPS does not support <b>Shared</b> " 8264 "authentication<br><b>Force to disable WPS</b><br>"); 8265 goto invalid; 8266 } 8267 8268 /* Get WEP */ 8269 wep = websGetVar(wp, "wl_wep", NULL); 8270 8271 /* 8272 * WiFi WPA2 requires that WEP be disabled if WPA2 or WPA2-PSK is used, 8273 * GUI has the WEP Enable/Disable field disabled when the user selects 8274 * WPA2, so WEP setting doesn't come in the HTTP buffer, which means we 8275 * must manually turn it off here to disable WEP. 8276 * 8277 * According above description and WSC 2.0 only allowed WPA2, WPA2-PSK 8278 * and WPA-PSK+WPA2-PSK(mix mode). Here WEP is allowed only when 8279 * wep_survival back door enabled and akm is empty. 8280 */ 8281 /* 8282 * WSC 2.0, Authentication type check. 8283 * Allowed type : Open, WPA2, WPA2-PSK and WPA-PSK+WPA2-PSK(Mix mode) 8284 * Deprecated type: Shared, WPA and WPS-PSK only 8285 */ 8286 /* Check AKM and Crypto */ 8287 if ((wpa = websGetVar(wp, "wl_akm_wpa", NULL)) == NULL) 8288 wpa = "disabled"; 8289 if ((psk = websGetVar(wp, "wl_akm_psk", NULL)) == NULL) 8290 psk = "disabled"; 8291 if ((wpa2 = websGetVar(wp, "wl_akm_wpa2", NULL)) == NULL) 8292 wpa2 = "disabled"; 8293 if ((psk2 = websGetVar(wp, "wl_akm_psk2", NULL)) == NULL) 8294 psk2 = "disabled"; 8295 8296 if (!strcmp(wpa, "enabled") || !strcmp(psk, "enabled") 8297 || !strcmp(wpa2, "enabled") || !strcmp(psk2, "enabled") 8298 ) { 8299 /* AKM enabled */ 8300 /* 8301 * For now, Broadcom WPS does not support WPA and WPA2. 8302 * We support WPA2-PSK and WPA2PSK+WPA-PSK 8303 */ 8304 /* Check AKM. BCMWPA2 MUST enabled */ 8305 if (strcmp(psk2, "enabled") != 0) { 8306 websBufferWrite(wp, "WPS only support <b>WPA2-PSK or " 8307 "WPA2-PSK+WPA-PSK mixed mode</b> authentication " 8308 "key management<br>" 8309 "<b>Force to disable WPS</b><br>"); 8310 goto invalid; 8311 } 8312 8313 /* 8314 * WSC 2.0, Encryption type check. 8315 * Allowed type : None, AES and TKIP+AES(Mix mode) 8316 * Deprecated type: Wep and TKIP only 8317 * 8318 * Note: A back door to keep supporting WEP by seting 8319 * NVRAM "wps_wep_survival" 8320 */ 8321 crypto = websGetVar(wp, "wl_crypto", NULL); 8322 if (!crypto || ( 8323 strcmp(crypto, "tkip") && 8324 strcmp(crypto, "aes") && 8325 strcmp(crypto, "tkip+aes"))) { 8326 websBufferWrite(wp, "<b>Crypto Algorithm</b> mode must be" 8327 " TKIP or AES or TKIP+AES<br>" 8328 "<b>Force to disable WPS</b><br>"); 8329 goto invalid; 8330 } else if (strcmp(crypto, "tkip") == 0) { 8331 websBufferWrite(wp, "WPS does not support <b>TKIP</b> only " 8332 "crypto algorithm<br><b>Force to disable WPS</b>" 8333 "<br>"); 8334 goto invalid; 8335 } 8336 } 8337 else { 8338 /* AKM Disabled */ 8339 /* Check WEP */ 8340 if (wep && strcmp(wep, "enabled") == 0) { 8341 websBufferWrite(wp, "WPS does not support <b>WEP</b> crypto " 8342 "algorithm<br><b>Force to disable WPS</b><br>"); 8343 goto invalid; 8344 } 8345 8346 } 8347 } 8348 8349 /* Set wl_wps_mode */ 8350 nvram_set(vname, "enabled"); 8351 8352 /* WSC 2.0, Set SSID Network Type to Open */ 8353 if (nvram_invmatch("wl_closed", "0")) { 8354 websBufferWrite(wp, "<br>Enable WPS will change the SSID " 8355 "<b>Network Type to Open</b><br>"); 8356 nvram_set("wl_closed", "0"); 8357 } 8358 8359 /* WSC 2.0, MAC filter check */ 8360 if (nvram_match("wl_macmode", "allow")) { 8361 for (i = 0; i < MACLIST_MAX_NUM; i++) { 8362 sprintf(wl_maclist, "wl_maclist%d", i); 8363 wl_mac = nvram_get(wl_maclist); 8364 /* a legal non-empty mac check */ 8365 if (wl_mac && strlen(wl_mac) && ether_atoe(wl_mac, hwaddr) && 8366 !(hwaddr[0] & 1) && 8367 (hwaddr[0] & hwaddr[1] & hwaddr[2] & hwaddr[3] & hwaddr[4] & hwaddr[5]) != 0xff && 8368 (hwaddr[0] | hwaddr[1] | hwaddr[2] | hwaddr[3] | hwaddr[4] | hwaddr[5]) != 0x00) 8369 break; 8370 } 8371 /* All maclist are empty */ 8372 if (i == MACLIST_MAX_NUM) { 8373 websBufferWrite(wp, "Enable WPS will <b>Disabled MAC Restrict Mode</b><br>"); 8374 nvram_set("wl_macmode", "disabled"); 8375 } 8376 } 8377 } 8378 else if (!strcmp(value, "enr_enabled")) { 8379 nvram_set(vname, "enr_enabled"); 8380 } 8381 else { 8382 nvram_set(vname, "disabled"); 8383 } 8384 8385 ret_code = 0; 8386 return; 8387 8388invalid: 8389 /* Force disable WPS */ 8390 nvram_set(vname, "disabled"); 8391 8392 return; 8393} 8394#endif /* __CONFIG_WPS__ */ 8395 8396static char *get_ifname (webs_t wp) 8397{ 8398 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 8399 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 8400 websError(wp, 400, "unit number variable doesn't exist<br>"); 8401 return NULL; 8402 } 8403 return (nvram_safe_get(strcat_r(prefix, "ifname", tmp))); 8404} 8405 8406static void 8407validate_wl_chanspec(webs_t wp, char *value, struct variable *v, char *varname) 8408{ 8409 /* chanspec "N/A" are set to 0 (Auto) */ 8410 nvram_set(v->name, !strcmp("N/A", value) ? "0" : value); 8411 ret_code = 0; 8412} 8413 8414static void 8415validate_wl_country_code(webs_t wp, char *value, struct variable *v, char *varname) 8416{ 8417 wl_country_t country_spec = {{0}, 0, {0}}; 8418 ret_code = EINVAL; 8419 char *name=NULL; 8420 char *rev=NULL; 8421 8422 assert(v); 8423 8424 name = get_ifname(wp); 8425 8426 rev = websGetVar(wp, "wl_country_rev", NULL); 8427 country_spec.rev = atoi(rev); 8428 sprintf( country_spec.ccode, "%s", value ); 8429 sprintf( country_spec.country_abbrev, "%s", value ); 8430 if (wl_iovar_set(name, "country", &country_spec, sizeof(country_spec))){ 8431 websError(wp, 400, "<br><b>ERROR:</b>Country"); 8432 return; 8433 } 8434 nvram_set( v->name, value); 8435 ret_code = 0; 8436} 8437 8438static void 8439validate_wl_country_rev(webs_t wp, char *value, struct variable *v, char *varname) 8440{ 8441 wl_country_t country_spec = {{0}, 0, {0}}; 8442 ret_code = EINVAL; 8443 char *name=NULL; 8444 char *country=NULL; 8445 8446 assert(v); 8447 8448 name = get_ifname(wp); 8449 country = websGetVar(wp, "wl_country_code", NULL); 8450 country_spec.rev = atoi(value); 8451 sprintf( country_spec.ccode, "%s", country ); 8452 sprintf( country_spec.country_abbrev, "%s", country ); 8453 if (wl_iovar_set(name, "country", &country_spec, sizeof(country_spec))){ 8454 websError(wp, 400, "/Regulatory revision doesn't exist<br>"); 8455 return; 8456 } 8457 nvram_set( v->name, value); 8458 ret_code = 0; 8459} 8460 8461static void 8462validate_ure(webs_t wp, char *value, struct variable *v, char *varname) 8463{ 8464 char *temp=NULL; 8465 int wl_unit = -1; 8466 int wl_subunit = -1; 8467 int wl_ure = -1; 8468 int ii = 0; 8469 char nv_param[NVRAM_MAX_PARAM_LEN]; 8470 char nv_interface[NVRAM_MAX_PARAM_LEN]; 8471 char os_interface[NVRAM_MAX_PARAM_LEN]; 8472 char interface_list[NVRAM_MAX_VALUE_LEN]; 8473 int interface_list_size = sizeof(interface_list); 8474 char *wan0_ifname = "wan0_ifname"; 8475 char *lan_ifnames = "lan_ifnames"; 8476 char *wan_ifnames = "wan_ifnames"; 8477 int travel_router = 0; 8478 char cap[WLC_IOCTL_SMLEN]; 8479 char caps[WLC_IOCTL_MEDLEN]; 8480 char *name = NULL; 8481 char *next = NULL; 8482 int max_no_vifs = 0; 8483 int i = 0; 8484 char tmp[20]; 8485 8486 if ((temp = websGetVar(wp, "wl_unit", NULL))) 8487 { 8488 if( *temp ) { 8489 if (get_ifname_unit( temp, &wl_unit, &wl_subunit ) != 0) { 8490 websError(wp, 400, "URE error getting wl_unit\n"); 8491 ret_code = EINVAL; 8492 return; 8493 } 8494 } 8495 8496 if( wl_subunit != -1 ) 8497 { 8498 websError(wp, 400, "URE can't be enabled for a virtual I/F\n"); 8499 ret_code = EINVAL; 8500 return; 8501 } 8502 } 8503 8504 if((temp = websGetVar(wp, "wl_ure", NULL))) 8505 { 8506 if( *temp ) 8507 wl_ure = atoi( temp ); 8508 } 8509 8510 if( wl_ure < 0 || wl_unit < 0 ) 8511 { 8512 websError(wp, 400, "Insufficient args\n"); 8513 ret_code = EINVAL; 8514 return; 8515 } 8516 8517 if ( nvram_match( "router_disable", "1" ) && wl_ure == 1 ) 8518 travel_router = 0; 8519 else 8520 travel_router = 1; 8521 8522 /* Get the No of VIFS */ 8523 sprintf( nv_interface, "wl%d_ifname", wl_unit ); 8524 name = nvram_safe_get(nv_interface); 8525 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) 8526 return; 8527 foreach(cap, caps, next) { 8528 if (!strcmp(cap, "mbss16")) 8529 max_no_vifs = 16; 8530 else if (!strcmp(cap, "mbss8")) 8531 max_no_vifs = 8; 8532 else if (!strcmp(cap, "mbss4")) 8533 max_no_vifs = 4; 8534 } 8535 8536 if( wl_ure == 1 ) 8537 { 8538 /* turning on URE*/ 8539 8540 /* If TR, we can only allow a single TR interface */ 8541 for( ii = 0; ii < DEV_NUMIFS; ii++ ) { 8542 if( ii == wl_unit ) 8543 continue; 8544 8545 sprintf( nv_param, "wl%d_ure", ii ); 8546 temp = nvram_safe_get( nv_param ); 8547 if( temp && strlen( temp ) > 0 ) 8548 { 8549 if( atoi( temp ) == 1 ) { 8550 websError(wp, 400, "Can not have more than one URE interface\n"); 8551 ret_code = EINVAL; 8552 return; 8553 } 8554 } 8555 } 8556 8557 sprintf( nv_param, "wl_ure" ); 8558 temp = nvram_safe_get( nv_param ); 8559 if( strncmp( temp, "0", 1 ) == 0 || strlen( temp ) == 0 ) 8560 { 8561 action = REBOOT; 8562 } 8563 else { 8564 /* nothing to do, bail out now */ 8565 return; 8566 } 8567 /* turn URE on for this primary interface */ 8568 nvram_set( nv_param, "1" ); 8569 8570 nvram_set( "ure_disable", "0" ); 8571 8572 /* Set the wl modes for the primary wireless adapter and it's 8573 virtual interface */ 8574 sprintf( nv_param, "wl%d_mode", wl_unit ); 8575 if( travel_router == 1 ) { 8576 nvram_set( nv_param, "sta" ); 8577 nvram_set( "wl_mode", "sta" ); 8578 } 8579 else { 8580 nvram_set( nv_param, "wet" ); 8581 nvram_set( "wl_mode", "wet" ); 8582 } 8583 8584 sprintf( nv_param, "wl%d.1_mode", wl_unit ); 8585 nvram_set( nv_param, "ap" ); 8586 8587 if( travel_router == 1 ) { 8588 /* For URE with routing(Travel Router)we're using the STA part of our 8589 URE enabled radio as our WAN connection. So, we need to remove this 8590 interface from the list of bridged lan interfaces and set it up as 8591 the WAN device. 8592 */ 8593 temp = nvram_safe_get(lan_ifnames); 8594 if( interface_list_size <= strlen( temp ) ) 8595 { 8596 websError(wp, 400, "string too long\n"); 8597 ret_code = 1; 8598 return; 8599 } 8600 strncpy( interface_list, temp, interface_list_size ); 8601 /* this may be confusing, right now the interface name that is stored 8602 in the nvram lists is OS specific. For linux it's an "ethX" for 8603 wireless interfaces and for VxWorks "wlX" is stored as "wlX" so 8604 this is trying to make OS independant code */ 8605 sprintf( nv_interface, "wl%d", wl_unit ); 8606 nvifname_to_osifname( nv_interface, os_interface, sizeof(os_interface) ); 8607 remove_from_list( os_interface, interface_list, interface_list_size ); 8608 nvram_set( lan_ifnames, interface_list ); 8609 8610 /* Now remove the existing WAN interface from "wan_ifnames" */ 8611 temp = nvram_safe_get( wan_ifnames ); 8612 if( interface_list_size <= (strlen( temp ) + strlen( interface_list )) ) 8613 { 8614 websError(wp, 400, "string too long\n"); 8615 ret_code = 1; 8616 return; 8617 } 8618 strncpy( interface_list, temp, interface_list_size ); 8619 temp = nvram_safe_get( wan0_ifname ); 8620 if( strlen( temp ) != 0 ) 8621 { 8622 /* stash this interface name in an nvram variable so 8623 we can restore this interface as the WAN interface when URE 8624 is disabled. */ 8625 nvram_set( "old_wan0_ifname", temp ); 8626 remove_from_list( temp, interface_list, interface_list_size ); 8627 } 8628 8629 /* set the new WAN interface as the pimary WAN interface and add to 8630 the list wan_ifnames */ 8631 nvram_set( wan0_ifname, os_interface ); 8632 add_to_list( os_interface, interface_list, interface_list_size ); 8633 nvram_set( wan_ifnames, interface_list ); 8634 8635 /* now add the AP to the list of bridged lan interfaces */ 8636 temp = nvram_safe_get(lan_ifnames); 8637 if( interface_list_size <= strlen( temp ) ) 8638 { 8639 websError(wp, 400, "string too long\n"); 8640 ret_code = 1; 8641 return; 8642 } 8643 strncpy( interface_list, temp, interface_list_size ); 8644 sprintf( nv_interface, "wl%d.1", wl_unit ); 8645 /* virtual interfaces that appear in NVRAM lists are ALWAYS stored 8646 as the NVRAM_FORM so we can add to list without translating */ 8647 if( add_to_list( nv_interface, interface_list, interface_list_size ) != 8648 0 ) 8649 { 8650 websError(wp, 400, "Failed to add AP interface to lan_ifnames\n"); 8651 ret_code = 1; 8652 return; 8653 } 8654 nvram_set( lan_ifnames, interface_list ); 8655 8656 } 8657 else { 8658 /* For URE without routing(Range Extender) we're using the STA 8659 as a WET device to connect to the "upstream" AP. We need to 8660 add our virtual interface(AP) to the bridged lan */ 8661 temp = nvram_safe_get(lan_ifnames); 8662 if( interface_list_size <= strlen( temp ) ) 8663 { 8664 websError(wp, 400, "string too long\n"); 8665 ret_code = 1; 8666 return; 8667 } 8668 strncpy( interface_list, temp, interface_list_size ); 8669 8670 sprintf( nv_interface, "wl%d.1", wl_unit ); 8671 add_to_list( nv_interface, interface_list, interface_list_size ); 8672 nvram_set( lan_ifnames, interface_list ); 8673 8674 } 8675 8676 /* Security - We don't support any RADIUS-based authentication, so 8677 we must force these options to OFF */ 8678 /* turn off wlX_auth_mode and wlX.1_auth_mode */ 8679 sprintf( nv_param, "wl%d_auth_mode", wl_unit ); 8680 nvram_set( nv_param, "none" ); 8681 sprintf( nv_param, "wl%d.1_auth_mode", wl_unit ); 8682 nvram_set( nv_param, "none" ); 8683 /* remove wpa and wpa2 from wlX_akm and wlX.1_akm */ 8684 /* wl_akm should be used here rather than wlX_akm, it's an 8685 indexed param, so wl_akm represents wlX_akm */ 8686 sprintf( nv_param, "wl_akm" ); 8687 temp = nvram_get( nv_param ); 8688 if( temp && *temp ) 8689 { 8690 memset( interface_list, 0, interface_list_size ); 8691 /* NOTE: using "interface_list" to hold security nvram values */ 8692 strncpy( interface_list, temp, interface_list_size - 1 ); 8693 remove_from_list("wpa", interface_list, interface_list_size ); 8694 remove_from_list("wpa2", interface_list, interface_list_size ); 8695 nvram_set( nv_param, interface_list ); 8696 } 8697 sprintf( nv_param, "wl%d.1_akm", wl_unit ); 8698 temp = nvram_get( nv_param ); 8699 if( temp && *temp ) 8700 { 8701 memset( interface_list, 0, interface_list_size ); 8702 /* NOTE: using "interface_list" to hold security nvram values */ 8703 strncpy( interface_list, temp, interface_list_size - 1 ); 8704 remove_from_list("wpa", interface_list, interface_list_size ); 8705 remove_from_list("wpa2", interface_list, interface_list_size ); 8706 nvram_set( nv_param, interface_list ); 8707 } 8708 8709 /* Make lan1_ifname lan1_ifnames empty sothat br1 is not created in URE mode. */ 8710 /* Disable all VIFS wlX.2 onwards */ 8711 nvram_set("lan1_ifname", "" ); 8712 nvram_set("lan1_ifnames", "" ); 8713 if(wl_unit) 8714 nvram_set("wl0.1_bss_enabled", "0"); 8715 else 8716 nvram_set("wl1.1_bss_enabled", "0"); 8717 for (i=2; i<max_no_vifs; i++) { 8718 sprintf( nv_interface, "wl0.%d_bss_enabled", i ); 8719 nvram_set(nv_interface, "0"); 8720 sprintf( nv_interface, "wl1.%d_bss_enabled", i ); 8721 nvram_set(nv_interface, "0"); 8722 } 8723 8724 } 8725 else 8726 { 8727 sprintf( nv_param, "wl_ure"); 8728 temp = nvram_get( nv_param ); 8729 if( strncmp( temp, "1", 1 ) != 0 ) { 8730 /* nothing to do, bail out now */ 8731 return; 8732 } 8733 nvram_set( nv_param, "0" ); 8734 8735 nvram_set( "ure_disable", "1" ); 8736 8737 /* Restore default WAN interface */ 8738 8739 /* Now remove the existing WAN interface from "wan_ifnames" */ 8740 temp = nvram_safe_get( wan_ifnames ); 8741 if( interface_list_size <= (strlen( temp ) + strlen( interface_list )) ) 8742 { 8743 websError(wp, 400, "string too long\n"); 8744 ret_code = 1; 8745 return; 8746 } 8747 strncpy( interface_list, temp, interface_list_size ); 8748 temp = nvram_safe_get( wan0_ifname ); 8749 if( strlen( temp ) != 0 ) 8750 { 8751 remove_from_list( temp, interface_list, interface_list_size ); 8752 } 8753 8754 /* set the default WAN interface as the pimary WAN interface and add to 8755 the list wan_ifnames */ 8756 temp = nvram_get( "old_wan0_ifname" ); 8757 8758 if( temp && *temp ) 8759 strcpy( os_interface, temp ); 8760 else /* best guess */ 8761 strcpy( os_interface, "eth1" ); 8762 nvram_set( wan0_ifname, os_interface ); 8763 add_to_list( os_interface, interface_list, interface_list_size ); 8764 nvram_set( wan_ifnames, interface_list ); 8765 8766 /* Now we need to remove the virtual I/F from the bridged lan interfaces */ 8767 temp = nvram_safe_get(lan_ifnames); 8768 if( interface_list_size <= strlen( temp ) ) 8769 { 8770 websError(wp, 400, "string too long\n"); 8771 ret_code = 1; 8772 return; 8773 } 8774 strncpy( interface_list, temp, interface_list_size ); 8775 sprintf( nv_interface, "wl%d.1", wl_unit ); 8776 /* virtual interfaces that appear in NVRAM lists are ALWAYS stored 8777 as the NVRAM_FORM so we can add to list without translating */ 8778 remove_from_list( nv_interface, interface_list, interface_list_size ); 8779 /* Add our primary interface to lan_ifnames - default behavior */ 8780 sprintf( nv_interface, "wl%d", wl_unit ); 8781 nvifname_to_osifname( nv_interface, os_interface, sizeof(os_interface) ); 8782 add_to_list( os_interface, interface_list, interface_list_size ); 8783 nvram_set( lan_ifnames, interface_list ); 8784 8785 /* Make lan1_ifname, lan1_ifnames to default values */ 8786 nvram_set("lan1_ifname", "br1" ); 8787 memset( interface_list, 0, interface_list_size ); 8788 for (i=1; i<max_no_vifs; i++) { 8789 sprintf( nv_interface, "wl0.%d", i ); 8790 add_to_list(nv_interface, interface_list, interface_list_size ); 8791 nvram_set(strcat_r(nv_interface, "_hwaddr",tmp),""); 8792 sprintf( nv_interface, "wl1.%d", i ); 8793 add_to_list(nv_interface, interface_list, interface_list_size ); 8794 nvram_set(strcat_r(nv_interface, "_hwaddr",tmp),""); 8795 } 8796 nvram_set("lan1_ifnames", interface_list ); 8797 8798 } 8799 action = REBOOT; 8800 8801 /* We're unsetting the WAN hardware address so that we get the correct 8802 address for the new WAN interface the next time we boot. */ 8803 nvram_unset( "wan0_hwaddr" ); 8804 8805 ret_code = 0; 8806 return; 8807} 8808 8809static int 8810valid_hwaddr(webs_t wp, char *value, struct variable *v) 8811{ 8812 unsigned char hwaddr[6]; 8813 8814 assert(v); 8815 8816 /* Make exception for "NOT IMPLELEMENTED" string */ 8817 if (!strcmp(value,"NOT_IMPLEMENTED")) 8818 return(TRUE); 8819 8820 /* Check for bad, multicast, broadcast, or null address */ 8821 if (!ether_atoe(value, hwaddr) || 8822 (hwaddr[0] & 1) || 8823 (hwaddr[0] & hwaddr[1] & hwaddr[2] & hwaddr[3] & hwaddr[4] & hwaddr[5]) == 0xff || 8824 (hwaddr[0] | hwaddr[1] | hwaddr[2] | hwaddr[3] | hwaddr[4] | hwaddr[5]) == 0x00) { 8825 websBufferWrite(wp, "Invalid <b>%s</b> %s: not a MAC address<br>", 8826 v->longname, value); 8827 return FALSE; 8828 } 8829 8830 return TRUE; 8831} 8832 8833static void 8834validate_hwaddr(webs_t wp, char *value, struct variable *v, char *varname ) 8835{ 8836 8837 ret_code = EINVAL; 8838 8839 if (!valid_hwaddr(wp, value, v)) return; 8840 8841 if(varname ) 8842 nvram_set(varname,value); 8843 else 8844 nvram_set(v->name, value); 8845 8846 ret_code = 0; 8847 8848 8849} 8850 8851static void 8852validate_hwaddrs(webs_t wp, char *value, struct variable *v, char *varname ) 8853{ 8854 8855 assert(v); 8856 8857 ret_code = EINVAL; 8858 validate_list(wp, value, v, valid_hwaddr, varname); 8859} 8860 8861static void 8862validate_dhcp(webs_t wp, char *value, struct variable *v, char *varname) 8863{ 8864 struct variable dhcp_variables[] = { 8865 { longname: "DHCP Server Starting LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 8866 { longname: "DHCP Server Ending LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 8867 }; 8868 char *start=NULL, *end=NULL; 8869 char dhcp_start[20]="dhcp_start"; 8870 char dhcp_end[20]="dhcp_start"; 8871 char lan_proto[20]="lan_proto"; 8872 char lan_ipaddr[20]="lan_ipaddr"; 8873 char lan_netmask[20]= "lan_netmask"; 8874 char *dhcp0_argv[3],*dhcp1_argv[3]; 8875 char index[5]; 8876 8877 assert(v); 8878 8879 ret_code = EINVAL; 8880 8881 memset(index,0,sizeof(index)); 8882 /* fixup the nvram varnames if varname override is provided */ 8883 if (varname){ 8884 if (!get_index_string(v->prefix, 8885 varname,index,sizeof(index))) 8886 return; 8887 8888 snprintf(dhcp_start,sizeof(dhcp_start),"dhcp%s_start",index); 8889 snprintf(dhcp_end,sizeof(dhcp_end),"dhcp%s_end",index); 8890 snprintf(lan_proto,sizeof(lan_proto),"lan%s_proto",index); 8891 snprintf(lan_ipaddr,sizeof(lan_ipaddr),"lan%s_ipaddr",index); 8892 snprintf(lan_netmask,sizeof(lan_netmask),"lan%s_netmask",index); 8893 dhcp0_argv[0]=lan_ipaddr; 8894 dhcp0_argv[1]=lan_netmask; 8895 dhcp0_argv[2]=NULL; 8896 dhcp1_argv[0]=lan_ipaddr; 8897 dhcp1_argv[1]=lan_netmask; 8898 dhcp1_argv[2]=NULL; 8899 dhcp_variables[0].argv = dhcp0_argv; 8900 dhcp_variables[1].argv = dhcp1_argv; 8901 } 8902 8903 if (!(start = websGetVar(wp, dhcp_start, NULL)) || 8904 !(end = websGetVar(wp, dhcp_end, NULL))) 8905 return; 8906 if (!*start) start = end; 8907 if (!*end) end = start; 8908 if (!*start && !*end && !strcmp(nvram_safe_get(lan_proto), "dhcp")) { 8909 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a range<br>", v->longname); 8910 return; 8911 } 8912 if (!valid_ipaddr(wp, start, &dhcp_variables[0]) || 8913 !valid_ipaddr(wp, end, &dhcp_variables[1])) 8914 return; 8915 if (ntohl(inet_addr(start)) > ntohl(inet_addr(end))) { 8916 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 8917 dhcp_variables[0].longname, start, dhcp_variables[1].longname, end); 8918 return; 8919 } 8920 8921 nvram_set(dhcp_start, start); 8922 nvram_set(dhcp_end, end); 8923 8924 ret_code = 0; 8925} 8926 8927static void 8928validate_lan_ipaddr(webs_t wp, char *value, struct variable *v, char *varname) 8929{ 8930 struct variable fields[] = { 8931 { name: "lan_ipaddr", longname: "LAN IP Address" }, 8932 { name: "lan_netmask", longname: "LAN Subnet Mask" }, 8933 }; 8934 char *lan_ipaddr=NULL, *lan_netmask=NULL; 8935 char tmp_ipaddr[20], tmp_netmask[20]; 8936 struct in_addr ipaddr, netmask, netaddr, broadaddr; 8937 char lan_ipaddrs[][20] = { "dhcp_start", "dhcp_end", "dmz_ipaddr" }; 8938#ifdef __CONFIG_NAT__ 8939 netconf_filter_t start, end; 8940#ifdef __CONFIG_URLFILTER__ 8941 netconf_urlfilter_t url_start, url_end; 8942#endif /* __CONFIG_URLFILTER__ */ 8943 netconf_nat_t nat; 8944 bool valid; 8945#endif /* __CONFIG_NAT__ */ 8946 int i; 8947 8948 assert(v); 8949 8950 ret_code = EINVAL; 8951 8952 /* Insert name overrides */ 8953 if (varname) 8954 { 8955 char index[5]; 8956 8957 if (!get_index_string(v->prefix, 8958 varname,index,sizeof(index))) 8959 return ; 8960 8961 snprintf(tmp_ipaddr,sizeof(tmp_ipaddr),"lan%s_ipaddr",index); 8962 snprintf(tmp_netmask,sizeof(tmp_netmask),"lan%s_netmask",index); 8963 fields[0].name = tmp_ipaddr; 8964 fields[1].name = tmp_netmask; 8965 snprintf(lan_ipaddrs[0],sizeof(lan_ipaddrs[0]),"dhcp%s_start",index); 8966 snprintf(lan_ipaddrs[1],sizeof(lan_ipaddrs[1]),"dhcp%s_end",index); 8967 } 8968 /* Basic validation */ 8969 if (!(lan_ipaddr = websGetVar(wp, fields[0].name, NULL)) || 8970 !(lan_netmask = websGetVar(wp, fields[1].name, NULL)) || 8971 !valid_ipaddr(wp, lan_ipaddr, &fields[0]) || 8972 !valid_ipaddr(wp, lan_netmask, &fields[1])) 8973 return; 8974 8975 /* Check for broadcast or network address */ 8976 (void) inet_aton(lan_ipaddr, &ipaddr); 8977 (void) inet_aton(lan_netmask, &netmask); 8978 netaddr.s_addr = ipaddr.s_addr & netmask.s_addr; 8979 broadaddr.s_addr = netaddr.s_addr | ~netmask.s_addr; 8980 if (ipaddr.s_addr == netaddr.s_addr) { 8981 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the network address<br>", 8982 fields[0].longname, lan_ipaddr); 8983 return; 8984 } 8985 if (ipaddr.s_addr == broadaddr.s_addr) { 8986 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the broadcast address<br>", 8987 fields[0].longname, lan_ipaddr); 8988 return; 8989 } 8990 8991 8992 nvram_set(fields[0].name, lan_ipaddr); 8993 nvram_set(fields[1].name, lan_netmask); 8994 8995 8996 /* Fix up LAN IP addresses */ 8997 for (i = 0; i < ARRAYSIZE(lan_ipaddrs); i++) { 8998 8999 value = nvram_get(lan_ipaddrs[i]); 9000 if (value && *value) { 9001 (void) inet_aton(value, &ipaddr); 9002 ipaddr.s_addr &= ~netmask.s_addr; 9003 ipaddr.s_addr |= netaddr.s_addr; 9004 9005 nvram_set(lan_ipaddrs[i], inet_ntoa(ipaddr)); 9006 } 9007 } 9008 9009#ifdef __CONFIG_NAT__ 9010 /* Fix up client filters and port forwards */ 9011 for (i = 0; i < MAX_NVPARSE; i++) { 9012 if (get_filter_client(i, &start, &end)) { 9013 start.match.src.ipaddr.s_addr &= ~netmask.s_addr; 9014 start.match.src.ipaddr.s_addr |= netaddr.s_addr; 9015 end.match.src.ipaddr.s_addr &= ~netmask.s_addr; 9016 end.match.src.ipaddr.s_addr |= netaddr.s_addr; 9017 9018 valid = set_filter_client(i, &start, &end); 9019 a_assert(valid); 9020 } 9021#ifdef __CONFIG_URLFILTER__ 9022 if (get_filter_url(i, &url_start, &url_end)) { 9023 url_start.match.src.ipaddr.s_addr &= ~netmask.s_addr; 9024 url_start.match.src.ipaddr.s_addr |= netaddr.s_addr; 9025 url_end.match.src.ipaddr.s_addr &= ~netmask.s_addr; 9026 url_end.match.src.ipaddr.s_addr |= netaddr.s_addr; 9027 9028 valid = set_filter_url(i, &url_start, &url_end); 9029 a_assert(valid); 9030 } 9031#endif /* __CONFIG_URLFILTER__ */ 9032 if (get_forward_port(i, &nat)) { 9033 nat.ipaddr.s_addr &= ~netmask.s_addr; 9034 nat.ipaddr.s_addr |= netaddr.s_addr; 9035 valid = set_forward_port(i, &nat); 9036 a_assert(valid); 9037 } 9038 } 9039#endif /* __CONFIG_NAT__ */ 9040 9041 ret_code = 0; 9042} 9043 9044#ifdef __CONFIG_NAT__ 9045static void 9046validate_filter_client(webs_t wp, char *value, struct variable *v, char *varname) 9047{ 9048 int n, i, j; 9049 bool valid; 9050 struct variable fields[] = { 9051 { name: "filter_client_from_start%d", longname: "LAN Client Filter Starting IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 9052 { name: "filter_client_from_end%d", longname: "LAN Client Filter Ending IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 9053 { name: "filter_client_proto%d", longname: "LAN Client Filter Protocol", argv: ARGV("tcp", "udp") }, 9054 { name: "filter_client_to_start%d", longname: "LAN Client Filter Starting Destination Port", argv: ARGV("0", "65535") }, 9055 { name: "filter_client_to_end%d", longname: "LAN Client Filter Ending Destination Port", argv: ARGV("0", "65535") }, 9056 { name: "filter_client_from_day%d", longname: "LAN Client Filter Starting Day", argv: ARGV("0", "6") }, 9057 { name: "filter_client_to_day%d", longname: "LAN Client Filter Ending Day", argv: ARGV("0", "6") }, 9058 { name: "filter_client_from_sec%d", longname: "LAN Client Filter Starting Second", argv: ARGV("0", "86400") }, 9059 { name: "filter_client_to_sec%d", longname: "LAN Client Filter Ending Second", argv: ARGV("0", "86400") }, 9060 }; 9061 char *from_start=NULL, *from_end=NULL, *proto=NULL, *to_start=NULL; 9062 char *to_end=NULL, *from_day=NULL, *to_day=NULL, *from_sec=NULL, *to_sec=NULL, *enable=NULL; 9063 char **locals[] = { &from_start, &from_end, &proto, &to_start, &to_end, &from_day, &to_day, &from_sec, &to_sec }; 9064 char name[1000]; 9065 netconf_filter_t start, end; 9066 9067 assert(v); 9068 9069 ret_code = EINVAL; 9070 9071 /* filter_client indicates how many to expect */ 9072 if (!valid_range(wp, value, v)){ 9073 websBufferWrite(wp, "Invalid filter client string <b>%s</b><br>",value); 9074 return; 9075 } 9076 n = atoi(value); 9077 9078 for (i = 0; i <= n; i++) { 9079 /* Set up field names */ 9080 for (j = 0; j < ARRAYSIZE(fields); j++) { 9081 snprintf(name, sizeof(name), fields[j].name, i); 9082 if (!(*locals[j] = websGetVar(wp, name, NULL))) 9083 break; 9084 } 9085 /* Incomplete web page */ 9086 if (j < ARRAYSIZE(fields)) 9087 continue; 9088 /* Enable is a checkbox */ 9089 snprintf(name, sizeof(name), "filter_client_enable%d", i); 9090 if (websGetVar(wp, name, NULL)) 9091 enable = "on"; 9092 else 9093 enable = "off"; 9094 /* Delete entry if all fields are blank */ 9095 if (!*from_start && !*from_end && !*to_start && !*to_end) { 9096 del_filter_client(i); 9097 continue; 9098 } 9099 /* Fill in empty fields with default values */ 9100 if (!*from_start) from_start = from_end; 9101 if (!*from_end) from_end = from_start; 9102 if (!*to_start) to_start = to_end; 9103 if (!*to_end) to_end = to_start; 9104 if (!*from_start || !*from_end) { 9105 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address Range<br>", v->longname); 9106 continue; 9107 } 9108 if (!*to_start || !*to_end) { 9109 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Destination Port Range<br>", v->longname); 9110 continue; 9111 } 9112 /* Check individual fields */ 9113 if (!valid_ipaddr(wp, from_start, &fields[0]) || 9114 !valid_ipaddr(wp, from_end, &fields[1]) || 9115 !valid_choice(wp, proto, &fields[2]) || 9116 !valid_range(wp, to_start, &fields[3]) || 9117 !valid_range(wp, to_end, &fields[4]) || 9118 !valid_range(wp, from_day, &fields[5]) || 9119 !valid_range(wp, to_day, &fields[6]) || 9120 !valid_range(wp, from_sec, &fields[7]) || 9121 !valid_range(wp, to_sec, &fields[8])) 9122 continue; 9123 /* Check dependencies between fields */ 9124 if (ntohl(inet_addr(from_start)) > ntohl(inet_addr(from_end))) { 9125 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9126 fields[0].longname, from_start, fields[1].longname, from_end); 9127 continue; 9128 } 9129 if (atoi(to_start) > atoi(to_end)) { 9130 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9131 fields[3].longname, to_start, fields[4].longname, to_end); 9132 continue; 9133 } 9134 9135 /* Set up parameters */ 9136 memset(&start, 0, sizeof(netconf_filter_t)); 9137 if (!strcmp(proto, "tcp")) 9138 start.match.ipproto = IPPROTO_TCP; 9139 else if (!strcmp(proto, "udp")) 9140 start.match.ipproto = IPPROTO_UDP; 9141 (void) inet_aton(from_start, &start.match.src.ipaddr); 9142 start.match.src.netmask.s_addr = htonl(0xffffffff); 9143 start.match.dst.ports[0] = htons(atoi(to_start)); 9144 start.match.dst.ports[1] = htons(atoi(to_end)); 9145 start.match.days[0] = atoi(from_day); 9146 start.match.days[1] = atoi(to_day); 9147 start.match.secs[0] = atoi(from_sec); 9148 start.match.secs[1] = atoi(to_sec); 9149 if (!strcmp(enable, "off")) 9150 start.match.flags |= NETCONF_DISABLED; 9151 memcpy(&end, &start, sizeof(netconf_filter_t)); 9152 (void) inet_aton(from_end, &end.match.src.ipaddr); 9153 9154 /* Do it */ 9155 valid = set_filter_client(i, &start, &end); 9156 a_assert(valid); 9157 } 9158 9159 ret_code = 0; 9160} 9161 9162#ifdef __CONFIG_URLFILTER__ 9163static void 9164validate_filter_url(webs_t wp, char *value, struct variable *v, char *varname) 9165{ 9166 int n, i, j; 9167 bool valid; 9168 struct variable fields[] = { 9169 { name: "filter_url_from_start%d", longname: "URL Filter Starting IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 9170 { name: "filter_url_from_end%d", longname: "URL Filter Ending IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 9171 }; 9172 char *from_start=NULL, *from_end=NULL; 9173 char *url_addr=NULL, *enable=NULL; 9174 char **locals[] = { &from_start, &from_end }; 9175 char name[1000]; 9176 netconf_urlfilter_t start, end; 9177 9178 assert(v); 9179 9180 ret_code = EINVAL; 9181 9182 /* filter_url indicates how many to expect */ 9183 if (!valid_range(wp, value, v)){ 9184 websBufferWrite(wp, "Invalid url filter string <b>%s</b><br>",value); 9185 return; 9186 } 9187 n = atoi(value); 9188 9189 for (i = 0; i <= n; i++) { 9190 /* Set up field names */ 9191 for (j = 0; j < ARRAYSIZE(fields); j++) { 9192 snprintf(name, sizeof(name), fields[j].name, i); 9193 if (!(*locals[j] = websGetVar(wp, name, NULL))) 9194 break; 9195 } 9196 /* Incomplete web page */ 9197 if (j < ARRAYSIZE(fields)) 9198 continue; 9199 /* URL */ 9200 snprintf(name, sizeof(name), "filter_url_addr%d", i); 9201 if (!(url_addr = websGetVar(wp, name, NULL))) { 9202 del_filter_url(i); 9203 continue; 9204 } 9205 /* Enable is a checkbox */ 9206 snprintf(name, sizeof(name), "filter_url_enable%d", i); 9207 if (websGetVar(wp, name, NULL)) 9208 enable = "on"; 9209 else 9210 enable = "off"; 9211 /* Delete entry if all fields are blank */ 9212 if (!*from_start && !*from_end) { 9213 del_filter_url(i); 9214 continue; 9215 } 9216 /* Fill in empty fields with default values */ 9217 if (!*from_start) from_start = from_end; 9218 if (!*from_end) from_end = from_start; 9219 if (!*from_start || !*from_end) { 9220 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address Range<br>", v->longname); 9221 continue; 9222 } 9223 /* Check individual fields */ 9224 if (!valid_ipaddr(wp, from_start, &fields[0]) || 9225 !valid_ipaddr(wp, from_end, &fields[1])) 9226 continue; 9227 /* Check dependencies between fields */ 9228 if (ntohl(inet_addr(from_start)) > ntohl(inet_addr(from_end))) { 9229 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9230 fields[0].longname, from_start, fields[1].longname, from_end); 9231 continue; 9232 } 9233 9234 /* Set up parameters */ 9235 memset(&start, 0, sizeof(netconf_urlfilter_t)); 9236 (void) inet_aton(from_start, &start.match.src.ipaddr); 9237 start.match.src.netmask.s_addr = htonl(0xffffffff); 9238 strcpy(start.url, url_addr); 9239 if (!strcmp(enable, "off")) 9240 start.match.flags |= NETCONF_DISABLED; 9241 memcpy(&end, &start, sizeof(netconf_urlfilter_t)); 9242 (void) inet_aton(from_end, &end.match.src.ipaddr); 9243 9244 /* Do it */ 9245 valid = set_filter_url(i, &start, &end); 9246 a_assert(valid); 9247 } 9248 9249 ret_code = 0; 9250} 9251#endif /* __CONFIG_URLFILTER__ */ 9252 9253static void 9254validate_forward_port(webs_t wp, char *value, struct variable *v, char *varname) 9255{ 9256 int n, i, j; 9257 bool valid; 9258 struct variable fields[] = { 9259 { name: "forward_port_proto%d", longname: "Port Forward Protocol", argv: ARGV("tcp", "udp") }, 9260 { name: "forward_port_from_start%d", longname: "Port Forward Starting WAN Port", argv: ARGV("0", "65535") }, 9261 { name: "forward_port_from_end%d", longname: "Port Forward Ending WAN Port", argv: ARGV("0", "65535") }, 9262 { name: "forward_port_to_ip%d", longname: "Port Forward LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 9263 { name: "forward_port_to_start%d", longname: "Port Forward Starting LAN Port", argv: ARGV("0", "65535") }, 9264 { name: "forward_port_to_end%d", longname: "Port Forward Ending LAN Port", argv: ARGV("0", "65535") }, 9265 }; 9266 char *proto=NULL, *from_start=NULL, *from_end=NULL; 9267 char *to_ip=NULL, *to_start=NULL, *to_end=NULL, *enable=NULL; 9268 char **locals[] = { &proto, &from_start, &from_end, &to_ip, &to_start, &to_end }; 9269 char name[1000]; 9270 netconf_nat_t nat; 9271 9272 assert(v); 9273 9274 ret_code = EINVAL; 9275 9276 /* forward_port indicates how many to expect */ 9277 if (!valid_range(wp, value, v)){ 9278 websBufferWrite(wp, "Invalid forward port string <b>%s</b><br>",value); 9279 return; 9280 } 9281 n = atoi(value); 9282 9283 for (i = 0; i <= n; i++) { 9284 /* Set up field names */ 9285 for (j = 0; j < ARRAYSIZE(fields); j++) { 9286 snprintf(name, sizeof(name), fields[j].name, i); 9287 if (!(*locals[j] = websGetVar(wp, name, NULL))) 9288 break; 9289 } 9290 /* Incomplete web page */ 9291 if (j < ARRAYSIZE(fields)) 9292 continue; 9293 /* Enable is a checkbox */ 9294 snprintf(name, sizeof(name), "forward_port_enable%d", i); 9295 if (websGetVar(wp, name, NULL)) 9296 enable = "on"; 9297 else 9298 enable = "off"; 9299 /* Delete entry if all fields are blank */ 9300 if (!*from_start && !*from_end && !*to_ip && !*to_start && !*to_end) { 9301 del_forward_port(i); 9302 continue; 9303 } 9304 /* Fill in empty fields with default values */ 9305 if (!*from_start) from_start = from_end; 9306 if (!*from_end) from_end = from_start; 9307 if (!*to_start && !*to_end) 9308 to_start = from_start; 9309 if (!*to_start) to_start = to_end; 9310 if (!*to_end) to_end = to_start; 9311 if (!*from_start || !*from_end) { 9312 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address Range<br>", v->longname); 9313 continue; 9314 } 9315 if (!*to_ip) { 9316 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address<br>", v->longname); 9317 continue; 9318 } 9319 if (!*to_start || !*to_end) { 9320 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Destination Port Range<br>", v->longname); 9321 continue; 9322 } 9323 /* Check individual fields */ 9324 if (!valid_choice(wp, proto, &fields[0]) || 9325 !valid_range(wp, from_start, &fields[1]) || 9326 !valid_range(wp, from_end, &fields[2]) || 9327 !valid_ipaddr(wp, to_ip, &fields[3]) || 9328 !valid_range(wp, to_start, &fields[4]) || 9329 !valid_range(wp, to_end, &fields[5])) 9330 continue; 9331 if (atoi(from_start) > atoi(from_end)) { 9332 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9333 fields[1].longname, from_start, fields[2].longname, from_end); 9334 continue; 9335 } 9336 if (atoi(to_start) > atoi(to_end)) { 9337 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9338 fields[4].longname, to_start, fields[5].longname, to_end); 9339 continue; 9340 } 9341 if ((atoi(from_end) - atoi(from_start)) != (atoi(to_end) - atoi(to_start))) { 9342 websBufferWrite(wp, "Invalid <b>%s</b>: WAN Port Range and LAN Port Range must be the same size<br>", v->longname); 9343 continue; 9344 } 9345 9346 /* Set up parameters */ 9347 memset(&nat, 0, sizeof(netconf_nat_t)); 9348 if (!strcmp(proto, "tcp")) 9349 nat.match.ipproto = IPPROTO_TCP; 9350 else if (!strcmp(proto, "udp")) 9351 nat.match.ipproto = IPPROTO_UDP; 9352 nat.match.dst.ports[0] = htons(atoi(from_start)); 9353 nat.match.dst.ports[1] = htons(atoi(from_end)); 9354 (void) inet_aton(to_ip, &nat.ipaddr); 9355 nat.ports[0] = htons(atoi(to_start)); 9356 nat.ports[1] = htons(atoi(to_end)); 9357 if (!strcmp(enable, "off")) 9358 nat.match.flags |= NETCONF_DISABLED; 9359 9360 /* Do it */ 9361 valid = set_forward_port(i, &nat); 9362 a_assert(valid); 9363 } 9364 ret_code =0; 9365} 9366 9367#if !defined(AUTOFW_PORT_DEPRECATED) 9368static void 9369validate_autofw_port(webs_t wp, char *value, struct variable *v, char *varname) 9370{ 9371 int n, i, j; 9372 bool valid; 9373 struct variable fields[] = { 9374 { name: "autofw_port_out_proto%d", longname: "Outbound Protocol", argv: ARGV("tcp", "udp") }, 9375 { name: "autofw_port_out_start%d", longname: "Outbound Port Start", argv: ARGV("0", "65535") }, 9376 { name: "autofw_port_out_end%d", longname: "Outbound Port End", argv: ARGV("0", "65535") }, 9377 { name: "autofw_port_in_proto%d", longname: "Inbound Protocol", argv: ARGV("tcp", "udp") }, 9378 { name: "autofw_port_in_start%d", longname: "Inbound Port Start", argv: ARGV("0", "65535") }, 9379 { name: "autofw_port_in_end%d", longname: "Inbound Port End", argv: ARGV("0", "65535") }, 9380 { name: "autofw_port_to_start%d", longname: "To Port Start", argv: ARGV("0", "65535") }, 9381 { name: "autofw_port_to_end%d", longname: "To Port End", argv: ARGV("0", "65535") }, 9382 }; 9383 char *out_proto=NULL, *out_start=NULL, *out_end=NULL, *in_proto=NULL; 9384 char *in_start=NULL, *in_end=NULL, *to_start=NULL, *to_end=NULL, *enable=NULL; 9385 char **locals[] = { &out_proto, &out_start, &out_end, &in_proto, &in_start, &in_end, &to_start, &to_end }; 9386 char name[1000]; 9387 netconf_app_t app; 9388 9389 assert(v); 9390 9391 ret_code = EINVAL; 9392 9393 /* autofw_port indicates how many to expect */ 9394 if (!valid_range(wp, value, v)){ 9395 websBufferWrite(wp, "Invalid auto forward port string <b>%s</b><br>",value); 9396 return; 9397 } 9398 n = atoi(value); 9399 9400 for (i = 0; i <= n; i++) { 9401 /* Set up field names */ 9402 for (j = 0; j < ARRAYSIZE(fields); j++) { 9403 snprintf(name, sizeof(name), fields[j].name, i); 9404 if (!(*locals[j] = websGetVar(wp, name, NULL))) 9405 break; 9406 } 9407 /* Incomplete web page */ 9408 if (j < ARRAYSIZE(fields)) 9409 continue; 9410 /* Enable is a checkbox */ 9411 snprintf(name, sizeof(name), "autofw_port_enable%d", i); 9412 if (websGetVar(wp, name, NULL)) 9413 enable = "on"; 9414 else 9415 enable = "off"; 9416 /* Delete entry if all fields are blank */ 9417 if (!*out_start && !*out_end && !*in_start && !*in_end && !*to_start && !*to_end) { 9418 del_autofw_port(i); 9419 continue; 9420 } 9421 /* Fill in empty fields with default values */ 9422 if (!*out_start) out_start = out_end; 9423 if (!*out_end) out_end = out_start; 9424 if (!*in_start) in_start = in_end; 9425 if (!*in_end) in_end = in_start; 9426 if (!*to_start && !*to_end) 9427 to_start = in_start; 9428 if (!*to_start) to_start = to_end; 9429 if (!*to_end) to_end = to_start; 9430 if (!*out_start || !*out_end) { 9431 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an Outbound Port Range<br>", v->longname); 9432 continue; 9433 } 9434 if (!*in_start || !*in_end) { 9435 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an Inbound Port Range<br>", v->longname); 9436 continue; 9437 } 9438 if (!*to_start || !*to_end) { 9439 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a To Port Range<br>", v->longname); 9440 continue; 9441 } 9442 /* Check individual fields */ 9443 if (!valid_choice(wp, out_proto, &fields[0]) || 9444 !valid_range(wp, out_start, &fields[1]) || 9445 !valid_range(wp, out_end, &fields[2]) || 9446 !valid_choice(wp, in_proto, &fields[3]) || 9447 !valid_range(wp, in_start, &fields[4]) || 9448 !valid_range(wp, in_end, &fields[5]) || 9449 !valid_range(wp, to_start, &fields[6]) || 9450 !valid_range(wp, to_end, &fields[7])) 9451 continue; 9452 /* Check dependencies between fields */ 9453 if (atoi(out_start) > atoi(out_end)) { 9454 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9455 fields[1].longname, out_start, fields[2].longname, out_end); 9456 continue; 9457 } 9458 if (atoi(in_start) > atoi(in_end)) { 9459 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9460 fields[4].longname, in_start, fields[5].longname, in_end); 9461 continue; 9462 } 9463 if (atoi(to_start) > atoi(to_end)) { 9464 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 9465 fields[6].longname, in_start, fields[7].longname, in_end); 9466 continue; 9467 } 9468 if ((atoi(in_end) - atoi(in_start)) != (atoi(to_end) - atoi(to_start))) { 9469 websBufferWrite(wp, "Invalid <b>%s</b>: Inbound Port Range and To Port Range must be the same size<br>", v->longname); 9470 continue; 9471 } 9472#ifdef NEW_PORT_TRIG 9473 if ((atoi(in_end) - atoi(in_start)) > 100) { 9474 websBufferWrite(wp, "Invalid <b>%s</b>: Inbound Port Range must be less than 100<br>", v->longname); 9475 continue; 9476 } 9477#endif 9478 9479 /* Set up parameters */ 9480 memset(&app, 0, sizeof(netconf_app_t)); 9481 if (!strcmp(out_proto, "tcp")) 9482 app.match.ipproto = IPPROTO_TCP; 9483 else if (!strcmp(out_proto, "udp")) 9484 app.match.ipproto = IPPROTO_UDP; 9485 app.match.dst.ports[0] = htons(atoi(out_start)); 9486 app.match.dst.ports[1] = htons(atoi(out_end)); 9487 if (!strcmp(in_proto, "tcp")) 9488 app.proto = IPPROTO_TCP; 9489 else if (!strcmp(in_proto, "udp")) 9490 app.proto = IPPROTO_UDP; 9491 app.dport[0] = htons(atoi(in_start)); 9492 app.dport[1] = htons(atoi(in_end)); 9493 app.to[0] = htons(atoi(to_start)); 9494 app.to[1] = htons(atoi(to_end)); 9495 if (!strcmp(enable, "off")) 9496 app.match.flags |= NETCONF_DISABLED; 9497 9498 /* Do it */ 9499 valid = set_autofw_port(i, &app); 9500 a_assert(valid); 9501 } 9502 ret_code = 0; 9503} 9504#endif /* !AUTOFW_PORT_DEPRECATED */ 9505#endif /* __CONFIG_NAT__ */ 9506 9507/* Validate HTML input data modified by Web user and stored in NVRAM */ 9508static void 9509validate_trf_mgmt_port(webs_t wp, char *value, struct variable *v, char *varname) 9510{ 9511 int n, i, j, enable; 9512 bool valid; 9513 struct variable fields[] = { 9514 { name: "%strf_mgmt_port_proto%d", longname: "Traffic Management Protocol", argv: ARGV("tcp", "udp", "mac") }, 9515 { name: "%strf_mgmt_port_sport%d", longname: "Traffic Management Source Port", argv: ARGV("0", "65535") }, 9516 { name: "%strf_mgmt_port_dport%d", longname: "Traffic Management Dest Port", argv: ARGV("0", "65535") }, 9517 { name: "%strf_mgmt_port_macaddr%d", longname: "Traffic Management Mac Addr", argv: NULL }, 9518 { name: "%strf_mgmt_port_prio%d", longname: "Traffic Management Priority", argv: ARGV("0", "1", "2", "3") }, 9519 }; 9520 char *proto=NULL, *prio=NULL, *flags=NULL; 9521 char *sport=NULL, *dport=NULL, *dmacaddr=NULL; 9522 char **locals[] = { &proto, &sport, &dport, &dmacaddr, &prio, &flags }; 9523 char name[1000]; 9524 netconf_trmgmt_t trm; 9525 char prefix[32]; 9526 char *wlunit = nvram_get("wl_unit"); 9527 9528 snprintf(prefix, sizeof(prefix), "wl%s_", wlunit); 9529 9530 assert(v); 9531 9532 ret_code = EINVAL; 9533 9534 /* forward_port indicates how many to expect */ 9535 if (!valid_range(wp, value, v)){ 9536 websBufferWrite(wp, "Invalid traffic management port string <b>%s</b><br>",value); 9537 return; 9538 } 9539 n = atoi(value); 9540 9541 for (i = 0; i <= n; i++) { 9542 /* Set up field names */ 9543 for (j = 0; j < ARRAYSIZE(fields); j++) { 9544 snprintf(name, sizeof(name), fields[j].name, prefix, i); 9545 if (!(*locals[j] = websGetVar(wp, name, NULL))) 9546 break; 9547 } 9548 /* Incomplete web page */ 9549 if (j < ARRAYSIZE(fields)) 9550 continue; 9551 9552 /* Set up parameters */ 9553 memset(&trm, 0, sizeof(netconf_trmgmt_t)); 9554 9555 /* Enable is a checkbox */ 9556 snprintf(name, sizeof(name), "%strf_mgmt_port_enable%d", prefix, i); 9557 if (websGetVar(wp, name, NULL)) 9558 enable = 1; 9559 else 9560 enable = 0; 9561 9562 /* Check favored checkbox */ 9563 snprintf(name, sizeof(name), "%strf_mgmt_port_favored%d", prefix, i); 9564 if (websGetVar(wp, name, NULL)) 9565 trm.favored = 1; 9566 else 9567 trm.favored = 0; 9568 9569 /* Check protocol field, remove if not valid */ 9570 if (!valid_choice(wp, proto, &fields[0])) { 9571 del_trf_mgmt_port(prefix, i); 9572 continue; 9573 } 9574 9575 if (!strcmp(proto, "tcp")) 9576 trm.match.ipproto = IPPROTO_TCP; 9577 else if (!strcmp(proto, "udp")) 9578 trm.match.ipproto = IPPROTO_UDP; 9579 else if (!strcmp(proto, "mac")) 9580 trm.match.ipproto = IPPROTO_IP; 9581 9582 9583 if (trm.match.ipproto == IPPROTO_IP) { 9584 /* Delete entry if mac address not specified for proto type "all" */ 9585 if (!*dmacaddr || !*prio) { 9586 if (enable) 9587 websBufferWrite(wp, "Invalid <b>settings at index %d</b> MAC address<br>",i); 9588 del_trf_mgmt_port(prefix, i); 9589 continue; 9590 } 9591 9592 /* Check individual fields */ 9593 if (!valid_hwaddr(wp, dmacaddr, &fields[3]) || 9594 !valid_choice(wp, prio, &fields[4])) { 9595 continue; 9596 } 9597 9598 /* Set up parameters */ 9599 trm.prio = atoi(prio); 9600 (void) ether_atoe((const char *)dmacaddr, (unsigned char *)&trm.match.mac); 9601 } else { 9602 /* Delete entry if priority field is blank */ 9603 if (!*prio ) { 9604 if (enable) 9605 websBufferWrite(wp, "Invalid <b>settings at index %d </b><br>",i); 9606 del_trf_mgmt_port(prefix, i); 9607 continue; 9608 } 9609 trm.prio = atoi(prio); 9610 9611 /* Validate source port number, "no value" treatred as zero value */ 9612 if (*sport) { 9613 if (!valid_range(wp, sport, &fields[1])) { 9614 if (enable) 9615 websBufferWrite(wp, "Invalid <b>settings at index %d </b><br>",i); 9616 del_trf_mgmt_port(prefix, i); 9617 continue; 9618 } 9619 trm.match.src.ports[0] = htons(atoi(sport)); 9620 } 9621 9622 /* Validate destination port number, "no value" treatred as zero value */ 9623 if (*dport) { 9624 if (!valid_range(wp, dport, &fields[2])) { 9625 if (enable) 9626 websBufferWrite(wp, "Invalid <b>settings at index %d </b><br>",i); 9627 del_trf_mgmt_port(prefix, i); 9628 continue; 9629 } 9630 trm.match.dst.ports[0] = htons(atoi(dport)); 9631 } 9632 } 9633 9634 if (enable == 0) 9635 trm.match.flags |= NETCONF_DISABLED; 9636 9637 /* Do it */ 9638 valid = set_trf_mgmt_port(prefix, i, &trm); 9639 a_assert(valid); 9640 } 9641 ret_code =0; 9642} 9643 9644static void 9645validate_lan_route(webs_t wp, char *value, struct variable *v, char *varname) 9646{ 9647 int n, i; 9648 char buf[1000] = "", *cur = buf; 9649 char lan_ipaddr[20] ="lan_ipaddr"; 9650 char lan_netmask[20]="lan_netmask"; 9651 char *lan_argv[3]; 9652 9653 struct variable lan_route_variables[] = { 9654 { longname: "Route IP Address", argv: NULL }, 9655 { longname: "Route Subnet Mask", argv: NULL }, 9656 { longname: "Route Gateway", argv: NULL }, 9657 { longname: "Route Metric", argv: ARGV("0", "15") }, 9658 }; 9659 9660 assert(v); 9661 9662 ret_code = EINVAL; 9663 9664 /* Insert name overrides */ 9665 if (varname) 9666 { 9667 char index[5]; 9668 9669 if (!get_index_string(v->prefix,varname, 9670 index,sizeof(index))) 9671 return; 9672 9673 snprintf(lan_ipaddr,sizeof(lan_ipaddr),"lan%s_ipaddr",index); 9674 snprintf(lan_netmask,sizeof(lan_netmask),"lan%s_netmask",index); 9675 } 9676 9677 n = atoi(value); 9678 9679 for (i = 0; i < n; i++) { 9680 char lan_route_ipaddr[] = "lan_route_ipaddrXXX"; 9681 char lan_route_netmask[] = "lan_route_netmaskXXX"; 9682 char lan_route_gateway[] = "lan_route_gatewayXXX"; 9683 char lan_route_metric[] = "lan_route_metricXXX"; 9684 char *ipaddr, *netmask, *gateway, *metric; 9685 9686 snprintf(lan_route_ipaddr, sizeof(lan_route_ipaddr), "%s_ipaddr%d", v->name, i); 9687 snprintf(lan_route_netmask, sizeof(lan_route_netmask), "%s_netmask%d", v->name, i); 9688 snprintf(lan_route_gateway, sizeof(lan_route_gateway), "%s_gateway%d", v->name, i); 9689 snprintf(lan_route_metric, sizeof(lan_route_metric), "%s_metric%d", v->name, i); 9690 if (!(ipaddr = websGetVar(wp, lan_route_ipaddr, NULL)) || 9691 !(netmask = websGetVar(wp, lan_route_netmask, NULL)) || 9692 !(gateway = websGetVar(wp, lan_route_gateway, NULL)) || 9693 !(metric = websGetVar(wp, lan_route_metric, NULL))) 9694 return; 9695 if (!*ipaddr && !*netmask && !*gateway && !*metric) 9696 continue; 9697 if (!*ipaddr && !*netmask && *gateway) { 9698 ipaddr = "0.0.0.0"; 9699 netmask = "0.0.0.0"; 9700 } 9701 if (!*gateway) 9702 gateway = "0.0.0.0"; 9703 if (!*metric) 9704 metric = "0"; 9705 if (!*ipaddr) { 9706 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an IP Address<br>", v->longname); 9707 continue; 9708 } 9709 if (!*netmask) { 9710 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Subnet Mask<br>", v->longname); 9711 continue; 9712 } 9713 9714 lan_argv[0]=lan_ipaddr; 9715 lan_argv[1]=lan_netmask; 9716 lan_argv[2]=NULL; 9717 9718 lan_route_variables[2].argv = lan_argv; 9719 if (!valid_ipaddr(wp, ipaddr, &lan_route_variables[0]) || 9720 !valid_ipaddr(wp, netmask, &lan_route_variables[1]) || 9721 !valid_ipaddr(wp, gateway, &lan_route_variables[2]) || 9722 !valid_range(wp, metric, &lan_route_variables[3])) 9723 continue; 9724 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s:%s:%s:%s", 9725 cur == buf ? "" : " ", ipaddr, netmask, gateway, metric); 9726 } 9727 9728 if (varname) 9729 nvram_set(varname,buf); 9730 else 9731 nvram_set(v->name, buf); 9732 ret_code = 0; 9733} 9734 9735#ifdef __CONFIG_EMF__ 9736static void 9737validate_emf_entry(webs_t wp, char *value, struct variable *v, char *varname) 9738{ 9739 int n, i; 9740 char buf[1000] = "", temp[128], *cur = buf; 9741 9742 assert(v); 9743 9744 bzero(buf, sizeof(buf)); 9745 ret_code = EINVAL; 9746 9747 n = atoi(value); 9748 9749 for (i = 0; i < n; i++) { 9750 char emf_entry_mgrp[] = "emf_entry_mgrpXXX"; 9751 char emf_entry_if[] = "emf_entry_ifXXX"; 9752 char *mgrp, *ifname; 9753 struct in_addr mgrp_addr; 9754 9755 snprintf(emf_entry_mgrp, sizeof(emf_entry_mgrp), "%s_mgrp%d", v->name, i); 9756 9757 snprintf(emf_entry_if, sizeof(emf_entry_if), "%s_if%d", v->name, i); 9758 9759 if (!(mgrp = websGetVar(wp, emf_entry_mgrp, NULL)) || 9760 !(ifname = websGetVar(wp, emf_entry_if, NULL))) 9761 return; 9762 9763 if (!*mgrp && !*ifname) 9764 continue; 9765 9766#define IP_ISMULTI(addr) (((addr) & 0xf0000000) == 0xe0000000) 9767 if ((inet_aton(mgrp, &mgrp_addr) == 0) || 9768 (!IP_ISMULTI(ntohl(mgrp_addr.s_addr)))) { 9769 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a valid multicast IP Address<br>", 9770 v->longname); 9771 return; 9772 } 9773 9774 if ((*ifname) == 0) { 9775 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN interface name<br>", 9776 v->longname); 9777 return; 9778 } 9779 9780 if ((strstr(nvram_safe_get("br0_ifnames"), ifname) == NULL) && 9781 (strstr(nvram_safe_get("new_lan_ifnames"), ifname) == NULL) && 9782 (strncmp(ifname, "wds", 3) != 0)) { 9783 websBufferWrite(wp, "Invalid <b>%s</b>: must specify one of the bridge interfaces<br>", 9784 v->longname); 9785 return; 9786 } 9787 9788 /* Check for duplicate MFDB entry */ 9789 snprintf(temp, 128, "%s:%s", mgrp, ifname); 9790 if (strstr(buf, temp) != NULL) 9791 continue; 9792 9793 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s:%s", 9794 cur == buf ? "" : " ", mgrp, ifname); 9795 } 9796 9797 if (varname) 9798 nvram_set(varname, buf); 9799 else 9800 nvram_set(v->name, buf); 9801 9802 ret_code = 0; 9803 9804 return; 9805} 9806 9807static void 9808validate_emf_uffp_entry(webs_t wp, char *value, struct variable *v, char *varname) 9809{ 9810 int n, i; 9811 char buf[1000] = "", *cur = buf; 9812 9813 assert(v); 9814 9815 bzero(buf, sizeof(buf)); 9816 ret_code = EINVAL; 9817 9818 n = atoi(value); 9819 9820 for (i = 0; i < n; i++) { 9821 char emf_uffp_entry_if[] = "emf_uffp_entry_ifXXX"; 9822 char *ifname; 9823 9824 snprintf(emf_uffp_entry_if, sizeof(emf_uffp_entry_if), "%s_if%d", v->name, i); 9825 9826 if (!(ifname = websGetVar(wp, emf_uffp_entry_if, NULL))) 9827 return; 9828 9829 if (!*ifname) 9830 continue; 9831 9832 if ((*ifname) == 0) { 9833 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN interface name<br>", 9834 v->longname); 9835 return; 9836 } 9837 9838 if ((strstr(nvram_safe_get("br0_ifnames"), ifname) == NULL) && 9839 (strstr(nvram_safe_get("new_lan_ifnames"), ifname) == NULL) && 9840 (strncmp(ifname, "wds", 3) != 0)) { 9841 websBufferWrite(wp, "Invalid <b>%s</b>: must specify one of the bridge interfaces<br>", 9842 v->longname); 9843 return; 9844 } 9845 9846 /* Duplicate UFFP interface entry */ 9847 if (strstr(buf, ifname) != NULL) 9848 continue; 9849 9850 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s", 9851 cur == buf ? "" : " ", ifname); 9852 } 9853 9854 if (varname) 9855 nvram_set(varname, buf); 9856 else 9857 nvram_set(v->name, buf); 9858 9859 ret_code = 0; 9860 9861 return; 9862} 9863 9864static void 9865validate_emf_rtport_entry(webs_t wp, char *value, struct variable *v, char *varname) 9866{ 9867 int n, i; 9868 char buf[1000] = "", *cur = buf; 9869 9870 assert(v); 9871 9872 bzero(buf, sizeof(buf)); 9873 ret_code = EINVAL; 9874 9875 n = atoi(value); 9876 9877 for (i = 0; i < n; i++) { 9878 char emf_rtport_entry_if[] = "emf_rtport_entry_ifXXX"; 9879 char *ifname; 9880 9881 snprintf(emf_rtport_entry_if, sizeof(emf_rtport_entry_if), "%s_if%d", v->name, i); 9882 9883 if (!(ifname = websGetVar(wp, emf_rtport_entry_if, NULL))) 9884 return; 9885 9886 if (!*ifname) 9887 continue; 9888 9889 if ((*ifname) == 0) { 9890 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN interface name<br>", 9891 v->longname); 9892 return; 9893 } 9894 9895 if ((strstr(nvram_safe_get("br0_ifnames"), ifname) == NULL) && 9896 (strstr(nvram_safe_get("new_lan_ifnames"), ifname) == NULL) && 9897 (strncmp(ifname, "wds", 3) != 0)) { 9898 websBufferWrite(wp, "Invalid <b>%s</b>: must specify one of the bridge interfaces<br>", 9899 v->longname); 9900 return; 9901 } 9902 9903 /* Duplicate rtport interface entry */ 9904 if (strstr(buf, ifname) != NULL) 9905 continue; 9906 9907 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s", 9908 cur == buf ? "" : " ", ifname); 9909 } 9910 9911 if (varname) 9912 nvram_set(varname, buf); 9913 else 9914 nvram_set(v->name, buf); 9915 9916 ret_code = 0; 9917 9918 return; 9919} 9920#endif /* __CONFIG_EMF__ */ 9921 9922#ifdef __CONFIG_NAT__ 9923static void 9924validate_wan_route(webs_t wp, char *value, struct variable *v, char *varname) 9925{ 9926 int n, i; 9927 char buf[1000] = "", *cur = buf; 9928 struct variable wan_route_variables[] = { 9929 { longname: "Route IP Address", argv: NULL }, 9930 { longname: "Route Subnet Mask", argv: NULL }, 9931 { longname: "Route Gateway", argv: NULL }, 9932 { longname: "Route Metric", argv: ARGV("0", "15") }, 9933 }; 9934 9935 assert(v); 9936 9937 ret_code = EINVAL; 9938 9939 n = atoi(value); 9940 9941 for (i = 0; i < n; i++) { 9942 char wan_route_ipaddr[] = "wan_route_ipaddrXXX"; 9943 char wan_route_netmask[] = "wan_route_netmaskXXX"; 9944 char wan_route_gateway[] = "wan_route_gatewayXXX"; 9945 char wan_route_metric[] = "wan_route_metricXXX"; 9946 char *ipaddr, *netmask, *gateway, *metric; 9947 9948 snprintf(wan_route_ipaddr, sizeof(wan_route_ipaddr), "%s_ipaddr%d", v->name, i); 9949 snprintf(wan_route_netmask, sizeof(wan_route_netmask), "%s_netmask%d", v->name, i); 9950 snprintf(wan_route_gateway, sizeof(wan_route_gateway), "%s_gateway%d", v->name, i); 9951 snprintf(wan_route_metric, sizeof(wan_route_metric), "%s_metric%d", v->name, i); 9952 if (!(ipaddr = websGetVar(wp, wan_route_ipaddr, NULL)) || 9953 !(netmask = websGetVar(wp, wan_route_netmask, NULL)) || 9954 !(gateway = websGetVar(wp, wan_route_gateway, NULL)) || 9955 !(metric = websGetVar(wp, wan_route_metric, NULL))) 9956 continue; 9957 if (!*ipaddr && !*netmask && !*gateway && !*metric) 9958 continue; 9959 if (!*ipaddr && !*netmask && *gateway) { 9960 ipaddr = "0.0.0.0"; 9961 netmask = "0.0.0.0"; 9962 } 9963 if (!*gateway) 9964 gateway = "0.0.0.0"; 9965 if (!*metric) 9966 metric = "0"; 9967 if (!*ipaddr) { 9968 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an IP Address<br>", v->longname); 9969 continue; 9970 } 9971 if (!*netmask) { 9972 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Subnet Mask<br>", v->longname); 9973 continue; 9974 } 9975 if (!valid_ipaddr(wp, ipaddr, &wan_route_variables[0]) || 9976 !valid_ipaddr(wp, netmask, &wan_route_variables[1]) || 9977 !valid_ipaddr(wp, gateway, &wan_route_variables[2]) || 9978 !valid_range(wp, metric, &wan_route_variables[3])) 9979 continue; 9980 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s:%s:%s:%s", 9981 cur == buf ? "" : " ", ipaddr, netmask, gateway, metric); 9982 } 9983 9984 9985 nvram_set(v->name, buf); 9986 9987 ret_code = 0; 9988} 9989#endif /* __CONFIG_NAT__ */ 9990 9991/* 9992*/ 9993#ifdef __CONFIG_IPV6__ 9994static void 9995validate_ipv6mode(webs_t wp, char *value, struct variable *v , char *varname) 9996{ 9997 char *pvarname; 9998 9999 assert(v); 10000 10001 if (!valid_range(wp, value, v)) { 10002 websBufferWrite(wp, "<p>Invalid <b>%s</b> %s: Unsupported IPv6 mode.<br>", 10003 v->longname, value); 10004 ret_code = EINVAL; 10005 return; 10006 } 10007 10008 if (varname) 10009 pvarname = varname; 10010 else 10011 pvarname = v->name; 10012 10013 nvram_set(pvarname, value); 10014 10015 ret_code = 0; 10016} 10017 10018static void 10019validate_ipv6prefix(webs_t wp, char *value, struct variable *v , char *varname) 10020{ 10021 char prefix[48]; 10022 struct in6_addr addr; 10023 int bits = -1; 10024 int i; 10025 10026 assert(v); 10027 10028 i = sscanf(value, "%[^/]/%d", prefix, &bits); 10029 if (i != 2) { 10030 websBufferWrite(wp, "<p>Invalid <b>%s</b> %s: IPv6 network prefix contains an IPv6 address followed by a slash(/) and then by the number of netmask bits.<br>", 10031 v->longname, value); 10032 ret_code = EINVAL; 10033 return; 10034 } 10035 if (bits >= 128 || bits <= 0) { 10036 websBufferWrite(wp, "<p>Invalid <b>%s</b> %s: the number of netmask bits after shash(/) is between 1~127.<br>", 10037 v->longname, value); 10038 ret_code = EINVAL; 10039 return; 10040 } 10041 if (inet_pton(AF_INET6, prefix, &addr) <= 0) { 10042 websBufferWrite(wp, "<p>Invalid <b>%s</b> %s: Not a proper IPv6 address before slash(/).<br>", 10043 v->longname, value); 10044 ret_code = EINVAL; 10045 return; 10046 } 10047 10048 if (varname) 10049 nvram_set(varname, value); 10050 else 10051 nvram_set(v->name, value); 10052 10053 ret_code = 0; 10054} 10055 10056static void 10057validate_ipv6addr(webs_t wp, char *value, struct variable *v , char *varname) 10058{ 10059 struct in6_addr addr; 10060 10061 assert(v); 10062 10063 if ((inet_pton(AF_INET6, value, &addr) <= 0)) { 10064 websBufferWrite(wp, "<p>Invalid <b>%s</b> %s: Incorrect IPv6 address format.<br>", 10065 v->longname, value); 10066 ret_code = EINVAL; 10067 return; 10068 } 10069 10070 if (varname) 10071 nvram_set(varname, value); 10072 else 10073 nvram_set(v->name, value); 10074 10075 ret_code = 0; 10076} 10077 10078#endif /* __CONFIG_IPV6__ */ 10079/* 10080*/ 10081 10082static void 10083validate_wl_auth(webs_t wp, char *value, struct variable *v, char *varname) 10084{ 10085 10086 assert(v); 10087 10088 ret_code = EINVAL; 10089 10090 if (!valid_choice(wp, value, v)){ 10091 websBufferWrite(wp, "Invalid auth value string <b>%s</b><br>",value); 10092 return; 10093 } 10094 10095 if (!strcmp(value, "1")) { 10096 char *wep = websGetVar(wp, "wl_wep", ""); 10097 if (!wep || strcmp(wep, "enabled")) { 10098 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>802.11 Authentication</b> is <b>%s</b><br>", value); 10099 return; 10100 } 10101 else { 10102 /* Clear nvrams that conflict with this setting */ 10103 nvram_set("wl_akm", ""); 10104 } 10105 } 10106 10107 if (varname) 10108 nvram_set(varname, value); 10109 else 10110 nvram_set(v->name, value); 10111 ret_code = 0; 10112} 10113 10114static void 10115validate_wl_preauth(webs_t wp, char *value, struct variable *v, char *varname) 10116{ 10117 char *ptr=NULL; 10118 10119 assert(v); 10120 10121 ptr =( (varname) ? varname : v->name ); 10122 10123 if (!strcmp(value, "disabled")) 10124 nvram_set(ptr, "0"); 10125 else 10126 nvram_set(ptr, "1"); 10127 10128 ret_code =0; 10129 10130 return; 10131} 10132 10133static void 10134validate_wl_auth_mode(webs_t wp, char *value, struct variable *v, char *varname) 10135{ 10136 10137 assert(v); 10138 10139 ret_code = EINVAL; 10140 10141 if (!valid_choice(wp, value, v)){ 10142 websBufferWrite(wp, "Invalid auto mode string <b>%s</b>",value); 10143 return; 10144 } 10145 10146 if (!strcmp(value, "radius")) { 10147 char *wep = websGetVar(wp, "wl_wep", ""); 10148 char *ipaddr = websGetVar(wp, "wl_radius_ipaddr", ""); 10149 if (!wep || strcmp(wep, "enabled")) { 10150 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>Network Authentication</b> is <b>%s</b><br>", value); 10151 return; 10152 } 10153 if (!ipaddr || !strcmp(ipaddr, "")) { 10154 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>RADIUS Server</b><br>", v->longname); 10155 return; 10156 } 10157 } 10158 10159 if (varname) 10160 nvram_set(varname, value); 10161 else 10162 nvram_set(v->name, value); 10163 10164 ret_code = 0; 10165 10166} 10167 10168static void 10169validate_wl_akm(webs_t wp, char *value, struct variable *v, char *varname) 10170{ 10171 char akms[WLC_IOCTL_SMLEN] = ""; 10172 char *wpa=NULL, *psk=NULL; 10173 char *wpa2=NULL, *psk2=NULL, *brcm_psk=NULL; 10174 char *name; 10175 10176 assert(v); 10177 10178 ret_code = EINVAL; 10179 10180 wpa = websGetVar(wp, "wl_akm_wpa", NULL); 10181 if( !wpa ) 10182 wpa = "disabled"; 10183 psk = websGetVar(wp, "wl_akm_psk", NULL); 10184 if( !psk ) 10185 psk = "disabled"; 10186 wpa2 = websGetVar(wp, "wl_akm_wpa2", NULL); 10187 if( !wpa2 ) 10188 wpa2 = "disabled"; 10189 psk2 = websGetVar(wp, "wl_akm_psk2", NULL); 10190 if( !psk2 ) 10191 psk2 = "disabled"; 10192 brcm_psk = websGetVar(wp, "wl_akm_brcm_psk", NULL); 10193 if( !brcm_psk ) 10194 brcm_psk = "disabled"; 10195 10196 if (!strcmp(wpa, "enabled") 10197 || !strcmp(wpa2, "enabled") 10198 ) { 10199 char *ipaddr = websGetVar(wp, "wl_radius_ipaddr", ""); 10200 if (!ipaddr || !strcmp(ipaddr, "")) { 10201 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>RADIUS Server</b><br>", v->longname); 10202 return; 10203 } 10204 } 10205 10206 if (!strcmp(psk, "enabled") 10207 || !strcmp(psk2, "enabled") 10208 ) { 10209 char *key = websGetVar(wp, "wl_wpa_psk", ""); 10210 if (!key || !strcmp(key, "")) { 10211 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>WPA Pre-Shared Key</b><br>", v->longname); 10212 return; 10213 } 10214 } 10215 10216 if (!strcmp(wpa, "enabled") || !strcmp(psk, "enabled") 10217 || !strcmp(wpa2, "enabled") || !strcmp(psk2, "enabled") || !strcmp(brcm_psk, "enabled") 10218 ) { 10219 char *crypto = websGetVar(wp, "wl_crypto", NULL); 10220 if (!crypto || ( 10221 strcmp(crypto, "tkip") && 10222 strcmp(crypto, "aes") && 10223 strcmp(crypto, "tkip+aes") 10224 )) { 10225 bool wapi_sel = FALSE; 10226 10227 if (wapi_sel == FALSE) { 10228 websBufferWrite(wp, "Invalid <b>%s</b>: <b>Crypto Algorithm</b> mode must be TKIP or AES or TKIP+AES<br>", v->longname); 10229 return; 10230 } 10231 } 10232 } 10233 10234 if (!strcmp(wpa, "enabled")) 10235 strcat(akms, "wpa "); 10236 if (!strcmp(psk, "enabled")) 10237 strcat(akms, "psk "); 10238 if (!strcmp(wpa2, "enabled")) 10239 strcat(akms, "wpa2 "); 10240 if (!strcmp(psk2, "enabled")) 10241 strcat(akms, "psk2 "); 10242 if (!strcmp(brcm_psk, "enabled")) 10243 strcat(akms, "brcm_psk "); 10244 10245 /* WiFi WPA2 requires that WEP be disabled if WPA2 or WPA2-PSK is used, 10246 * GUI has the WEP Enable/Disable field disabled when the user selects 10247 * WPA2, so WEP setting doesn't come in the HTTP buffer, which means we 10248 * must manually turn it off here to disable WEP. 10249 */ 10250 if ((!strcmp(wpa2, "enabled")) || (!strcmp(psk2, "enabled")) 10251 || (!strcmp(brcm_psk, "enabled"))) 10252 nvram_set("wl_wep", "disabled"); 10253 10254 if (varname) 10255 name = varname; 10256 else 10257 name = "wl_akm"; 10258 10259 if (nvram_match(name, akms) != TRUE) { 10260 nvram_set(name, akms); 10261#ifdef __CONFIG_WPS__ 10262 wps_disable_oob(); 10263#endif 10264 } 10265 ret_code = 0; 10266} 10267 10268static void 10269validate_wl_wpa_psk(webs_t wp, char *value, struct variable *v, char *varname) 10270{ 10271 int len = strlen(value); 10272 char *c=NULL; 10273 char *name; 10274 10275 assert(v); 10276 10277 ret_code = EINVAL; 10278 10279 if (len == 64) { 10280 for (c = value; *c; c++) { 10281 if (!isxdigit((int) *c)) { 10282 websBufferWrite(wp, "Invalid <b>%s</b>: character %c is not a hexadecimal digit<br>", v->longname, *c); 10283 return; 10284 } 10285 } 10286 } else if (len < 8 || len > 63) { 10287 websBufferWrite(wp, "Invalid <b>%s</b>: must be between 8 and 63 ASCII characters or 64 hexadecimal digits<br>", v->longname); 10288 return; 10289 } 10290 10291 if (varname) 10292 name = varname; 10293 else 10294 name = v->name; 10295 10296 if (nvram_match(name, value) != TRUE) { 10297 nvram_set(name, value); 10298#ifdef __CONFIG_WPS__ 10299 wps_disable_oob(); 10300#endif 10301 } 10302 ret_code = 0; 10303} 10304 10305static void 10306validate_wl_key(webs_t wp, char *value, struct variable *v, char *varname) 10307{ 10308 char *c=NULL; 10309 10310 assert(v); 10311 10312 ret_code = EINVAL; 10313 10314 switch (strlen(value)) { 10315 case 5: 10316 case 13: 10317 break; 10318 case 10: 10319 case 26: 10320 for (c = value; *c; c++) { 10321 if (!isxdigit((int) *c)) { 10322 websBufferWrite(wp, "Invalid <b>%s</b>: character %c is not a hexadecimal digit<br>", v->longname, *c); 10323 return; 10324 } 10325 } 10326 break; 10327 default: 10328 websBufferWrite(wp, "Invalid <b>%s</b>: must be 5 or 13 ASCII characters or 10 or 26 hexadecimal digits<br>", v->longname); 10329 return; 10330 } 10331 10332 if (varname) 10333 nvram_set(varname, value); 10334 else 10335 nvram_set(v->name, value); 10336 10337 ret_code = 0; 10338} 10339 10340static void 10341validate_wl_wep(webs_t wp, char *value, struct variable *v, char *varname) 10342{ 10343 char *auth_mode=NULL,*name=NULL, *auth=NULL; 10344 10345 assert(v); 10346 10347 ret_code = EINVAL; 10348 10349 if (!valid_choice(wp, value, v)){ 10350 websBufferWrite(wp, "Invalid wep string <b>%s</b>",value); 10351 return; 10352 } 10353 if (varname) 10354 name = varname; 10355 else 10356 name = v->name; 10357 10358 10359 /* WSC 2.0, auth may grayed by WPS enabled */ 10360 auth = websGetVar(wp, "wl_auth", ""); 10361 10362 auth_mode = websGetVar(wp, "wl_auth_mode", NULL); 10363 if (!strcmp(value, "enabled")) { 10364 if (!auth_mode || strcmp(auth_mode, "radius")) { 10365 char wl_key[] = "wl_keyXXX"; 10366 char wl_key_index[] = "wl_keyXXX"; 10367 10368 if (varname){ 10369 char index[5]; 10370 if (!get_index_string(v->prefix,varname,index,sizeof(index))) 10371 return; 10372 snprintf(wl_key_index, sizeof(wl_key_index),"wl%s_key",index); 10373 }else 10374 snprintf(wl_key_index, sizeof(wl_key_index),"wl_key"); 10375 10376 snprintf(wl_key, sizeof(wl_key), "%s%s",wl_key_index, nvram_safe_get(wl_key_index)); 10377 if (!strlen(nvram_safe_get(wl_key))) { 10378 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>Network Key %s</b><br>", 10379 v->longname, nvram_safe_get(wl_key_index)); 10380 if (nvram_match(name, "enabled")) { 10381 websBufferWrite(wp, "<b>%s</b> is <b>Disabled</b><br>", v->longname); 10382 nvram_set(name, "disabled"); 10383 } 10384 return; 10385 } 10386 } 10387 /* WSC 2.0, when wep is enabled, wps must disabled */ 10388 if (strcmp(websGetVar(wp, "wl_wps_mode", ""), "enabled") == 0) { 10389 char prefix[] = "wlXXXXXXXXXX_"; 10390 char wps_mode[64]; 10391 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 10392 websError(wp, 400, "unit number variable doesn't exist\n"); 10393 return; 10394 } 10395 snprintf(wps_mode, sizeof(wps_mode), "%swps_mode", prefix); 10396 nvram_set(wps_mode, "disabled"); 10397 } 10398 } 10399 else { 10400 if (!auth || !strcmp(auth, "shared") || 10401 ( auth_mode && !strcmp(auth_mode, "radius"))) { 10402 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>Network Authentication</b> is <b>%s</b><br>", auth_mode); 10403 return; 10404 } 10405 } 10406 10407 nvram_set(name, value); 10408 10409 ret_code = 0; 10410} 10411 10412static void 10413validate_wl_crypto(webs_t wp, char *value, struct variable *v, char *varname) 10414{ 10415 char *name; 10416 10417 assert(v); 10418 10419 ret_code = EINVAL; 10420 10421 if (!valid_choice(wp, value, v)){ 10422 websBufferWrite(wp, "Invalid crypto config string <b>%s</b>",value); 10423 return; 10424 } 10425 10426 if (varname) 10427 name = varname; 10428 else 10429 name = v->name; 10430 10431 if (nvram_match(name, value) != TRUE) { 10432 nvram_set(name, value); 10433#ifdef __CONFIG_WPS__ 10434 wps_disable_oob(); 10435#endif 10436 } 10437 ret_code = 0; 10438} 10439 10440#ifdef MFP 10441static void 10442validate_wl_mfp(webs_t wp, char *value, struct variable *v, char *varname) 10443{ 10444 char *ptr=NULL; 10445 10446 assert(v); 10447 10448 ptr =( (varname) ? varname : v->name ); 10449 10450 if ('0' <= value[0] && value[0] <= '2' && value[1] == '\0') 10451 nvram_set(ptr, value); 10452 else 10453 nvram_set(ptr, "0"); 10454 10455 ret_code =0; 10456} 10457#endif 10458 10459#ifdef __CONFIG_NAT__ 10460static void 10461validate_wan_ifname(webs_t wp, char *value, struct variable *v, char *varname) 10462{ 10463 char ifname[64], *next=NULL; 10464 10465 assert(v); 10466 10467 ret_code = EINVAL; 10468 foreach (ifname, nvram_safe_get("wan_ifnames"), next) 10469 if (!strcmp(ifname, value)) { 10470 nvram_set(v->name, value); 10471 ret_code = 0; 10472 return; 10473 } 10474 websBufferWrite(wp, "Invalid <b>%s</b>: must be one of <b>%s</b><br>", v->longname, nvram_safe_get("wan_ifnames")); 10475} 10476#endif /* __CONFIG_NAT__ */ 10477 10478static void 10479validate_wl_lazywds(webs_t wp, char *value, struct variable *v, char *varname) 10480{ 10481 assert(v); 10482 10483 ret_code = EINVAL; 10484 validate_choice(wp, value, v, varname); 10485} 10486 10487static void 10488validate_wl_wds_hwaddrs(webs_t wp, char *value, struct variable *v, char *varname) 10489{ 10490 assert(v); 10491 10492 ret_code = EINVAL; 10493 validate_list(wp, value, v, valid_hwaddr, varname); 10494} 10495 10496typedef enum { 10497 CALLFROM_DWDS, 10498 CALLFROM_PSTA 10499} callfrom_e; 10500 10501static void 10502validate_dpsta(webs_t wp, callfrom_e callfrom) 10503{ 10504 char *temp = NULL; 10505 int wl_unit = -1; 10506 int wl_subunit = -1; 10507 char *wl_dwds; 10508 char nv_param[NVRAM_MAX_PARAM_LEN]; 10509 char nv_interface[NVRAM_MAX_PARAM_LEN]; 10510 char os_interface[NVRAM_MAX_PARAM_LEN]; 10511 char *mode[2]; 10512 int dwds[2]; 10513 int psta[2]; 10514 int dpsta; 10515 10516 if ((temp = websGetVar(wp, "wl_unit", NULL))) { 10517 if (*temp) 10518 get_ifname_unit(temp, &wl_unit, &wl_subunit); 10519 10520 if (wl_subunit != -1) { 10521 websError(wp, 400, "psta can't be enabled for a virtual i/f\n"); 10522 ret_code = EINVAL; 10523 } 10524 } 10525 10526 if (wl_unit == -1) { 10527 websError(wp, 400, "Insufficient args\n"); 10528 ret_code = EINVAL; 10529 } 10530 10531 /* While enabling proxy sta,repeater or dwds modes on second wl interface 10532 * (dual band repeater) set nvram variable dpsta_ifnames to upstream 10533 * interfaces. 10534 */ 10535 10536 if (callfrom == CALLFROM_DWDS) { 10537 /* Called after setting DWDS from SSID page */ 10538 wl_dwds = websGetVar(wp, "wl_dwds", NULL); 10539 if (wl_dwds == NULL) { 10540 ret_code = EINVAL; 10541 } 10542 dwds[wl_unit] = atoi(wl_dwds); 10543 10544 sprintf(nv_param, "wl%d_dwds", 1 - wl_unit); 10545 dwds[1 - wl_unit] = atoi(nvram_safe_get(nv_param)); 10546 10547 mode[0] = nvram_safe_get("wl0_mode"); 10548 mode[1] = nvram_safe_get("wl1_mode"); 10549 } else { 10550 /* Called after setting PSTA/mode from radio page */ 10551 mode[wl_unit]= websGetVar(wp, "wl_mode", NULL); 10552 if (mode[wl_unit] == NULL) { 10553 ret_code = EINVAL; 10554 } 10555 10556 sprintf(nv_param, "wl%d_mode", 1 - wl_unit); 10557 mode[1-wl_unit] = nvram_safe_get(nv_param); 10558 10559 dwds[0] = atoi(nvram_safe_get("wl0_dwds")); 10560 dwds[1] = atoi(nvram_safe_get("wl1_dwds")); 10561 } 10562 10563 psta[0] = !strcmp(mode[0], "psta") || !strcmp(mode[0], "psr"); 10564 psta[1] = !strcmp(mode[1], "psta") || !strcmp(mode[1], "psr"); 10565 10566 dwds[0] = (dwds[0] && strcmp(mode[0], "ap")); 10567 dwds[1] = (dwds[1] && strcmp(mode[1], "ap")); 10568 10569 dpsta = ((dwds[0] || psta[0]) && (dwds[1] || psta[1])); 10570 10571 strcpy(nv_param, "dpsta_ifnames"); 10572 if (dpsta) { 10573 char if_list[NVRAM_MAX_VALUE_LEN]; 10574 int if_list_size = sizeof(if_list); 10575 10576 sprintf(nv_interface, "wl0"); 10577 nvifname_to_osifname(nv_interface, os_interface, sizeof(os_interface)); 10578 add_to_list(os_interface, if_list, if_list_size); 10579 10580 sprintf(nv_interface, "wl1"); 10581 nvifname_to_osifname(nv_interface, os_interface, sizeof(os_interface)); 10582 add_to_list(os_interface, if_list, if_list_size); 10583 10584 nvram_set(nv_param, if_list); 10585 } else { 10586 nvram_set(nv_param, ""); 10587 } 10588} 10589 10590static bool 10591validate_psta(webs_t wp, char *value, struct variable *v, char *varname) 10592{ 10593 char *temp = NULL; 10594 int wl_unit = -1; 10595 int wl_subunit = -1; 10596 char *wl_mode; 10597 char nv_param[NVRAM_MAX_PARAM_LEN]; 10598 char nv_interface[NVRAM_MAX_PARAM_LEN]; 10599 char os_interface[NVRAM_MAX_PARAM_LEN]; 10600 char interface_list[NVRAM_MAX_VALUE_LEN]; 10601 int interface_list_size = sizeof(interface_list); 10602 char lan_ifnames[NVRAM_MAX_PARAM_LEN] = "lan_ifnames"; 10603 char cap[WLC_IOCTL_SMLEN]; 10604 char caps[WLC_IOCTL_MEDLEN]; 10605 char *name = NULL; 10606 char *next = NULL; 10607 int max_no_vifs = 0; 10608 int i = 0; 10609 char tmp[20]; 10610 bool psta, psr, db_rpt; 10611 10612 if ((temp = websGetVar(wp, "wl_unit", NULL))) { 10613 if (*temp) { 10614 if (get_ifname_unit(temp, &wl_unit, &wl_subunit) != 0) { 10615 websError(wp, 400, "psta error getting wl_unit\n"); 10616 ret_code = EINVAL; 10617 return FALSE; 10618 } 10619 } 10620 10621 if (wl_subunit != -1) { 10622 websError(wp, 400, "psta can't be enabled for a virtual i/f\n"); 10623 ret_code = EINVAL; 10624 return FALSE; 10625 } 10626 } 10627 10628 if (wl_unit == -1) { 10629 websError(wp, 400, "Insufficient args\n"); 10630 ret_code = EINVAL; 10631 return FALSE; 10632 } 10633 10634 wl_mode = websGetVar(wp, "wl_mode", NULL); 10635 if (wl_mode == NULL) { 10636 ret_code = EINVAL; 10637 return FALSE; 10638 } 10639 10640 psta = !strcmp(wl_mode, "psta"); 10641 psr = !strcmp(wl_mode, "psr"); 10642 10643 sprintf(nv_param, "wl_mode"); 10644 temp = nvram_safe_get(nv_param); 10645 /* No change in mode */ 10646 if ((strcmp(temp, wl_mode) == 0) || (strlen(temp) == 0)) { 10647 ret_code = 0; 10648 return TRUE; 10649 } 10650 10651 /* Get the number of VIFS */ 10652 sprintf(nv_interface, "wl%d_ifname", wl_unit); 10653 name = nvram_safe_get(nv_interface); 10654 if (wl_iovar_get(name, "cap", (void *)caps, sizeof(caps))) { 10655 ret_code = EINVAL; 10656 return FALSE; 10657 } 10658 foreach(cap, caps, next) { 10659 if (!strcmp(cap, "mbss16")) 10660 max_no_vifs = 16; 10661 else if (!strcmp(cap, "mbss4")) 10662 max_no_vifs = 4; 10663 } 10664 10665 /* See if other interface also has psta or psr enabled */ 10666 sprintf(nv_param, "wl%d_mode", 1 - wl_unit); 10667 db_rpt = ((!strcmp(nvram_safe_get(nv_param), "psta") || 10668 !strcmp(nvram_safe_get(nv_param), "psr")) && (psta || psr)); 10669 10670 if (psta || psr) { 10671 temp = nvram_safe_get(lan_ifnames); 10672 if (interface_list_size <= strlen(temp)) { 10673 websError(wp, 400, "string too long\n"); 10674 ret_code = EINVAL; 10675 return FALSE; 10676 } 10677 strncpy(interface_list, temp, interface_list_size); 10678 10679 sprintf(nv_interface, "wl%d.1", wl_unit); 10680 10681 /* Set the wl mode for the virtual interface */ 10682 sprintf(nv_param, "wl%d.1_mode", wl_unit); 10683 if (psta) { 10684 /* For Proxy we need to remove our ap interface */ 10685 remove_from_list(nv_interface, interface_list, interface_list_size); 10686 nvram_set(lan_ifnames, interface_list); 10687 10688 /* Clear the ap mode */ 10689 nvram_set(nv_param, ""); 10690 } else { 10691 /* For Repeater we need to add our ap interface to the bridged lan */ 10692 add_to_list(nv_interface, interface_list, interface_list_size); 10693 nvram_set(lan_ifnames, interface_list); 10694 10695 /* Set the ap mode */ 10696 nvram_set(nv_param, "ap"); 10697 } 10698 10699 /* Turn off wlX_ure when proxy repeater modes are enabled */ 10700 nvram_set("wl_ure", "0"); 10701 10702 /* Security - We don't support any RADIUS-based authentication, 10703 * so we must force these options to OFF. 10704 */ 10705 /* turn off wlX_auth_mode and wlX.1_auth_mode */ 10706 sprintf(nv_param, "wl%d_auth_mode", wl_unit); 10707 nvram_set(nv_param, "none"); 10708 sprintf(nv_param, "wl%d.1_auth_mode", wl_unit); 10709 nvram_set(nv_param, "none"); 10710 /* Remove wpa and wpa2 from wlX_akm and wlX.1_akm */ 10711 /* wl_akm should be used here rather than wlX_akm, it's an 10712 * indexed param, so wl_akm represents wlX_akm 10713 */ 10714 sprintf(nv_param, "wl_akm"); 10715 temp = nvram_get(nv_param); 10716 if (temp && *temp) { 10717 memset(interface_list, 0, interface_list_size); 10718 /* NOTE: using "interface_list" to hold security nvram values */ 10719 strncpy(interface_list, temp, interface_list_size - 1); 10720 remove_from_list("wpa", interface_list, interface_list_size); 10721 remove_from_list("wpa2", interface_list, interface_list_size); 10722 nvram_set(nv_param, interface_list); 10723 } 10724 sprintf(nv_param, "wl%d.1_akm", wl_unit); 10725 temp = nvram_get(nv_param); 10726 if(temp && *temp) { 10727 memset(interface_list, 0, interface_list_size); 10728 /* NOTE: using "interface_list" to hold security nvram values */ 10729 strncpy(interface_list, temp, interface_list_size - 1); 10730 remove_from_list("wpa", interface_list, interface_list_size); 10731 remove_from_list("wpa2", interface_list, interface_list_size); 10732 nvram_set(nv_param, interface_list); 10733 } 10734 10735 sprintf(nv_param, "wl%d.1_bss_enabled", wl_unit); 10736 10737 if (psta) { 10738 nvram_set(nv_param, "0"); 10739 } else { 10740 nvram_set(nv_param, "1"); 10741 } 10742 10743 /* Make lan1_ifname lan1_ifnames empty so that br1 is not created 10744 * in psta/psr modes. 10745 */ 10746 nvram_set("lan1_ifname", ""); 10747 nvram_set("lan1_ifnames", ""); 10748 10749 /* Disable all VIFS wlX.2 onwards */ 10750 for (i = 2; i < max_no_vifs; i++) { 10751 sprintf(nv_param, "wl%d.%d_bss_enabled", wl_unit, i); 10752 nvram_set(nv_param, "0"); 10753 } 10754 } else { 10755 /* Now we need to remove the virtual i/f from the bridged lan interfaces */ 10756 temp = nvram_safe_get(lan_ifnames); 10757 if(interface_list_size <= strlen(temp)) { 10758 websError(wp, 400, "string too long\n"); 10759 ret_code = EINVAL; 10760 return FALSE; 10761 } 10762 strncpy(interface_list, temp, interface_list_size); 10763 sprintf(nv_interface, "wl%d.1", wl_unit); 10764 /* Virtual interfaces that appear in NVRAM lists are ALWAYS stored 10765 * as the NVRAM_FORM so we can add to list without translating. 10766 */ 10767 remove_from_list(nv_interface, interface_list, interface_list_size); 10768 /* Add our primary interface to lan_ifnames - default behavior */ 10769 sprintf(nv_interface, "wl%d", wl_unit); 10770 nvifname_to_osifname(nv_interface, os_interface, sizeof(os_interface)); 10771 add_to_list(os_interface, interface_list, interface_list_size); 10772 nvram_set(lan_ifnames, interface_list); 10773 10774 /* Make lan1_ifname, lan1_ifnames to default values */ 10775 nvram_set("lan1_ifname", "br1"); 10776 memset(interface_list, 0, interface_list_size); 10777 for (i = 1; i < max_no_vifs; i++) { 10778 sprintf(nv_interface, "wl%d.%d", wl_unit, i); 10779 add_to_list(nv_interface, interface_list, interface_list_size); 10780 nvram_set(strcat_r(nv_interface, "_hwaddr", tmp), ""); 10781 } 10782 nvram_set("lan1_ifnames", interface_list); 10783 } 10784 10785 return TRUE; 10786} 10787 10788 10789static void 10790validate_wl_mode(webs_t wp, char *value, struct variable *v, char *varname) 10791{ 10792 assert(v); 10793 10794 ret_code = EINVAL; 10795 10796 if (!valid_choice(wp, value, v)) 10797 return; 10798 10799 /* Configure the nvram for Proxy STA or Repeater modes */ 10800 if (!validate_psta(wp, value, v, varname)) 10801 return; 10802 10803 if (varname) 10804 nvram_set(varname, value); 10805 else 10806 nvram_set(v->name, value); 10807 10808 /* Based on DWDS/PSTA/PSR, turn on/off dpsta */ 10809 validate_dpsta(wp, CALLFROM_PSTA); 10810 10811 ret_code = 0; 10812} 10813 10814static void 10815validate_wl_dwds(webs_t wp, char *value, struct variable *v, char *varname) 10816{ 10817 assert(v); 10818 10819 ret_code = EINVAL; 10820 10821 if (!valid_choice(wp, value, v)) 10822 return; 10823 10824 if (varname) 10825 nvram_set(varname, value); 10826 else 10827 nvram_set(v->name, value); 10828 10829 /* Based on DWDS/PSTA/PSR, turn on/off dpsta */ 10830 validate_dpsta(wp, CALLFROM_DWDS); 10831 10832 ret_code = 0; 10833} 10834 10835static void 10836validate_wme_bool(webs_t wp, char *value, struct variable *v,char *varname) 10837{ 10838 char *wme=NULL; 10839 10840 assert(v); 10841 10842 ret_code = EINVAL; 10843 10844 /* return if wme is not enabled */ 10845 if (!(wme = websGetVar(wp, "wl_wme", NULL))){ 10846 ret_code = 0; 10847 return; 10848 } else if (!strcmp(wme, "off")){ 10849 ret_code = 0; 10850 return; 10851 } 10852 10853 validate_choice(wp, value, v, varname); 10854} 10855 10856#define CW_VALID(v) ((v) >= 0 && (v) <= 32767 && ((v) & ((v) + 1)) == 0) 10857#define AIFSN_VALID(a) ((a) >= 1 && (a) <= 15) 10858#define TXOP_VALID(t) ((t) >= 0 && (t) <= 65504 && ((t) % 32) == 0) 10859 10860static void 10861validate_wl_wme_params(webs_t wp, char *value, struct variable *v, char *varname) 10862{ 10863 int cwmin = 0, cwmax = 0, aifsn = 1, txop_b = 0, txop_ag = 0; 10864 char acm_str[100] = "off", dof_str[100] = "off"; 10865 char *s, *errmsg; 10866 char tmp[256]; 10867 10868 assert(v); 10869 10870 ret_code = EINVAL; 10871 10872 /* return if wme is not enabled */ 10873 if (!(s = websGetVar(wp, "wl_wme", NULL))) { 10874 ret_code = 0; 10875 return; 10876 } else if (!strcmp(s, "off")) { 10877 ret_code = 0; 10878 return; 10879 } 10880 10881 if (!value || atoi(value) != 5) { /* Number of INPUTs */ 10882 ret_code = 0; 10883 return; 10884 } 10885 10886 s = nvram_get(v->name); 10887 10888 if (s != NULL) 10889 sscanf(s, "%d %d %d %d %d %s %s", 10890 &cwmin, &cwmax, &aifsn, &txop_b, &txop_ag, acm_str, dof_str); 10891 10892 if ((value = websGetVar(wp, strcat_r(v->name, "0", tmp), NULL)) != NULL) 10893 cwmin = atoi(value); 10894 10895 if ((value = websGetVar(wp, strcat_r(v->name, "1", tmp), NULL)) != NULL) 10896 cwmax = atoi(value); 10897 10898 if (!CW_VALID(cwmin) || !CW_VALID(cwmax)) { 10899 errmsg = "CWmin and CWmax must be one less than a power of 2, up to 32767."; 10900 goto error; 10901 } 10902 10903 if (cwmax < cwmin) { 10904 errmsg = "CWmax must be greater than CWmin."; 10905 goto error; 10906 } 10907 10908 if ((value = websGetVar(wp, strcat_r(v->name, "2", tmp), NULL)) != NULL) 10909 aifsn = atoi(value); 10910 10911 if (!AIFSN_VALID(aifsn)) { 10912 errmsg = "AIFSN must be in the range 1 to 15."; 10913 goto error; 10914 } 10915 10916 if ((value = websGetVar(wp, strcat_r(v->name, "3", tmp), NULL)) != NULL) 10917 txop_b = atoi(value); 10918 10919 if ((value = websGetVar(wp, strcat_r(v->name, "4", tmp), NULL)) != NULL) 10920 txop_ag = atoi(value); 10921 10922 if (!TXOP_VALID(txop_b) || !TXOP_VALID(txop_ag)) { 10923 errmsg = "TXOP(b) and TXOP(a/g) must be multiples of 32 in the range 0 to 65504."; 10924 goto error; 10925 } 10926 10927 if ((value = websGetVar(wp, strcat_r(v->name, "5", tmp), NULL)) != NULL) 10928 if (!strcmp(value, "off") || !strcmp(value, "on")) { 10929 strncpy(acm_str, value, sizeof(acm_str)-1); 10930 acm_str[sizeof(acm_str)-1] = '\0'; 10931 } 10932 10933 if ((value = websGetVar(wp, strcat_r(v->name, "6", tmp), NULL)) != NULL) 10934 if (!strcmp(value, "off") || !strcmp(value, "on")) { 10935 strncpy(dof_str, value, sizeof(dof_str)-1); 10936 dof_str[sizeof(dof_str)-1] = '\0'; 10937 } 10938 10939 sprintf(tmp, "%d %d %d %d %d %s %s", 10940 cwmin, cwmax, aifsn, txop_b, txop_ag, acm_str, dof_str); 10941 10942 nvram_set(v->name, tmp); 10943 10944 ret_code = 0; 10945 10946 return; 10947 10948error: 10949 websBufferWrite(wp, "Error setting WME AC value: <b>"); 10950 websBufferWrite(wp, errmsg); 10951 websBufferWrite(wp, "<b><br>"); 10952} 10953 10954uint8 prio2ac[NUMPRIO] = { 10955 AC_BE, /* 0 BE Best Effort */ 10956 AC_BK, /* 1 BK Background */ 10957 AC_BK, /* 2 -- Background */ 10958 AC_BE, /* 3 EE Best Effort */ 10959 AC_VI, /* 4 CL Video */ 10960 AC_VI, /* 5 VI Video */ 10961 AC_VO, /* 6 VO Voice */ 10962 AC_VO /* 7 NC Voice */ 10963}; 10964 10965static void 10966wl_set_ampdu_rerty_limit(char *acname, int srl, int sfbl) 10967{ 10968 int ac_type = -1; 10969 int retry[NUMPRIO], rr_retry[NUMPRIO], tid, len; 10970 char tmp[256], *s, nvram[256], prefix[] = "wlXXXXXXXXXX_"; 10971 10972 if (acname == NULL || 10973 (len = strlen(acname)) < 2) 10974 return; 10975 10976 if (acname[len-2] == 'b') { 10977 if (acname[len-1] == 'e') 10978 ac_type = AC_BE; 10979 else if (acname[len-1] == 'k') 10980 ac_type = AC_BK; 10981 } 10982 else if (acname[len-2] == 'v') { 10983 if (acname[len-1] == 'i') 10984 ac_type = AC_VI; 10985 else if (acname[len-1] == 'o') 10986 ac_type = AC_VO; 10987 } 10988 10989 if (ac_type == -1) 10990 return; 10991 10992 /* 10993 * convert ac_type to tid index, set srl to ampdu_rtylimit_tid, 10994 * set sfbl to ampdu_rr_rtylimit_tid. 10995 */ 10996 sprintf(prefix,"wl%s_", nvram_get("wl_unit")); 10997 s = nvram_get(strcat_r(prefix, "ampdu_rtylimit_tid", nvram)); 10998 if (!s) { 10999 s = nvram_default_get(strcat_r(prefix, "ampdu_rtylimit_tid", nvram)); 11000 } 11001 if (s != NULL) 11002 sscanf(s, "%d %d %d %d %d %d %d %d", 11003 &retry[0], &retry[1], &retry[2], &retry[3], 11004 &retry[4], &retry[5], &retry[6], &retry[7]); 11005 11006 s = nvram_get(strcat_r(prefix, "ampdu_rr_rtylimit_tid", nvram)); 11007 if (!s) { 11008 s = nvram_default_get(strcat_r(prefix, "ampdu_rtylimit_tid", nvram)); 11009 } 11010 if (s != NULL) 11011 sscanf(s, "%d %d %d %d %d %d %d %d", 11012 &rr_retry[0], &rr_retry[1], &rr_retry[2], &rr_retry[3], 11013 &rr_retry[4], &rr_retry[5], &rr_retry[6], &rr_retry[7]); 11014 11015 for (tid = 0; tid < NUMPRIO; tid++) { 11016 if (ac_type == prio2ac[tid]) { 11017 /* over-write retry[tid] and rr_retry[tid] value */ 11018 retry[tid] = srl; 11019 rr_retry[tid] = sfbl; 11020 } 11021 } 11022 11023 sprintf(tmp, "%d %d %d %d %d %d %d %d", 11024 retry[0], retry[1], retry[2], retry[3], retry[4], 11025 retry[5], retry[6], retry[7]); 11026 11027 nvram_set(strcat_r(prefix, "ampdu_rtylimit_tid", nvram), tmp); 11028 11029 sprintf(tmp, "%d %d %d %d %d %d %d %d", 11030 rr_retry[0], rr_retry[1], rr_retry[2], rr_retry[3], 11031 rr_retry[4], rr_retry[5], rr_retry[6], rr_retry[7]); 11032 nvram_set(strcat_r(prefix, "ampdu_rr_rtylimit_tid", nvram), tmp); 11033 11034 return; 11035} 11036 11037#define SRL_VALID(v) (((v) > 0) && ((v) <= 15)) 11038#define SFBL_VALID(v) (((v) > 0) && ((v) <= 15)) 11039#define LRL_VALID(v) (((v) > 0) && ((v) <= 15)) 11040#define LFBL_VALID(v) (((v) > 0) && ((v) <= 15)) 11041 11042static void 11043validate_wl_wme_tx_params(webs_t wp, char *value, struct variable *v, char *varname) 11044{ 11045 int srl = 0, sfbl = 0, lrl = 0, lfbl = 0, max_rate = 0, nmode = 0; 11046 char *s, *errmsg; 11047 char tmp[256]; 11048 11049 assert(v); 11050 11051 ret_code = EINVAL; 11052 11053 /* return if wme is not enabled */ 11054 if (!(s = websGetVar(wp, "wl_wme", NULL))) { 11055 ret_code = 0; 11056 return; 11057 } else if (!strcmp(s, "off")) { 11058 ret_code = 0; 11059 return; 11060 } 11061 11062 if (!value || atoi(value) != 5) { /* Number of INPUTs */ 11063 ret_code = 0; 11064 return; 11065 } 11066 11067 s = nvram_get(v->name); 11068 11069 if (s != NULL) 11070 sscanf(s, "%d %d %d %d %d", &srl, &sfbl, &lrl, &lfbl, &max_rate); 11071 11072 if ((value = websGetVar(wp, strcat_r(v->name, "0", tmp), NULL)) != NULL) 11073 srl = atoi(value); 11074 11075 if (!SRL_VALID(srl)) { 11076 errmsg = "Short Retry Limit must be in the range 1 to 15"; 11077 goto error; 11078 } 11079 11080 if ((value = websGetVar(wp, strcat_r(v->name, "1", tmp), NULL)) != NULL) 11081 sfbl = atoi(value); 11082 11083 if (!SFBL_VALID(sfbl)) { 11084 errmsg = "Short Fallback Limit must be in the range 1 to 15"; 11085 goto error; 11086 } 11087 11088 if ((value = websGetVar(wp, strcat_r(v->name, "2", tmp), NULL)) != NULL) 11089 lrl = atoi(value); 11090 11091 if (!LRL_VALID(lrl)) { 11092 errmsg = "Long Retry Limit must be in the range 1 to 15"; 11093 goto error; 11094 } 11095 11096 if ((value = websGetVar(wp, strcat_r(v->name, "3", tmp), NULL)) != NULL) 11097 lfbl = atoi(value); 11098 11099 if (!LFBL_VALID(lfbl)) { 11100 errmsg = "Long Fallback Limit must be in the range 1 to 15"; 11101 goto error; 11102 } 11103 11104 if ((value = websGetVar(wp, strcat_r(v->name, "4", tmp), NULL)) != NULL) 11105 max_rate = atoi(value); 11106 11107 s = nvram_get("wl_nmode"); 11108 if (s != NULL) 11109 nmode = atoi(s); 11110 11111 sprintf(tmp, "%d %d %d %d %d", 11112 srl, sfbl, lrl, lfbl, max_rate); 11113 11114 nvram_set(v->name, tmp); 11115 11116 wl_set_ampdu_rerty_limit(v->name, srl, sfbl); 11117 11118 ret_code = 0; 11119 11120 return; 11121 11122error: 11123 websBufferWrite(wp, "Error setting WME TX parameters value: <b>"); 11124 websBufferWrite(wp, errmsg); 11125 websBufferWrite(wp, "<b><br>"); 11126} 11127 11128static void 11129validate_dfs_prefchan(webs_t wp, char *value, struct variable *v, char *varname) 11130{ 11131 char tmp[256]; 11132 char pref0[32], pref1[32], pref2[32], pref3[32], pref4[32], pref5[32]; 11133 11134 if ((value = websGetVar(wp, strcat_r(v->name, "0", tmp), NULL)) != NULL) 11135 sprintf(pref0, "%s", !strcmp("N/A", value) ? "0" : value); 11136 else 11137 sprintf(pref0, "%s", "0"); 11138 if ((value = websGetVar(wp, strcat_r(v->name, "1", tmp), NULL)) != NULL) 11139 sprintf(pref1, "%s", !strcmp("N/A", value) ? "0" : value); 11140 else 11141 sprintf(pref1, "%s", "0"); 11142 if ((value = websGetVar(wp, strcat_r(v->name, "2", tmp), NULL)) != NULL) 11143 sprintf(pref2, "%s", !strcmp("N/A", value) ? "0" : value); 11144 else 11145 sprintf(pref2, "%s", "0"); 11146 if ((value = websGetVar(wp, strcat_r(v->name, "3", tmp), NULL)) != NULL) 11147 sprintf(pref3, "%s", !strcmp("N/A", value) ? "0" : value); 11148 else 11149 sprintf(pref3, "%s", "0"); 11150 if ((value = websGetVar(wp, strcat_r(v->name, "4", tmp), NULL)) != NULL) 11151 sprintf(pref4, "%s", !strcmp("N/A", value) ? "0" : value); 11152 else 11153 sprintf(pref4, "%s", "0"); 11154 if ((value = websGetVar(wp, strcat_r(v->name, "5", tmp), NULL)) != NULL) 11155 sprintf(pref5, "%s", !strcmp("N/A", value) ? "0" : value); 11156 else 11157 sprintf(pref5, "%s", "0"); 11158 11159 sprintf(tmp, "%s %s %s %s %s %s", pref0, pref1, pref2, pref3, pref4, pref5); 11160 11161 nvram_set(v->name, tmp); 11162 ret_code = 0; 11163 return; 11164} 11165 11166/* Hook to write wl_* default set through to wl%d_* variable set */ 11167static void 11168wl_unit(webs_t wp, char *value, struct variable *v, char *varname) 11169{ 11170 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 11171 char *wl_bssid = NULL; 11172 char vif[64]; 11173 11174 assert(v); 11175 11176 ret_code = 0; 11177 11178 if (!value) return; 11179 11180 11181 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))){ 11182 snprintf(vif,sizeof(vif),"%s.%s",value,wl_bssid); 11183 value = vif; 11184 } 11185 11186 11187 11188 /* The unit numbers are built dynamically so what is 11189 present is assumed to be running */ 11190 11191 snprintf(prefix,sizeof(prefix),"wl%s_",value); 11192 11193 /* Write through to selected variable set 11194 * If the VIF_IGNORE flag is set, we still need to write if the interface is the 11195 * physical device. 11196 */ 11197 11198 for (; v >= variables && !strncmp(v->name, "wl_", 3); v--){ 11199 if (( v->ezc_flags & WEB_IGNORE) || ((v->ezc_flags & VIF_IGNORE) && (prefix[3] == '.'))) 11200 continue; 11201 nvram_set(strcat_r(prefix, &v->name[3], tmp), nvram_safe_get(v->name)); 11202 } 11203} 11204 11205#ifdef __CONFIG_NAT__ 11206static void 11207wan_primary(webs_t wp) 11208{ 11209 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 11210 int i; 11211 11212 for (i = 0; i < MAX_NVPARSE; i ++) { 11213 /* skip non-exist and disabled connection */ 11214 WAN_PREFIX(i, prefix); 11215 if (!nvram_get(strcat_r(prefix, "unit", tmp))|| 11216 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) 11217 continue; 11218 /* make connection <i> primary */ 11219 nvram_set(strcat_r(prefix, "primary", tmp), "1"); 11220 /* notify the user */ 11221 websBufferWrite(wp, "<br><b>%s</b> is set to primary.", 11222 wan_name(i, prefix, tmp, sizeof(tmp))); 11223 break; 11224 } 11225} 11226 11227/* Hook to write wan_* default set through to wan%d_* variable set */ 11228static void 11229wan_unit(webs_t wp, char *value, struct variable *v, char *varname) 11230{ 11231 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 11232 char pppx[] = "pppXXXXXXXXXXX"; 11233 int unit, i; 11234 char *wan_ifname=NULL; 11235 int wan_disabled = 0; 11236 int wan_prim = 0; 11237 int wan_wildcard = 0; 11238 char *wan_pppoe_service=NULL; 11239 char *wan_pppoe_ac=NULL; 11240 char wan_tmp[NVRAM_BUFSIZE]; 11241 int wildcard; 11242 char *pppoe_service=NULL; 11243 char *pppoe_ac=NULL; 11244 unsigned char ea[ETHER_ADDR_LEN], wan_ea[ETHER_ADDR_LEN]; 11245 11246 assert(v); 11247 ret_code = 0; 11248 11249 /* Do not write through if no connections are present */ 11250 if ((unit = atoi(value)) < 0) 11251 return; 11252 11253 /* override wan_pppoe_ifname */ 11254 if (nvram_match("wan_proto", "pppoe")) { 11255 snprintf(pppx, sizeof(pppx), "ppp%d", unit); 11256 nvram_set("wan_pppoe_ifname", pppx); 11257 } 11258 /* 11259 * Need to make sure this connection can co-exist with others. 11260 * Disable others if it can't (assuming this is the wanted one). 11261 * Disabled connection is for sure no problem to co-exist with 11262 * other connections. 11263 */ 11264 if (nvram_match("wan_proto", "disabled")) { 11265 /* Non primary always go with disabled connection. */ 11266 nvram_set("wan_primary", "0"); 11267 wan_disabled = 1; 11268 } 11269 /* 11270 * PPPoE connection is for sure no problem to co-exist with 11271 * other PPPoE connections even when they share the same 11272 * ethernet interface, but we need to make sure certain 11273 * PPPoE parameters are reasonablely different from eatch other 11274 * if they share the same ethernet interface. 11275 */ 11276 else if (nvram_match("wan_proto", "pppoe")) { 11277 /* must disable others if this connection is wildcard (any service any ac) */ 11278 wan_pppoe_service = nvram_get("wan_pppoe_service"); 11279 wan_pppoe_ac = nvram_get("wan_pppoe_ac"); 11280 wan_wildcard = (wan_pppoe_service == NULL || *wan_pppoe_service == 0) && 11281 (wan_pppoe_ac == NULL || *wan_pppoe_ac == 0); 11282 wan_ifname = nvram_safe_get("wan_ifname"); 11283 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 11284 /* check all PPPoE connections that share the same interface */ 11285 for (i = 0; i < MAX_NVPARSE; i ++) { 11286 /* skip the current connection */ 11287 if (i == unit) 11288 continue; 11289 /* skip non-exist and connection that does not share the same i/f */ 11290 WAN_PREFIX(i, prefix); 11291 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 11292 nvram_match(strcat_r(prefix, "proto", tmp), "disabled") || 11293 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 11294 continue; 11295 /* PPPoE can share the same i/f, but none can be wildcard */ 11296 if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { 11297 if (wan_wildcard) { 11298 /* disable connection <i> */ 11299 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 11300 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 11301 /* notify the user */ 11302 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because both " 11303 "<b>PPPoE Service Name</b> and <b>PPPoE Access Concentrator</b> " 11304 "in <b>%s</b> are empty.", 11305 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 11306 } 11307 else { 11308 pppoe_service = nvram_get(strcat_r(prefix, "pppoe_service", tmp)); 11309 pppoe_ac = nvram_get(strcat_r(prefix, "pppoe_ac", tmp)); 11310 wildcard = (pppoe_service == NULL || *pppoe_service == 0) && 11311 (pppoe_ac == NULL || *pppoe_ac == 0); 11312 /* allow connection <i> if certain pppoe parameters are not all same */ 11313 if (!wildcard && 11314 (nvram_invmatch(strcat_r(prefix, "pppoe_service", tmp), nvram_safe_get("wan_pppoe_service")) || 11315 nvram_invmatch(strcat_r(prefix, "pppoe_ac", tmp), nvram_safe_get("wan_pppoe_ac")))) 11316 continue; 11317 /* disable connection <i> */ 11318 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 11319 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 11320 /* notify the user */ 11321 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because both its " 11322 "<b>PPPoE Service Name</b> and <b>PPPoE Access Concentrator</b> " 11323 "are empty.", 11324 wan_name(i, prefix, tmp, sizeof(tmp))); 11325 } 11326 } 11327 /* other types can't (?) share the same i/f with PPPoE */ 11328 else { 11329 /* disable connection <i> */ 11330 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 11331 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 11332 /* notify the user */ 11333 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because it can't " 11334 "share the same interface with <b>%s</b>.", 11335 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 11336 } 11337 } 11338 } 11339 /* 11340 * All other types (now DHCP, Static) can't co-exist with 11341 * other connections if they use the same ethernet i/f. 11342 */ 11343 else { 11344 wan_ifname = nvram_safe_get("wan_ifname"); 11345 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 11346 /* check all connections that share the same interface */ 11347 for (i = 0; i < MAX_NVPARSE; i ++) { 11348 /* skip the current connection */ 11349 if (i == unit) 11350 continue; 11351 /* check if connection <i> exists and share the same i/f*/ 11352 WAN_PREFIX(i, prefix); 11353 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 11354 nvram_match(strcat_r(prefix, "proto", tmp), "disabled") || 11355 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 11356 continue; 11357 /* disable connection <i> */ 11358 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 11359 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 11360 /* notify the user */ 11361 websBufferWrite(wp, "<br><b>%s</b> is disabled because it can't share " 11362 "the ethernet interface with <b>%s</b>.", 11363 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 11364 } 11365 } 11366 11367 /* 11368 * Check if MAC address has been changed. Need to sync it to all connections 11369 * that share the same i/f if it is changed. 11370 */ 11371 WAN_PREFIX(unit, prefix); 11372 ether_atoe(nvram_safe_get("wan_hwaddr"), wan_ea); 11373 ether_atoe(nvram_safe_get(strcat_r(prefix, "hwaddr", tmp)), ea); 11374 if (memcmp(ea, wan_ea, ETHER_ADDR_LEN)) { 11375 wan_ifname = nvram_safe_get("wan_ifname"); 11376 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 11377 /* sync all connections that share the same interface */ 11378 for (i = 0; i < MAX_NVPARSE; i ++) { 11379 /* skip the current connection */ 11380 if (i == unit) 11381 continue; 11382 /* check if connection <i> exists and share the same i/f*/ 11383 WAN_PREFIX(i, prefix); 11384 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 11385 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 11386 continue; 11387 /* check if connection <i>'s hardware address is different */ 11388 if (ether_atoe(nvram_safe_get(strcat_r(prefix, "hwaddr", tmp)), ea) && 11389 !memcmp(ea, wan_ea, ETHER_ADDR_LEN)) 11390 continue; 11391 /* change connection <i>'s hardware address */ 11392 nvram_set(strcat_r(prefix, "hwaddr", tmp), nvram_safe_get("wan_hwaddr")); 11393 /* notify the user */ 11394 websBufferWrite(wp, "<br><b>MAC Address</b> in <b>%s</b> is changed to " 11395 "<b>%s</b> because it shares the ethernet interface with <b>%s</b>.", 11396 wan_name(i, prefix, tmp, sizeof(tmp)), nvram_safe_get("wan_hwaddr"), 11397 wan_tmp); 11398 } 11399 } 11400 11401 /* Set prefix */ 11402 WAN_PREFIX(unit, prefix); 11403 11404 /* Write through to selected variable set */ 11405 for (; v >= variables && !strncmp(v->name, "wan_", 4); v--){ 11406 if (v->ezc_flags & WEB_IGNORE) 11407 continue; 11408 nvram_set(strcat_r(prefix, &v->name[4], tmp), nvram_safe_get(v->name)); 11409 } 11410 11411 /* 11412 * There must be one and only one primary connection among all 11413 * enabled connections so that traffic can be routed by default 11414 * through the primary connection unless they are targetted to 11415 * a specific connection by means of static routes. (Primary ~= 11416 * Default Gateway). 11417 */ 11418 /* the current connection is primary, set others to non-primary */ 11419 if (!wan_disabled && nvram_match(strcat_r(prefix, "primary", tmp), "1")) { 11420 /* set other connections to non-primary */ 11421 for (i = 0; i < MAX_NVPARSE; i ++) { 11422 /* skip the current connection */ 11423 if (i == unit) 11424 continue; 11425 /* skip non-exist and disabled connection */ 11426 WAN_PREFIX(i, prefix); 11427 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 11428 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) 11429 continue; 11430 /* skip non-primary connection */ 11431 if (nvram_invmatch(strcat_r(prefix, "primary", tmp), "1")) 11432 continue; 11433 /* force primary to non-primary */ 11434 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 11435 /* notify the user */ 11436 websBufferWrite(wp, "<br><b>%s</b> is set to non-primary.", 11437 wan_name(i, prefix, tmp, sizeof(tmp))); 11438 } 11439 wan_prim = 1; 11440 } 11441 /* the current connection is not parimary, check if there is any primary */ 11442 else { 11443 /* check other connections to see if there is any primary */ 11444 for (i = 0; i < MAX_NVPARSE; i ++) { 11445 /* skip the current connection */ 11446 if (i == unit) 11447 continue; 11448 /* primary connection exists, honor it */ 11449 WAN_PREFIX(i, prefix); 11450 if (nvram_match(strcat_r(prefix, "primary", tmp), "1")) { 11451 wan_prim = 1; 11452 break; 11453 } 11454 } 11455 } 11456 /* no one is primary, pick the first enabled one as primary */ 11457 if (!wan_prim) 11458 wan_primary(wp); 11459} 11460#endif /* __CONFIG_NAT__ */ 11461 11462/* This is the monster V-block 11463 * 11464 * It controls the following functions 11465 * 11466 * Configuration variables are validated and saved in NVRAM 11467 * Variables saved by NVRAM save/restore routine 11468 * Method in which the variables are to be validates 11469 * SES handling 11470 * 11471 * The control flags: 11472 * EZC_FLAGS_READ,EZC_FLAGS_WRITE :Ses read/write flags 11473 * NVRAM_ENCRYPT: Encrypt variable prior to downloading NVRAM variable to file 11474 * NVRAM_MI: Multi instance NVRAM variable eg wlXX,wanXX 11475 * NVRAM_VLAN_MULTI: Special flag to handle oddball vlanXXname and its cousins 11476 * NVRAM_MP: Variable can be single & multi instance eg lan_ifname, lanX_ifname 11477 * NVRAM_IGNORE: Dont save/restore this var. 11478 * WEB_IGNORE: Don't validate or process this var during web validation. 11479 * VIF_IGNORE: Don't create from wlx.y interface. Shared within one phy. devive. 11480 * 11481 * 11482 * Below is the definition of the structure 11483 *struct variable { 11484 * char *name; <- name of variable 11485 * char *longname; <- display name 11486 * char *prefix; <- prefix for processing the multi-instance versions 11487 * void (*validate)(); <- Validation routine 11488 * char **argv; <- Optional argument vector for validation routine 11489 * int nullok; <- value can be NULL 11490 * int ezc_flags; <- control flags 11491 * }; 11492 * 11493 * IMPORTANT: 11494 * ========= 11495 * 11496 * The variables in tne table below determine if they will be saved/restored 11497 * by the UI NVRAM save/restore feature 11498 * 11499 * If an NVRAM variable is not present in this list it will 11500 * not be processed and thus will not be saved or restored. 11501 * 11502*/ 11503 11504/* 11505 * Variables are set in order (put dependent variables later). Set 11506 * nullok to TRUE to ignore zero-length values of the variable itself. 11507 * For more complicated validation that cannot be done in one pass or 11508 * depends on additional form components or can throw an error in a 11509 * unique painful way, write your own validation routine and assign it 11510 * to a hidden variable (e.g. filter_ip). 11511 * 11512 * EZC_FLAGS_READ : implies the variable will be returned for ezconfig read request 11513 * EZC_FLAGS_WRITE : allows the variable to be modified by the ezconfig tool 11514 * 11515 * The variables marked with EZConfig have to maintain backward compatibility. 11516 * If they cannot then the ezc_version has to be bumped up 11517 */ 11518static char wl_prefix[]="wl"; 11519#ifdef __CONFIG_NAT__ 11520static char wan_prefix[]="wan"; 11521#endif 11522static char lan_prefix[]="lan"; 11523static char dhcp_prefix[]="dhcp"; 11524static char vlan_prefix[]="vlan"; 11525 11526static struct hsearch_data vtab; 11527 11528static char *wan_proto_argv[] = { 11529 "dhcp", 11530 "static", 11531 "pppoe", 11532"disabled" 11533}; 11534 11535struct variable variables[] = { 11536#ifdef __CONFIG_WAPI_IAS__ 11537 /* AS setting */ 11538 { "as_mode", "Authentication Server mode",NULL, NULL, NULL, TRUE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11539#endif 11540 /* basic settings */ 11541 { "http_username", "Router Username",NULL, validate_name, ARGV("0", "63"), TRUE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11542 { "http_passwd", "Router Password",NULL, validate_name, ARGV("0", "63"), TRUE, NVRAM_ENCRYPT | EZC_FLAGS_WRITE }, 11543 { "http_wanport", "Router WAN Port",NULL, validate_range, ARGV("0", "65535"), TRUE, 0 }, 11544 { "http_lanport", "HTTP daemon lanport",NULL, NULL, NULL, TRUE, 0 }, 11545 { "router_disable", "Router Mode",NULL, validate_router_disable, ARGV("0", "1"), FALSE, 0 }, 11546 { "fw_disable", "Firewall",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11547 { "time_zone", "Time Zone",NULL, validate_choice, ARGV("PST8PDT", "MST7MDT", "CST6CDT", "EST5EDT"), FALSE }, 11548 { "upnp_enable", "UPnP",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11549 { "ezc_enable", "EZConfig",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE}, 11550 { "ntp_server", "NTP Servers",NULL, validate_ipaddrs, NULL, TRUE, 0 }, 11551 { "log_level", "Connection Logging",NULL, validate_range, ARGV("0", "3"), FALSE, 0 }, 11552 { "log_ipaddr", "Log LAN IP Address",NULL, validate_ipaddr, ARGV("lan_ipaddr", "lan_netmask"), TRUE, 0 }, 11553 { "log_ram_enable", "Syslog in RAM",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11554#ifdef BCMQOS 11555 { "qos_enable", "Qos enable",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11556 { "qos_ack", "Prioritize ACK",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11557 { "qos_icmp", "Prioritize ICMP",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11558 { "qos_default", "Default Outbound Class", NULL, validate_choice, ARGV("0", "1", "2", "3", "4"), FALSE, 0}, 11559 { "qos_obw", "Outbound BW", NULL, validate_range, ARGV("0", "999999"), TRUE, 0 }, 11560 { "qos_ibw", "Inbound BW", NULL, validate_range, ARGV("0", "999999"), TRUE, 0 }, 11561 { "qos_orates", "Outbound BW", NULL, valid_qos_var, NULL, TRUE, 0 }, 11562 { "qos_irates", "Inbound BW", NULL, valid_qos_var, NULL, TRUE, 0 }, 11563 { "qos_orules", "Qos rules", NULL, valid_qos_var, NULL, TRUE, 0 }, 11564#endif /* BCMQOS */ 11565 { "igmp_enable" , "Enable IGMP proxy", NULL, validate_choice, ARGV("1", "0"), FALSE, 0}, 11566 { "bsd_role" , "BandSteer Daemon State", NULL, validate_choice, ARGV("3", "2", "1", "0"), FALSE, 0}, 11567 { "bsd_helper", "BandSteer Helper IP Address", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11568 { "bsd_hport", "BandSteer Helper Port", wl_prefix, validate_range, ARGV("0", "65535"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11569 { "bsd_primary", "BandSteer Primary IP Address", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11570 { "bsd_pport", "BandSteer Primary Port", wl_prefix, validate_range, ARGV("0", "65535"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11571 { "trf_mgmt_port", "Traffic Port", NULL, validate_trf_mgmt_port, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11572 /* LAN settings */ 11573 { "lan_ifname" "LAN Interface Name", lan_prefix, NULL, NULL, FALSE, NVRAM_MI|NVRAM_IGNORE }, 11574 { "lan_hwaddr", "LAN MAC Address", lan_prefix, validate_hwaddr, NULL, TRUE, NVRAM_MI|NVRAM_IGNORE }, 11575 { "lan_dhcp", "DHCP Client", lan_prefix, validate_choice, ARGV("1", "0"), FALSE, NVRAM_MI | NVRAM_MP }, 11576 { "lan_ipaddr", "IP Address", lan_prefix, validate_lan_ipaddr, NULL, FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11577 { "lan_netmask", "Subnet Mask", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11578 { "lan_gateway", "Gateway Address", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11579 { "lan_proto", "DHCP Server", lan_prefix, validate_choice, ARGV("dhcp", "static"), FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11580 { "dhcp_start", "DHCP Server LAN IP Address Range", dhcp_prefix, validate_dhcp, NULL, FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11581 { "dhcp_end", "DHCP Server LAN IP End Address", dhcp_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11582 { "dhcp_wins", "DHCP WINS domain", dhcp_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP}, 11583 { "dhcp_domain", "DHCP domain", dhcp_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 11584 { "lan_lease", "DHCP Server Lease Time", lan_prefix, validate_range, ARGV("1", "604800"), FALSE, NVRAM_MI | NVRAM_MP |EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11585 { "lan_stp", "Spanning Tree Protocol", lan_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | NVRAM_MP| EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11586 { "lan_route", "Static Routes", lan_prefix, validate_lan_route, NULL, FALSE, NVRAM_MI | NVRAM_MP }, 11587#ifdef __CONFIG_EMF__ 11588 { "emf_enable", "Efficient Multicast Forwarding", NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11589 { "emf_entry", "Static Multicast Forwarding entries", NULL, validate_emf_entry, NULL, FALSE, NVRAM_MI | NVRAM_MP }, 11590 { "emf_uffp_entry", "Unregistered Frames Forwarding Ports", NULL, validate_emf_uffp_entry, NULL, FALSE, NVRAM_MI | NVRAM_MP }, 11591 { "emf_rtport_entry", "Multicast Router / IGMP Forwarding Ports", NULL, validate_emf_rtport_entry, NULL, FALSE, NVRAM_MI | NVRAM_MP }, 11592#endif /* __CONFIG_EMF__ */ 11593 { "lan_wins", "Lan WINS", lan_prefix, NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP}, 11594 { "lan_domain", "Lan Domain", lan_prefix,NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11595 { "lan_route","LAN route", lan_prefix, NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 11596 { "lan_guest_ifname","Guest LAN 1", lan_prefix, validate_guest_lan_ifname, ARGV("1"), FALSE, NVRAM_MI| NVRAM_IGNORE}, 11597 /*VLAN config vars. These are multi-instance Used by NVRAM save/restore for the moment */ 11598 { "vlanhwname", "VLAN HW name", vlan_prefix, NULL, NULL, TRUE, NVRAM_VLAN_MULTI}, 11599 { "vlanports", "VLAN Ports", vlan_prefix, NULL, NULL, TRUE, NVRAM_VLAN_MULTI}, 11600/* 11601*/ 11602#ifdef __CONFIG_IPV6__ 11603 { "lan_ipv6_prefix", "IPv6 LAN Network Prefix", lan_prefix, validate_ipv6prefix, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 11604 { "lan_ipv6_dns", "IPv6 Domain Name Server IP", lan_prefix, validate_ipv6addr, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 11605 { "lan_ipv6_mode", "IPv6 Mode", lan_prefix, validate_ipv6mode, ARGV("0", "3"), TRUE, NVRAM_MI | NVRAM_MP }, 11606 { "lan_ipv6_6to4id", "IPv6 6to4 Subnet ID", lan_prefix, validate_range, ARGV("0", "65535"), TRUE, NVRAM_MI | NVRAM_MP }, 11607 /* Note the wan_ipv6_prefix is per WAN interface configuration */ 11608 { "wan_ipv6_prefix", "IPv6 WAN Network Prefix", wan_prefix, validate_ipv6prefix, NULL, TRUE, NVRAM_MI }, 11609#endif /* __CONFIG_IPV6__ */ 11610/* 11611*/ 11612#ifdef __CONFIG_NAT__ 11613 /* ALL wan_XXXX variables below till wan_unit variable are per-interface */ 11614 { "wan_desc", "Description", wan_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11615 { "wan_proto", "Protocol", wan_prefix, validate_choice, wan_proto_argv , FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11616 { "wan_hostname", "Host Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI |EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11617 { "wan_domain", "Domain Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11618 { "wan_ifname", "Interface Name", wan_prefix, validate_wan_ifname, NULL, TRUE, NVRAM_MI }, 11619 { "wan_hwaddr", "MAC Address", wan_prefix, validate_hwaddr, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11620 { "wan_ipaddr", "IP Address", wan_prefix, validate_ipaddr, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11621 { "wan_netmask", "Subnet Mask", wan_prefix, validate_ipaddr, NULL, FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11622 { "wan_gateway", "Default Gateway", wan_prefix, validate_ipaddr, NULL, TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11623 { "wan_dns", "DNS Servers", wan_prefix, validate_ipaddrs, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11624 { "wan_wins", "WINS Servers", wan_prefix, validate_ipaddrs, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11625 { "wan_pppoe_ifname", "PPPoE Interface Name", wan_prefix, NULL, NULL, TRUE, NVRAM_MI }, 11626 { "wan_pppoe_username", "PPPoE Username", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11627 { "wan_pppoe_passwd", "PPPoE Password", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_WRITE }, 11628 { "wan_pppoe_service", "PPPoE Service Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11629 { "wan_pppoe_ac", "PPPoE Access Concentrator", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11630 { "wan_pppoe_keepalive", "PPPoE Keep Alive", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11631 { "wan_pppoe_demand", "PPPoE Connect on Demand", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11632 { "wan_pppoe_idletime", "PPPoE Max Idle Time", wan_prefix, validate_range, ARGV("1", "3600"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11633 { "wan_pppoe_mru", "PPPoE MRU", wan_prefix, validate_range, ARGV("128", "16384"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11634 { "wan_pppoe_mtu", "PPPoE MTU", wan_prefix, validate_range, ARGV("128", "16384"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11635 { "wan_primary", "Primary Interface", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI }, 11636 { "wan_route", "Static Routes", wan_prefix, validate_wan_route, NULL, FALSE, NVRAM_MI }, 11637 /* MUST leave this entry here after all wl_XXXX per-interface variables */ 11638 { "wan_unit", "WAN Instance", wan_prefix, wan_unit, NULL, TRUE, NVRAM_MI|NVRAM_MP }, 11639 /* filter settings */ 11640 { "filter_macmode", "MAC Filter Mode", NULL, validate_choice, ARGV("disabled", "allow", "deny"), FALSE, 0 }, 11641 { "filter_maclist", "MAC Filter", NULL, validate_hwaddrs, NULL, TRUE, 0 }, 11642 { "filter_client", "LAN Client Filter", NULL, validate_filter_client, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11643#ifdef __CONFIG_URLFILTER__ 11644 { "filter_url", "URL Filter", NULL, validate_filter_url, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11645#endif /* __CONFIG_URLFILTER__ */ 11646 /* routing settings */ 11647 { "forward_port", "Port Forward", NULL, validate_forward_port, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11648#if !defined(AUTOFW_PORT_DEPRECATED) 11649 { "autofw_port", "Application Specific Port Forward", NULL, validate_autofw_port, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11650#endif 11651 { "nat_type", "NAT Type Support", NULL, validate_choice, ARGV("cone", "sym"), TRUE, 0 }, 11652 { "dmz_ipaddr", "DMZ LAN IP Address", NULL, validate_ipaddr, ARGV("lan_ipaddr", "lan_netmask"), TRUE, 0 }, 11653#endif /* __CONFIG_NAT__ */ 11654 { "ure_disable", "URE Mode", NULL, NULL, ARGV("0"), FALSE, WEB_IGNORE }, 11655 11656 /* ALL wl_XXXX variables are per-interface */ 11657 /* This group is per ssid */ 11658 { "wl_bss_enabled", "BSS Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11659 11660#ifdef __CONFIG_HSPOT__ 11661 { "wl_hsflag", "Passpoint Flags", wl_prefix, validate_wl_hsflag, ARGV("0", "65535"), FALSE, NVRAM_MI }, 11662 { "wl_hs2cap", "Passpoint Capability", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11663 { "wl_opercls", "Operating Class", wl_prefix, validate_choice, ARGV("1", "2", "3"), FALSE, NVRAM_MI }, 11664 { "wl_anonai", "Anonymous NAI", wl_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11665 { "wl_wanmetrics", "WAN Metrics", wl_prefix, validate_wl_wanmetrics, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11666 { "wl_oplist", "Operator Friendly Name List", wl_prefix, validate_wl_oplist, ARGV("0", "1080"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11667 { "wl_homeqlist", "NAI Home Realm Query List", wl_prefix, validate_wl_homeqlist, ARGV("0", "1080"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11668 { "wl_osu_ssid", "OSU provider SSID", wl_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11669 { "wl_osu_frndname", "OSU Friendly name", wl_prefix, validate_wl_osuplist, ARGV("0", "2048"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11670 { "wl_osu_uri", "OSU URI", wl_prefix, validate_wl_osuplist, ARGV("0", "1024"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11671 { "wl_osu_nai", "OSU NAI", wl_prefix, validate_wl_osuplist, ARGV("0", "1024"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11672 { "wl_osu_method", "OSU Icon", wl_prefix, validate_wl_osuplist, ARGV("0", "20"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11673 { "wl_osu_icons", "OSU Icon", wl_prefix, validate_wl_osuplist, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11674 { "wl_osu_servdesc", "OSU Service Description", wl_prefix, validate_wl_osuplist, ARGV("0", "2048"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11675 { "wl_concaplist", "Connection Capability List", wl_prefix, validate_wl_concaplist, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11676 { "wl_qosmapie", "QoS Map IE", wl_prefix, validate_wl_qosmapie, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11677 { "wl_gascbdel", "GAS CB Delay", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11678 11679 /* ---- 802.11u ----------------------------------- */ 11680 { "wl_iwnettype", "Acees Network Type", wl_prefix, validate_choice, ARGV("0", "1", "2", "3", "4", "5", "14", "15"), FALSE, NVRAM_MI }, 11681 { "wl_hessid", "Interworking HESSID", wl_prefix, validate_hwaddr, NULL, TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11682 { "wl_ipv4addr", "IPV4 Address Type Availability", wl_prefix, validate_choice, ARGV("0", "1", "2", "3", "4", "5", "6", "7"), FALSE, NVRAM_MI }, 11683 { "wl_ipv6addr", "IPV6 Address Type Availability", wl_prefix, validate_choice, ARGV("0", "1", "2"), FALSE, NVRAM_MI }, 11684 { "wl_netauthlist", "Network Authentication Type List", wl_prefix, validate_wl_netauthlist, ARGV("0", "600"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11685 { "wl_venuegrp", "Venue Group", wl_prefix, validate_choice, ARGV("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"), FALSE, NVRAM_MI }, 11686 { "wl_venuetype", "BSS Venue Type", wl_prefix, validate_choice, ARGV("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17"), FALSE, NVRAM_MI }, 11687 { "wl_venuelist", "Venue Name List", wl_prefix, validate_wl_venuelist, ARGV("0", "1080"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11688 { "wl_ouilist", "Roaming Consortium List", wl_prefix, validate_wl_ouilist, ARGV("0", "128"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11689 { "wl_3gpplist", "3GPP Cellular Network Information Name List", wl_prefix, validate_wl_3gpplist, ARGV("0", "128"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11690 { "wl_domainlist", "Domain Name List", wl_prefix, validate_names, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11691 { "wl_realmlist", "NAI Realm List", wl_prefix, validate_wl_realmlist, ARGV("0", "4096"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11692 11693#endif /* __CONFIG_HSPOT__ */ 11694 11695 { "wl_ssid", "Network Name (ESSID)", wl_prefix, validate_ssid, ARGV("1", "32"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11696 { "wl_bridge", "Bridge Details", wl_prefix, validate_bridge, ARGV("0", "1"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11697 { "wl_closed", "Network Type", wl_prefix, validate_wl_closed, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11698 { "wl_ap_isolate", "AP Isolate", wl_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI }, 11699 { "wl_wmf_bss_enable", "WMF Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11700 { "wl_mcast_regen_bss_enable", "Multicast Regen Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11701 { "wl_macmode", "MAC Restrict Mode", wl_prefix, validate_wl_macmode, ARGV("disabled", "allow", "deny"), FALSE,NVRAM_MI }, 11702 { "wl_maclist", "Allowed MAC Address", wl_prefix, validate_hwaddrs, NULL, TRUE, NVRAM_MI }, 11703 { "wl_mode", "Mode", wl_prefix, validate_wl_mode, ARGV("ap", "wds", "sta", "wet", "apsta", "mac_spoof", "psta", "psr"), FALSE,NVRAM_MI }, 11704 { "wl_infra", "Network", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11705 { "wl_dwds", "DWDS", wl_prefix, validate_wl_dwds, ARGV("0", "1"), FALSE, NVRAM_MI }, 11706#ifdef __CONFIG_ROUTER_MINI__ 11707 /* Mini router has lower maxassoc (MAXSCB) limit */ 11708 { "wl_bss_maxassoc", "Per BSS Max Association Limit", wl_prefix, validate_range, ARGV("1", "64"), FALSE,NVRAM_MI }, 11709#else 11710 { "wl_bss_maxassoc", "Per BSS Max Association Limit", wl_prefix, validate_range, ARGV("1", "128"), FALSE,NVRAM_MI }, 11711#endif /* __CONFIG_ROUTER_MINI__ */ 11712 { "wl_wme_bss_disable", "Per-BSS WME Disable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11713 { "wl_bss_opmode_cap_reqd", "Per-BSS operational capabilities required", wl_prefix, validate_choice, ARGV("0", "1", "2", "3"), FALSE, NVRAM_MI }, 11714/* 11715*/ 11716#ifdef __CONFIG_WFI__ 11717 { "wl_wfi_enable", "Wifi Invite feature", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11718 { "wl_wfi_pinmode", "WFI PIN mode", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11719#endif /* __CONFIG_WFI__ */ 11720/* 11721*/ 11722 { "wl_wet_tunnel" , "Enable WET Tunnel", wl_prefix, validate_choice, ARGV("1", "0"), FALSE, NVRAM_MI}, 11723#ifdef TRAFFIC_MGMT_RSSI_POLICY 11724 { "wl_trf_mgmt_rssi_policy", "TRF MGMT RSSI Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11725#endif /* TRAFFIC_MGMT_RSSI_POLICY */ 11726 { "wl_atf", "Airtime Fairness", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11727#ifdef __CONFIG_EMF__ 11728 { "wl_wmf_ucigmp_query", "Unicast IGMP Query Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11729 { "wl_wmf_mdata_sendup", "Sendup Multicast Data Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11730 { "wl_wmf_psta_disable", "Sendup Multicast to PSTA disable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11731#endif /* __CONFIG_EMF__ */ 11732 { "wl_pspretend_threshold", "Stalled Link Detection Threshold", wl_prefix, validate_range, ARGV("0", "32"), FALSE, NVRAM_MI | VIF_IGNORE }, 11733 { "wl_pspretend_retry_limit", "PsPretend retry limit", wl_prefix, validate_range, ARGV("0", "32"), FALSE, NVRAM_MI | VIF_IGNORE }, 11734#ifdef __CONFIG_EXTACS__ 11735 { "wl_acs_fcs_mode", "ACS Fast Channel Switch Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11736 { "wl_acs_dfs", "ACS DFS Channel Selection", wl_prefix, validate_range, ARGV("0", "2"), FALSE, NVRAM_MI | VIF_IGNORE }, 11737 { "wl_acs_dfsr_immediate", "ACS DFS Immediate Reentry Window", wl_prefix, validate_dfs_window, NULL, NVRAM_MI | VIF_IGNORE }, 11738 { "wl_acs_dfsr_deferred", "ACS DFS Deferred Reentry Window", wl_prefix, validate_dfs_window, NULL, NVRAM_MI | VIF_IGNORE }, 11739 { "wl_acs_dfsr_activity", "ACS DFS Channel Active Window", wl_prefix, validate_dfs_window, NULL, NVRAM_MI | VIF_IGNORE }, 11740 { "wl_acs_cs_scan_timer", "ACS CS Scan Interval", wl_prefix, validate_range, ARGV("60", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11741 { "wl_acs_ci_scan_timer", "ACS CI Scan Interval", wl_prefix, validate_range, ARGV("1", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11742 { "wl_acs_ci_scan_timeout", "ACS CI Scan Timeout", wl_prefix, validate_range, ARGV("1", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11743 { "wl_acs_scan_entry_expire", "Scan Result Timeout", wl_prefix, validate_range, ARGV("1", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11744 { "wl_acs_tx_idle_cnt", "TX Idle Frame Count", wl_prefix, validate_range, ARGV("0", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11745 { "wl_acs_chan_dwell_time", "ACS Scan Dwell Time", wl_prefix, validate_range, ARGV("1", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11746 { "wl_acs_chan_flop_period", "ACS Chan Flop Period", wl_prefix, validate_range, ARGV("1", "4294967295"), FALSE, NVRAM_MI | VIF_IGNORE }, 11747 11748 { "wl_intfer_period", "Sample Period", wl_prefix, validate_range, ARGV("0", "65535"), FALSE, NVRAM_MI | VIF_IGNORE }, 11749 { "wl_intfer_cnt", "Sample Count", wl_prefix, validate_range, ARGV("1", "4"), FALSE, NVRAM_MI | VIF_IGNORE }, 11750 { "wl_intfer_txfail", "non-TCP TxFail threshold", wl_prefix, validate_range, ARGV("0", "65535"), FALSE, NVRAM_MI | VIF_IGNORE }, 11751 { "wl_intfer_tcptxfail", "TCP TxFail threshold", wl_prefix, validate_range, ARGV("0", "65535"), FALSE, NVRAM_MI | VIF_IGNORE }, 11752#endif /* __CONFIG_EXTACS__ */ 11753 { "wl_probresp_mf", "MAC filter based Probe Response", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11754 /* This group is per radio */ 11755 { "wl_ure", "URE Mode",NULL, validate_ure, ARGV("0"), FALSE, NVRAM_MI | VIF_IGNORE }, 11756 { "wl_vifs", "WL Virtual Interfaces", NULL, NULL, ARGV("0"), FALSE, NVRAM_MI | WEB_IGNORE }, 11757 { "wl_country_code", "Country Code", wl_prefix, validate_wl_country_code, NULL, FALSE, NVRAM_MI | VIF_IGNORE }, 11758 { "wl_country_rev", "Country Revision", wl_prefix, validate_wl_country_rev, NULL, FALSE, NVRAM_MI | VIF_IGNORE }, 11759 { "wl_lazywds", "Bridge Restrict", wl_prefix, validate_wl_lazywds, ARGV("0", "1"), FALSE,NVRAM_MI | VIF_IGNORE }, 11760 { "wl_wds", "Bridges", wl_prefix, validate_wl_wds_hwaddrs, NULL, TRUE, NVRAM_MI | VIF_IGNORE }, 11761 { "wl_wds_timeout", "Link Timeout Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11762 { "wl_radio", "Radio Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 11763 { "wl_phytype", "Radio Band", wl_prefix, validate_choice, ARGV("a", "b", "g", "n", "l", "s", "h"), TRUE, NVRAM_MI | VIF_IGNORE }, 11764 { "wl_antdiv", "Antenna Diversity", wl_prefix, validate_choice, ARGV("-1", "0", "1", "3"), FALSE, NVRAM_MI | VIF_IGNORE }, 11765 { "wl_chanspec", "Channel Specification", wl_prefix, validate_wl_chanspec, NULL, FALSE, NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11766 { "wl_reg_mode", "Regulatory Mode", wl_prefix, validate_choice, ARGV("off", "h", "strict_h", "d"), FALSE, NVRAM_MI | VIF_IGNORE}, 11767 { "wl_tpc_db", "TPC Mitigation (db)", wl_prefix, validate_range, ARGV("0", "99"), FALSE,NVRAM_MI | VIF_IGNORE}, 11768 { "wl_rate", "Rate", wl_prefix, validate_range, ARGV("0", "54000000"), FALSE,NVRAM_MI | VIF_IGNORE }, 11769 { "wl_rateset", "Supported Rates", wl_prefix, validate_choice, ARGV("all", "default", "12"), FALSE,NVRAM_MI | VIF_IGNORE}, 11770 { "wl_mrate", "Multicast Rate", wl_prefix, validate_range, ARGV("0", "54000000"), FALSE,NVRAM_MI | VIF_IGNORE }, 11771 { "wl_frag", "Fragmentation Threshold", wl_prefix, validate_range, ARGV("256", "2346"), FALSE,NVRAM_MI | VIF_IGNORE }, 11772 { "wl_rts", "RTS Threshold", wl_prefix, validate_range, ARGV("0", "2347"), FALSE, NVRAM_MI | VIF_IGNORE }, 11773 { "wl_dtim", "DTIM Period", wl_prefix, validate_range, ARGV("1", "255"), FALSE, NVRAM_MI | VIF_IGNORE }, 11774 { "wl_bcn", "Beacon Interval", wl_prefix, validate_range, ARGV("1", "65535"), FALSE, NVRAM_MI | VIF_IGNORE}, 11775 { "wl_bcn_rotate", "Beacon Rotation", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11776 { "wl_plcphdr", "Preamble Type", wl_prefix, validate_choice, ARGV("long", "short"), FALSE, NVRAM_MI | VIF_IGNORE }, 11777 { "wl_maxassoc", "Max Association Limit", wl_prefix, validate_range, ARGV("1", "128"), FALSE,NVRAM_MI | VIF_IGNORE }, 11778 { "wl_gmode", "54g Mode", wl_prefix, validate_choice, ARGV(XSTR(GMODE_AUTO), XSTR(GMODE_ONLY), XSTR(GMODE_PERFORMANCE), XSTR(GMODE_LRS), XSTR(GMODE_LEGACY_B)), FALSE, NVRAM_MI | VIF_IGNORE }, 11779 { "wl_gmode_protection", "54g Protection", wl_prefix, validate_choice, ARGV("off", "auto"), FALSE,NVRAM_MI | VIF_IGNORE }, 11780 { "wl_frameburst", "XPress Technology", wl_prefix, validate_choice, ARGV("off", "on"), FALSE,NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11781 { "wl_txbf_bfr_cap", "TX Beamformer", wl_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11782 { "wl_txbf_bfe_cap", "TX Beamformee", wl_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11783 { "wl_nband", "Radio Band for EWC", wl_prefix, validate_choice, ARGV("1", "2"), TRUE, NVRAM_MI | VIF_IGNORE }, 11784 { "wl_bw_cap", "Channel Bandwidth", wl_prefix, validate_choice, ARGV("1", "3", "7"), TRUE, NVRAM_MI | VIF_IGNORE}, 11785 { "wl_nmcsidx", "MCS Index", wl_prefix, validate_range, ARGV("-2", "32"), TRUE, NVRAM_MI | VIF_IGNORE}, 11786 { "wl_nmode", "802.11 N mode", wl_prefix, validate_choice, ARGV("-1", "0"), TRUE, NVRAM_MI | VIF_IGNORE}, 11787 { "wl_txchain", "Number of TxChains", wl_prefix, validate_range, ARGV("1", "7"), TRUE, NVRAM_MI | VIF_IGNORE }, 11788 { "wl_rxchain", "Number of RxChains", wl_prefix, validate_range, ARGV("1", "7"), TRUE, NVRAM_MI | VIF_IGNORE }, 11789 { "wl_vlan_prio_mode", "VLAN Priority Support", wl_prefix, validate_choice, ARGV("off", "on"), TRUE, NVRAM_MI | VIF_IGNORE}, 11790 { "wl_nmode_protection", "802.11n Protection", wl_prefix, validate_choice, ARGV("off", "auto"), FALSE,NVRAM_MI | VIF_IGNORE }, 11791 { "wl_mimo_preamble", "802.11n Preamble", wl_prefix, validate_choice, ARGV("mm", "gf", "auto", "gfbcm"), FALSE,NVRAM_MI | VIF_IGNORE }, 11792 { "wl_rifs", "Enable/Disable RIFS Transmissions", wl_prefix, validate_choice, ARGV("auto", "off", "on"), FALSE, NVRAM_MI | VIF_IGNORE}, 11793 { "wl_rifs_advert", "RIFS Mode Advertisement", wl_prefix, validate_choice, ARGV("auto", "off"), FALSE, NVRAM_MI | VIF_IGNORE}, 11794 { "wl_stbc_tx", "Enable/Disable STBC Transmissions", wl_prefix, validate_choice, ARGV("auto", "off", "on"), FALSE, NVRAM_MI | VIF_IGNORE}, 11795 { "wl_amsdu", "MSDU aggregation Technology", wl_prefix, validate_choice, ARGV("auto", "off", "on"), FALSE, NVRAM_MI | VIF_IGNORE }, 11796 { "wl_ampdu", "MPDU aggregation Technology", wl_prefix, validate_choice, ARGV("auto", "off", "on"), FALSE, NVRAM_MI | VIF_IGNORE }, 11797 { "wl_wme", "WME Support", wl_prefix, validate_choice, ARGV("auto", "off", "on"), FALSE, NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11798 { "wl_wme_no_ack", "No-Acknowledgement", wl_prefix, validate_wme_bool, ARGV("off", "on"), FALSE,NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11799 { "wl_wme_apsd", "U-APSD Support", wl_prefix, validate_wme_bool, ARGV("off", "on"), FALSE, NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11800 { "wl_wme_ap_be", "WME AP BE", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11801 { "wl_wme_ap_bk", "WME AP BK", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11802 { "wl_wme_ap_vi", "WME AP VI", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11803 { "wl_wme_ap_vo", "WME AP VO", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11804 { "wl_wme_sta_be", "WME STA BE", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11805 { "wl_wme_sta_bk", "WME STA BK", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11806 { "wl_wme_sta_vi", "WME STA VI", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11807 { "wl_wme_sta_vo", "WME STA VO", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11808 { "wl_wme_txp_be", "WME TXP BE", wl_prefix, validate_wl_wme_tx_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11809 { "wl_wme_txp_bk", "WME TXP BK", wl_prefix, validate_wl_wme_tx_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11810 { "wl_wme_txp_vi", "WME TXP VI", wl_prefix, validate_wl_wme_tx_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11811 { "wl_wme_txp_vo", "WME TXP VO", wl_prefix, validate_wl_wme_tx_params, NULL, TRUE, NVRAM_MI | VIF_IGNORE}, 11812 { "wl_obss_coex", "Overlapping BSS Coexistence", wl_prefix, validate_choice, ARGV("0", "1"), TRUE, NVRAM_MI | VIF_IGNORE }, 11813 { "wl_probresp_sw", "SW Probe Response", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | VIF_IGNORE }, 11814 { "wl_vht_features", "VHT features", wl_prefix, validate_range, ARGV("0", "255"), FALSE, NVRAM_MI | VIF_IGNORE }, 11815 /* security parameters */ 11816 { "wl_key", "Network Key Index", wl_prefix, validate_range, ARGV("1", "4"), FALSE,NVRAM_MI | EZC_FLAGS_WRITE }, 11817 { "wl_key1", "Network Key 1", wl_prefix, validate_wl_key, NULL, TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 11818 { "wl_key2", "Network Key 2", wl_prefix, validate_wl_key, NULL, TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 11819 { "wl_key3", "Network Key 3", wl_prefix, validate_wl_key, NULL, TRUE,NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 11820 { "wl_key4", "Network Key 4", wl_prefix, validate_wl_key, NULL, TRUE,NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 11821 { "wl_auth", "802.11 Authentication", wl_prefix, validate_wl_auth, ARGV("0", "1", "2"), FALSE, NVRAM_MI | 0}, 11822 { "wl_auth_mode", "Network Authentication", wl_prefix, validate_wl_auth_mode, ARGV("radius", "none"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11823 { "wl_akm", "Authenticated Key Management", wl_prefix, validate_wl_akm, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11824 { "wl_wep", "WEP Encryption", wl_prefix, validate_wl_wep, ARGV("disabled", "enabled"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11825 { "wl_crypto", "WPA Encryption", wl_prefix, validate_wl_crypto, ARGV("tkip", "aes", "tkip+aes"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11826 { "wl_net_reauth", "Network Re-auth Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI }, 11827 { "wl_preauth", "Network Preauthentication Support", wl_prefix, validate_wl_preauth, ARGV("disabled", "enabled"), FALSE,NVRAM_MI | 0 }, 11828 { "wl_radius_ipaddr", "RADIUS Server", wl_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11829 { "wl_radius_port", "RADIUS Port", wl_prefix, validate_range, ARGV("0", "65535"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11830 { "wl_radius_key", "RADIUS Shared Secret", wl_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 11831 { "wl_wpa_psk", "WPA Pre-Shared Key", wl_prefix, validate_wl_wpa_psk, ARGV("64"), TRUE, NVRAM_ENCRYPT | NVRAM_MI | EZC_FLAGS_WRITE}, 11832 { "wl_wpa_gtk_rekey", "Network Key Rotation Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11833#ifdef MFP 11834 { "wl_mfp", "Management Frame Protection", wl_prefix, validate_wl_mfp, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11835#endif 11836 /* Multi SSID Guest interface flag */ 11837 { "wl_guest", "Guest SSID Interface", wl_prefix, NULL, NULL, TRUE, WEB_IGNORE|NVRAM_MI }, 11838 { "wl_sta_retry_time", "STA Retry Time", wl_prefix, validate_range, ARGV("0", "3600"), FALSE, NVRAM_MI }, 11839#ifdef __CONFIG_WPS__ 11840 /* 11841 * WPS Setting, put wl_wps_mode latter than other wl_xxx variables except wl_unit. 11842 * We have to do other validations check before validate_wps_mode 11843 */ 11844 { "wl_wps_mode", "WPS Mode", wl_prefix, validate_wps_mode, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11845#endif /* __CONFIG_WPS__ */ 11846 /* MUST leave this entry here after all wl_XXXX variables */ 11847 { "wl_unit", "802.11 Instance", wl_prefix, wl_unit, NULL, TRUE, NVRAM_IGNORE|NVRAM_MI|NVRAM_MP }, 11848#ifdef __CONFIG_WPS__ 11849 /* MUST leave wps_reg and wps_oob here after wl_unit */ 11850 { "wps_reg", "WPS Registrar Mode", NULL, validate_wps_reg, NULL, FALSE, 0 }, 11851 { "wps_oob", "WPS OOB state", NULL, validate_wps_oob, NULL, FALSE, 0 }, 11852 { "wps_device_name", "WPS device name", NULL, validate_name, ARGV("1", "32"), FALSE, 0 }, 11853 { "wps_wer_mode", "Wireless ER Restrict Mode", NULL, validate_choice, ARGV("allow", "deny"), FALSE,0 }, 11854#ifdef WFA_WPS_20_TESTBED 11855 { "wps_version2", "WPS version supported", NULL, validate_choice, ARGV("enabled", "disabled"), FALSE, 0 }, 11856 { "wps_version2_num", "WPS version2 number", NULL, validate_wps2_range, ARGV("20", "99"), FALSE, 0 }, 11857 { "wps_ie_frag", "WPS IE fragment threshold", NULL, validate_wps2_range, ARGV("72", "228"), FALSE, 0 }, 11858 { "wps_eap_frag", "WPS EAP fragment threshold", NULL, validate_wps2_range, ARGV("100", "1398"), FALSE, 0 }, 11859 { "wps_nattr", "New attribute", NULL, validate_name, ARGV("0", "127"), FALSE, 0 }, 11860 { "wps_zpadding", "Do Zero Padding", NULL, validate_range, ARGV("0", "1"), FALSE, 0 }, 11861 { "wps_mca", "Multiple Credential Attribute", NULL, validate_range, ARGV("0", "1"), FALSE, 0 }, 11862#endif /* WFA_WPS_20_TESTBED */ 11863#endif /* __CONFIG_WPS__ */ 11864 /* Internal variables */ 11865 { "os_server", "OS Server", NULL, NULL, NULL, TRUE, 0 }, 11866 { "stats_server", "Stats Server", NULL, NULL, NULL, TRUE, 0 }, 11867 { "timer_interval", "Timer Interval", NULL, NULL, NULL, TRUE, 0 }, 11868 { "lan_ifname", "LAN Interface Name", lan_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 11869 { "lan_ifnames", "LAN Interface Names", NULL, NULL, NULL, TRUE, 0 }, 11870 { "lan1_ifnames", "Guest Interface Names", NULL, NULL, NULL, TRUE, 0 }, 11871 { "wan_ifnames", "WAN Interface Names", NULL, NULL, NULL, TRUE, 0 }, 11872#if defined(__CONFIG_DLNA_DMR__) 11873 { "dlna_dmr_enable", "DLNA Renderer",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11874#endif 11875#if defined(__CONFIG_DLNA_DMS__) 11876 { "dlna_dms_enable", "DLNA Server",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11877#endif 11878#if defined(__CONFIG_SAMBA__) 11879 { "samba_mode", "Samba Mode",NULL, validate_range, ARGV("0", "2"), FALSE, 0 }, 11880 { "samba_passwd", "Samba Password",NULL, validate_name, ARGV("0", "63"), FALSE, NVRAM_ENCRYPT | EZC_FLAGS_WRITE }, 11881#endif 11882#ifdef __CONFIG_NORTON__ 11883 { "nga_lickey", "NGA License Key",NULL, validate_name, ARGV("0", "63"), TRUE, NVRAM_ENCRYPT }, 11884 { "nga_user", "NGA Username", NULL, validate_name, ARGV("0", "254"), TRUE, NVRAM_ENCRYPT }, 11885 { "nga_pass", "NGA Password", NULL, validate_name, ARGV("0", "63"), TRUE, NVRAM_IGNORE }, 11886 { "nga_devname", "NGA Device Name", NULL, validate_name, ARGV("0", "63"), TRUE, 0 }, 11887 { "nga_ncw", "NGA Community Watch", NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11888 { "nga_enable", "NGA Enabled", NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 11889 { "nga_gact", "NGA Generic Action", NULL, validate_name, ARGV("0", "2048"), TRUE, NVRAM_IGNORE }, 11890 { "ngap_0", "NGA Bind ID", NULL, NULL, NULL, TRUE, NVRAM_ENCRYPT | WEB_IGNORE }, 11891 { "ngap_1", "NGA Bind Validation", NULL, NULL, NULL, TRUE, NVRAM_ENCRYPT | WEB_IGNORE }, 11892 { "NGA_MID", "NGA MID", NULL, NULL, NULL, TRUE, WEB_IGNORE }, 11893#endif /* __CONFIG_NORTON__ */ 11894 { "coma_sleep", "Coma Mode Sleep Time", NULL, NULL, NULL, TRUE, 0 }, 11895 { "trf_mgmt_dwm", "Traffic Management DWM", NULL, validate_trf_mgmt_dwm, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 11896 { "wl_dfs_pref", "DFS Preferred chan", wl_prefix, validate_dfs_prefchan, NULL, FALSE, NVRAM_MI | VIF_IGNORE | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 11897}; 11898 11899/* build hashtable of the monster v-block 11900 11901 Inputs: 11902 -tab: hash table structure 11903 -vblock: the monster V-block 11904 -num_items: estimated size of hash table 11905 11906 Returns: 0 on success -1 on error 11907*/ 11908 11909int 11910hash_vtab(struct hsearch_data *tab,struct variable *vblock,int num_items) 11911{ 11912 ENTRY e, *ep=NULL; 11913 int count; 11914 11915 assert(tab); 11916 assert(vblock); 11917 11918 if (!num_items) return -1; 11919 11920 if (!hcreate_r(num_items,tab)) 11921 { 11922 return -1; 11923 } 11924 11925 11926 for (count=0; count < num_items; count++) 11927 { 11928 e.key = vblock[count].name; 11929 e.data = &vblock[count]; 11930 if (!hsearch_r(e, ENTER, &ep, tab)) 11931 return -1; 11932 } 11933 11934 return 0; 11935 11936} 11937/* The routine gets the pointer into the giant "V" block above give the cgi var name.. 11938 Inputs: 11939 -varname: Pointer to cgi var name 11940 11941 Returns: entry within "V" block or NULL if not found. 11942 11943 It will try the following forms 11944 varXX_type 11945 var_typeXX 11946 vlanXXtype 11947 11948 where XX is the instance number 11949 11950*/ 11951 11952static struct variable* 11953get_var_handle(char *varname) 11954{ 11955 ENTRY e, *ep=NULL; 11956 struct variable *variable=NULL; 11957 char *ptr=NULL,*ptr2=NULL; 11958 int offset; 11959 char prefix[8],tmp[64]; 11960 11961 if (!varname ) return NULL; 11962 if (!*varname) return NULL; 11963 11964 ep=NULL; 11965 e.key = varname; 11966 hsearch_r(e, FIND, &ep, &vtab); 11967 11968 11969 /* found something */ 11970 if (ep) 11971 { 11972 variable = (struct variable *)ep->data; 11973 if ( variable->ezc_flags & NVRAM_MP) return variable; 11974 11975 /* Drop the variable is multi instance but not 11976 Multi personality 11977 */ 11978 11979 if ( variable->ezc_flags & NVRAM_MI) return NULL; 11980 if ( variable->ezc_flags & NVRAM_VLAN_MULTI) return NULL; 11981 if ( variable->ezc_flags & NVRAM_GENERIC_MULTI) return NULL; 11982 11983 return variable; 11984 11985 } 11986 11987 /* variable not found could be the form of vlanXXtype, varXX_type or var_typeXX*/ 11988 11989 ptr=strchr(varname,'_'); 11990 11991 /* Is it vlanXXtype ? */ 11992 if (!ptr) 11993 { 11994 if (!strstr(varname,"vlan")) return NULL; 11995 strcpy(tmp,"vlan"); 11996 offset=4; 11997 ptr=&varname[offset]; 11998 while (*ptr){ 11999 if (!isdigit((int)*ptr)) tmp[offset++] = *ptr; 12000 ptr++; 12001 } 12002 12003 tmp[offset] = '\0'; 12004 ep = NULL; 12005 e.key = tmp; 12006 hsearch_r(e, FIND, &ep, &vtab); 12007 12008 /* check to see if this has the 12009 NVRAM_VLAN MULTI flag set in the v-block 12010 */ 12011 if (ep){ 12012 variable = (struct variable *)ep->data; 12013 if (variable->ezc_flags & NVRAM_VLAN_MULTI) 12014 return variable; 12015 } 12016 12017 return NULL; 12018 } 12019 12020 /* Is it varXX_type ? */ 12021 ptr2=varname; 12022 offset=0; 12023 memset(prefix,0,sizeof(prefix)); 12024 while (ptr2 < ptr){ 12025 if (isdigit((int)*ptr2)) break; 12026 prefix[offset++] =*ptr2; 12027 ptr2++; 12028 } 12029 snprintf(tmp,sizeof(tmp),"%s%s",prefix,ptr); 12030 12031 ep = NULL; 12032 e.key = tmp; 12033 hsearch_r(e, FIND, &ep, &vtab); 12034 12035 if (ep){ 12036 variable = (struct variable *)ep->data; 12037 if (variable->ezc_flags & NVRAM_MI) 12038 return variable; 12039 } 12040 12041 /* Is is a var_typeXX */ 12042 strncpy(tmp,varname,sizeof(tmp) - 1); 12043 tmp[sizeof(tmp) - 1] = '\0'; 12044 12045 offset = strlen(tmp) - 1 ; 12046 while(isdigit((int)tmp[offset])) 12047 tmp[offset--] = '\0'; 12048 ep = NULL; 12049 e.key = tmp; 12050 hsearch_r(e, FIND, &ep, &vtab); 12051 12052 if (ep){ 12053 variable = (struct variable *)ep->data; 12054 if (variable->ezc_flags & NVRAM_GENERIC_MULTI) 12055 return variable; 12056 } 12057 12058 return NULL; 12059} 12060int 12061variables_arraysize(void) 12062{ 12063 return ARRAYSIZE(variables); 12064} 12065 12066/* Need to do special handling for the lan cgi stuff as the DHCP ranges need 12067 overlap checking . In addition multi index variables are also present 12068 on the same page. This breaks the conventional validation flow as implemented 12069*/ 12070static void 12071validate_lan_cgi(webs_t wp) 12072{ 12073 char cgi_vars[][32]= { 12074 "lan_dhcp", 12075 "lan_ipaddr", 12076 "lan_netmask", 12077 "lan_gateway", 12078 "lan_proto", 12079 "dhcp_start", 12080 "dhcp_end", 12081 "lan_lease", 12082 "lan_stp", 12083 "lan_route", 12084#ifdef __CONFIG_EMF__ 12085 "emf_enable", 12086 "emf_entry", 12087 "emf_uffp_entry", 12088 "emf_rtport_entry", 12089#endif /* __CONFIG_EMF__ */ 12090 12091/* 12092*/ 12093#ifdef __CONFIG_IPV6__ 12094 "lan_ipv6_prefix", 12095 "lan_ipv6_dns", 12096 "lan_ipv6_mode", 12097 "lan_ipv6_6to4id", 12098#endif /* __CONFIG_IPV6__ */ 12099/* 12100*/ 12101 }; 12102 12103 int count,num_ifaces; 12104 char *varname=NULL,*value=NULL; 12105 struct variable *v=NULL; 12106 int num_items = sizeof(cgi_vars)/sizeof(cgi_vars[0]); 12107 struct in_addr i_addr,g_addr,i_mask,g_mask; 12108 char err_msg[255] ; 12109 char vector[16]; 12110 int router_enable=0; 12111 12112 ret_code = EINVAL; 12113 12114 memset(err_msg,0,sizeof(err_msg)); 12115 memset(vector,0,sizeof(vector)); 12116 12117 websBufferInit(wp); 12118 if (!webs_buf) { 12119 snprintf(err_msg,sizeof(err_msg),"out of memory<br>"); 12120 goto validate_lan_cgi_error; 12121 } 12122 12123 value = websGetVar(wp, "num_lan_ifaces" , NULL); 12124 if (!value){ 12125 snprintf(err_msg,sizeof(err_msg), 12126 "unable to get number of lan interfaces<br>"); 12127 goto validate_lan_cgi_error; 12128 } 12129 12130 num_ifaces=atoi(value); 12131 12132 router_enable = nvram_match("router_disable","0"); 12133 12134 /* Build a LAN block valid enabled vector, skip processing if the 12135 * vector is not set. 12136 */ 12137 for (count=0; count < num_ifaces ; count++){ 12138 char buf[64]; 12139 12140 if (count) 12141 snprintf(buf, sizeof(buf), "lan%d_ifname", count); 12142 else 12143 snprintf(buf, sizeof(buf), "lan_ifname"); 12144 12145 /* Skip LAN blocks that aren't enabled */ 12146 value = websGetVar(wp, buf , NULL); 12147 if (!value || !*value) 12148 continue; 12149 12150 vector[count] = 1; 12151 } 12152 12153 /* check to see if the ip addresses overlap */ 12154 for (count=0; count < num_ifaces ; count++){ 12155 int entry; 12156 char *valueA,*valueB; 12157 char lanA_ipaddr[32],lanA_netmask[32]; 12158 char lanB_ipaddr[32],lanB_netmask[32]; 12159 char dhcpA_start[32],dhcpB_start[32]; 12160 char dhcpA_end[32],dhcpB_end[32]; 12161 char lanA_ifname[32],lanB_ifname[32]; 12162 char lanA_proto[32],lanB_proto[32]; 12163 12164 /* Skip LAN blocks that aren't enabled */ 12165 if (!vector[count]) 12166 continue; 12167 12168 if (count){ 12169 snprintf(lanA_ifname,sizeof(lanA_ifname),"lan%d_ifname",count); 12170 snprintf(lanA_ipaddr,sizeof(lanA_ipaddr),"lan%d_ipaddr",count); 12171 snprintf(lanA_netmask,sizeof(lanA_netmask),"lan%d_netmask",count); 12172 snprintf(lanA_proto,sizeof(lanA_proto),"lan%d_proto",count); 12173 snprintf(dhcpA_start,sizeof(dhcpA_start),"dhcp%d_start",count); 12174 snprintf(dhcpA_end,sizeof(dhcpA_end),"dhcp%d_end",count); 12175 }else{ 12176 snprintf(lanA_ifname,sizeof(lanA_ifname),"lan_ifname"); 12177 snprintf(lanA_ipaddr,sizeof(lanA_ipaddr),"lan_ipaddr"); 12178 snprintf(lanA_netmask,sizeof(lanA_netmask),"lan_netmask"); 12179 snprintf(lanA_proto,sizeof(lanA_proto),"lan_proto"); 12180 snprintf(dhcpA_start,sizeof(dhcpA_start),"dhcp_start"); 12181 snprintf(dhcpA_end,sizeof(dhcpA_end),"dhcp_end"); 12182 } 12183 12184 for (entry=0; entry < num_ifaces; entry++){ 12185 12186 if (count == entry) 12187 continue; 12188 12189 /* Skip LAN blocks that aren't enabled */ 12190 if (!vector[entry]) 12191 continue; 12192 12193 if (entry){ 12194 snprintf(lanB_ifname,sizeof(lanB_ifname),"lan%d_ifname",entry); 12195 snprintf(lanB_ipaddr,sizeof(lanB_ipaddr),"lan%d_ipaddr",entry); 12196 snprintf(lanB_netmask,sizeof(lanB_netmask),"lan%d_netmask",entry); 12197 snprintf(lanB_proto,sizeof(lanB_proto),"lan%d_proto",count); 12198 snprintf(dhcpB_start,sizeof(dhcpB_start),"dhcp%d_start",entry); 12199 snprintf(dhcpB_end,sizeof(dhcpB_end),"dhcp%d_end",entry); 12200 }else{ 12201 snprintf(lanB_ifname,sizeof(lanB_ifname),"lan_ifname"); 12202 snprintf(lanB_ipaddr,sizeof(lanB_ipaddr),"lan_ipaddr"); 12203 snprintf(lanB_netmask,sizeof(lanB_netmask),"lan_netmask"); 12204 snprintf(lanB_proto,sizeof(lanB_proto),"lan_proto"); 12205 snprintf(dhcpB_start,sizeof(dhcpB_start),"dhcp_start"); 12206 snprintf(dhcpB_end,sizeof(dhcpB_end),"dhcp_end"); 12207 } 12208 12209 value = websGetVar(wp, lanA_ipaddr , NULL); 12210 if (! value ) goto validate_lan_cgi_error; 12211 (void)inet_aton(value,&i_addr); 12212 12213 value = websGetVar(wp, lanB_ipaddr , NULL); 12214 if (! value ) goto validate_lan_cgi_error; 12215 (void)inet_aton(value,&g_addr); 12216 12217 value = websGetVar(wp, lanA_netmask , NULL); 12218 if (! value ) goto validate_lan_cgi_error; 12219 (void)inet_aton(value,&i_mask); 12220 12221 value = websGetVar(wp, lanB_netmask , NULL); 12222 if (! value ) goto validate_lan_cgi_error; 12223 (void)inet_aton(value,&g_mask); 12224 12225 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 12226 snprintf(err_msg,sizeof(err_msg), 12227 "<br>Overlapping IP address ranges:<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 12228 lanA_ipaddr,lanA_netmask,lanB_ipaddr,lanB_netmask); 12229 goto validate_lan_cgi_error; 12230 } 12231 12232 valueA = websGetVar(wp , lanA_proto , NULL); 12233 valueB = websGetVar(wp , lanB_proto , NULL); 12234 12235 /* If any of the proto vars are null skip the check */ 12236 if ((!valueA) ||(!valueB)) 12237 continue; 12238 12239 /* Overlapping DHCP range check only if DHCP is the lan proto on both*/ 12240 if (!strcmp(valueA,"dhcp") && !strcmp(valueB,"dhcp")) 12241 { 12242 value = websGetVar(wp, dhcpA_start , NULL); 12243 if (! value ) goto validate_lan_cgi_error; 12244 (void) inet_aton(value,&i_addr); 12245 12246 value = websGetVar(wp, dhcpB_start , NULL); 12247 if (! value ) goto validate_lan_cgi_error; 12248 (void) inet_aton(value,&g_addr); 12249 12250 /* Are they in the same subnetwork ? */ 12251 12252 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 12253 snprintf(err_msg,sizeof(err_msg), 12254 "<br>Overlapping DHCP start ranges<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 12255 dhcpA_start,lanA_netmask,dhcpB_start,lanB_netmask); 12256 goto validate_lan_cgi_error; 12257 } 12258 12259 value = websGetVar(wp, dhcpA_end , NULL); 12260 if (! value ) goto validate_lan_cgi_error; 12261 (void) inet_aton(value,&i_addr); 12262 12263 value = websGetVar(wp, dhcpB_end , NULL); 12264 if (! value ) goto validate_lan_cgi_error; 12265 (void) inet_aton(value,&g_addr); 12266 12267 /* Are they in the same subnetwork ? */ 12268 12269 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 12270 snprintf(err_msg,sizeof(err_msg), 12271 "<br>Overlapping DHCP end ranges<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 12272 dhcpA_end,lanA_netmask,dhcpB_end,lanB_netmask); 12273 goto validate_lan_cgi_error; 12274 } 12275 } 12276 } 12277 } 12278 12279 ret_code = 0; 12280 12281 /* The individual validation functions will set ret_code to EINVAL 12282 if an error is encountered. On success zero is returned. 12283 Validation stops on the first error encountered 12284 */ 12285 for ( count = 0; ( count < num_items && !(ret_code) ); count++){ 12286 12287 char var[64]; 12288 int entry; 12289 12290 /* Lookup template */ 12291 varname = cgi_vars[count]; 12292 v = get_var_handle(varname); 12293 12294 /* Enumerate thru list of interfaces */ 12295 if (v) 12296 for (entry=0; entry < num_ifaces; entry++){ 12297 12298 /* Skip LAN blocks that aren't enabled */ 12299 if (!vector[entry]) 12300 continue; 12301 12302 if (v->ezc_flags & WEB_IGNORE) 12303 continue; 12304 12305 if (entry && v->prefix ) 12306 snprintf(var,sizeof(var),"%s%d_%s", 12307 v->prefix,entry,&varname[strlen(v->prefix) + 1]); 12308 else 12309 snprintf(var,sizeof(var),"%s",varname); 12310 12311 value = websGetVar(wp, var, NULL); 12312 12313 if (value){ 12314 if ((!*value && v->nullok) || !v->validate) 12315 nvram_set(var, value); 12316 else 12317 v->validate(wp, value, v, var); 12318 } 12319 } 12320 } 12321 12322 12323 /* Set lanX_dhcp to static for all interfaces in router mode */ 12324 if (router_enable) 12325 for (count = 0; count < num_ifaces; count++){ 12326 char lan_dhcp[]="lanXXXXX_dhcp"; 12327 12328 /* Skip entry if the SSID is not turned on */ 12329 if (!vector[count]) 12330 continue; 12331 12332 if (count) 12333 snprintf(lan_dhcp,sizeof(lan_dhcp),"lan%d_dhcp",count); 12334 else 12335 snprintf(lan_dhcp,sizeof(lan_dhcp),"lan_dhcp"); 12336 nvram_set(lan_dhcp,"0"); 12337 12338 } 12339 12340 /* Handlers already print error messages. No need for further explanation */ 12341 if (ret_code) 12342 snprintf(err_msg,sizeof(err_msg),"Error during variable validation.<br>"); 12343 12344validate_lan_cgi_error: 12345 if (*err_msg) 12346 websWrite(wp, err_msg); 12347 12348 websBufferFlush(wp); 12349} 12350 12351static void 12352validate_cgi(webs_t wp) 12353{ 12354 struct variable *v=NULL; 12355 char *value=NULL; 12356 12357 websBufferInit(wp); 12358 if (!webs_buf) { 12359 websWrite(wp, "out of memory<br>"); 12360 websDone(wp, 0); 12361 return; 12362 } 12363 12364 12365 /* Validate and set variables in table order */ 12366 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 12367 if (!(value = websGetVar(wp, v->name, NULL))) 12368 continue; 12369 12370 if (v->ezc_flags & WEB_IGNORE) 12371 continue; 12372 12373 if ((!*value && v->nullok) || !v->validate) 12374 nvram_set(v->name, value); 12375 else 12376 v->validate(wp, value, v, NULL); 12377 } 12378 12379 websBufferFlush(wp); 12380} 12381 12382#ifdef __CONFIG_WPS__ 12383static int 12384is_wps_enabled() 12385{ 12386 int i, unit; 12387 char *ifnames, *next; 12388 char prefix[] = "wlXXXXXXXXXX_"; 12389 char name[IFNAMSIZ], os_name[IFNAMSIZ], wl_name[IFNAMSIZ]; 12390 char lan_name[IFNAMSIZ]; 12391 char tmp[100]; 12392 char *wps_mode; 12393 char *wl_radio, *wl_bss_enabled; 12394 12395 /* (LAN) */ 12396 for (i = 0; i < 256; i ++) { 12397 /* Taking care of LAN interface names */ 12398 if (i == 0) { 12399 strcpy(name, "lan_ifnames"); 12400 strcpy(lan_name, "lan"); 12401 } 12402 else { 12403 sprintf(name, "lan%d_ifnames", i); 12404 sprintf(lan_name, "lan%d", i); 12405 } 12406 12407 ifnames = nvram_get(name); 12408 if (!ifnames) 12409 continue; 12410 12411 /* Search for wl_name in ess */ 12412 foreach(name, ifnames, next) { 12413 if (nvifname_to_osifname(name, os_name, sizeof(os_name)) < 0) 12414 continue; 12415 if (wl_probe(os_name) || 12416 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))) 12417 continue; 12418 12419 /* Convert eth name to wl name */ 12420 if (osifname_to_nvifname(name, wl_name, sizeof(wl_name)) != 0) 12421 continue; 12422 12423 /* Get configured wireless address */ 12424 snprintf(prefix, sizeof(prefix), "%s_", wl_name); 12425 12426 /* Ignore radio or bss is disabled */ 12427 snprintf(tmp, sizeof(tmp), "wl%d_radio", unit); 12428 wl_radio = nvram_safe_get(tmp); 12429 wl_bss_enabled = nvram_safe_get(strcat_r(prefix, "bss_enabled", tmp)); 12430 if (strcmp(wl_radio, "1") != 0 || strcmp(wl_bss_enabled, "1") != 0) 12431 continue; 12432 if (nvram_get(strcat_r(prefix, "hwaddr", tmp)) == NULL) 12433 continue; 12434 12435 /* Enabled/ Disabled */ 12436 wps_mode = nvram_get(strcat_r(prefix, "wps_mode", tmp)); 12437 if (!wps_mode || 12438 (strcmp(wps_mode, "enabled") != 0 && 12439 strcmp(wps_mode, "enr_enabled") != 0)) { 12440 continue; 12441 } 12442 12443 /* got it enabled, wps is running */ 12444 return 1; 12445 } 12446 } 12447 12448 /* (WAN) */ 12449 for (i = 0; i < 256; i ++) { 12450 /* Taking care of WAN interface names */ 12451 if (i == 0) 12452 strcpy(name, "wan_ifnames"); 12453 else 12454 sprintf(name, "wan%d_ifnames", i); 12455 12456 ifnames = nvram_get(name); 12457 if (!ifnames) 12458 continue; 12459 12460 /* Search for wl_name in it */ 12461 foreach(name, ifnames, next) { 12462 if (nvifname_to_osifname(name, os_name, sizeof(os_name)) < 0) 12463 continue; 12464 if (wl_probe(os_name) || 12465 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))) 12466 continue; 12467 12468 /* Convert eth name to wl name */ 12469 if (osifname_to_nvifname(name, wl_name, sizeof(wl_name)) != 0) 12470 continue; 12471 12472 /* Get configured wireless address */ 12473 snprintf(prefix, sizeof(prefix), "%s_", wl_name); 12474 12475 /* Ignore radio or bss is disabled */ 12476 snprintf(tmp, sizeof(tmp), "wl%d_radio", unit); 12477 wl_radio = nvram_safe_get(tmp); 12478 wl_bss_enabled = nvram_safe_get(strcat_r(prefix, "bss_enabled", tmp)); 12479 if (strcmp(wl_radio, "1") != 0 || strcmp(wl_bss_enabled, "1") != 0) 12480 continue; 12481 if (nvram_get(strcat_r(prefix, "hwaddr", tmp)) == NULL) 12482 continue; 12483 12484 /* Enabled/ Disabled */ 12485 wps_mode = nvram_get(strcat_r(prefix, "wps_mode", tmp)); 12486 if (!wps_mode || strcmp(wps_mode, "enr_enabled") != 0) 12487 continue; 12488 12489 /* got it enabled, wps is running */ 12490 return 1; 12491 } 12492 } 12493 12494 return 0; 12495} 12496 12497static int 12498write_to_wps(int fd, char *cmd) 12499{ 12500 int n; 12501 int len; 12502 struct sockaddr_in to; 12503 12504 len = strlen(cmd)+1; 12505 12506 /* open loopback socket to communicate with wps */ 12507 memset(&to, 0, sizeof(to)); 12508 to.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 12509 to.sin_family = AF_INET; 12510 to.sin_port = htons(WPS_UI_PORT); 12511 12512 if ((n = sendto(fd, cmd, len, 0, (struct sockaddr *)&to, 12513 sizeof(struct sockaddr_in))) <0) { 12514 perror("write_to_wps: sendto failed"); 12515 } 12516 else { 12517 /* Sleep 100 ms to make sure WPS have received socket */ 12518 USLEEP(100*1000); 12519 } 12520 return n; 12521} 12522 12523static int 12524read_from_wps(int fd, char *databuf, int datalen) 12525{ 12526 int n, max_fd = -1; 12527 fd_set fdvar; 12528 struct timeval timeout; 12529 int recvBytes; 12530 struct sockaddr_in addr; 12531 socklen_t size = sizeof(struct sockaddr); 12532 12533 timeout.tv_sec = 2; 12534 timeout.tv_usec = 0; 12535 12536 FD_ZERO(&fdvar); 12537 12538 /* get ui fd */ 12539 if (fd >= 0) { 12540 FD_SET(fd, &fdvar); 12541 max_fd = fd; 12542 } 12543 12544 if (max_fd == -1) { 12545 fprintf(stderr, "wps ui utility: no fd set!\n"); 12546 return -1; 12547 } 12548 12549 n = select(max_fd + 1, &fdvar, NULL, NULL, &timeout); 12550 12551 if (n < 0) { 12552 return -1; 12553 } 12554 12555 if (n > 0) { 12556 if (fd >= 0) { 12557 if (FD_ISSET(fd, &fdvar)) { 12558 recvBytes = recvfrom(fd, databuf, datalen, 12559 0, (struct sockaddr *)&addr, &size); 12560 12561 if (recvBytes == -1) { 12562 fprintf(stderr, 12563 "wps ui utility:recv failed, recvBytes = %d\n", recvBytes); 12564 return -1; 12565 } 12566 12567 return recvBytes; 12568 } 12569 12570 return 0; 12571 } 12572 } 12573 12574 return -1; 12575} 12576 12577#define MAX_WPS_ENV_ARGS 32 12578 12579int 12580parse_wps_env(char *buf) 12581{ 12582 char *argv[MAX_WPS_ENV_ARGS] = {0}; 12583 char *value, *p, *name; 12584 int i; 12585 int unit, subunit; 12586 char nvifname[IFNAMSIZ]; 12587 12588 /* Seperate buf into argv[], we have to make sure at least one is empty */ 12589 for (i = 0, p = buf; i < MAX_WPS_ENV_ARGS-1; i++) { 12590 /* Eat white space */ 12591 while (*p == ' ') 12592 p++; 12593 if (*p == 0) 12594 goto all_found; 12595 12596 /* Save this item */ 12597 argv[i] = p; 12598 12599 /* Search until space */ 12600 while (*p != ' ' && *p) { 12601 /* Take care of doube quot */ 12602 if (*p == '\"') { 12603 char *qs, *qe; 12604 12605 qs = p; 12606 qe = strchr(p+1, '\"'); 12607 if (qe == NULL) { 12608 printf("%s:%d, unbalanced quote string!", __func__, __LINE__); 12609 argv[i] = 0; 12610 goto all_found; 12611 } 12612 12613 12614 /* Null eneded quot string and do shift */ 12615 *qe = '\0'; 12616 memmove(qs, qs+1, (int)(qe-qs)); 12617 12618 p = qe+1; 12619 break; 12620 } 12621 12622 p++; 12623 } 12624 12625 if (*p) 12626 *p++ = '\0'; 12627 } 12628 12629all_found: 12630 /* Parse message */ 12631 wps_config_command = WPS_UI_CMD_NONE; 12632 wps_method = 0; /* Add in PF #3 */ 12633 memset(wps_autho_sta_mac, 0, sizeof(wps_autho_sta_mac)); /* Add in PF #3 */ 12634 12635 for (i = 0; argv[i]; i++) { 12636 value = argv[i]; 12637 name = strsep(&value, "="); 12638 if (name) { 12639 if (!strcmp(name, "wps_config_command")) 12640 wps_config_command = atoi(value); 12641 else if (!strcmp(name, "wps_uuid")) { 12642 strncpy(wps_uuid , value, sizeof(wps_uuid) - 1); 12643 wps_uuid[sizeof(wps_uuid) - 1] = '\0'; 12644 } 12645 else if (!strcmp(name, "wps_method")) /* Add in PF #3 */ 12646 wps_method = atoi(value); 12647 else if (!strcmp(name, "wps_autho_sta_mac")) /* Add in PF #3 */ 12648 memcpy(wps_autho_sta_mac, value, sizeof(wps_autho_sta_mac)); 12649 else if (!strcmp(name, "wps_ifname")) { 12650 if (strlen(value) <=0) 12651 continue; 12652 if (osifname_to_nvifname(value, nvifname, sizeof(nvifname)) != 0) 12653 continue; 12654 12655 if (get_ifname_unit(nvifname, &unit, &subunit) == -1) 12656 continue; 12657 if (unit < 0) 12658 unit = 0; 12659 if (subunit < 0) 12660 subunit = 0; 12661 12662 if (subunit) 12663 sprintf(wps_unit, "%d.%d", unit, subunit); 12664 else 12665 sprintf(wps_unit, "%d", unit); 12666 } 12667#ifdef __CONFIG_NFC__ 12668 else if (!strcmp(name, "wps_nfc_dm_status")) 12669 wps_nfc_dm_status = atoi(value); 12670 else if (!strcmp(name, "wps_nfc_err_code")) 12671 wps_nfc_err_code = atoi(value); 12672#endif /* __CONFIG_NFC__ */ 12673 12674 } 12675 } 12676 12677 return 0; 12678} 12679 12680static int 12681get_wps_env() 12682{ 12683 int fd = -1; 12684 char databuf[257]; 12685 int datalen = sizeof(databuf); 12686 databuf[--datalen] = 0; 12687 12688 if (is_wps_enabled() == 0) 12689 return -1; 12690 12691 if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 12692 fprintf(stderr, "wps ui utility: failed to open loopback socket\n"); 12693 return -1; 12694 } 12695 12696 /* Receive response */ 12697 if (write_to_wps(fd, "GET") >= 0 && read_from_wps(fd, databuf, datalen) > 0) { 12698 parse_wps_env(databuf); 12699 } 12700 else { 12701 /* Show error message ? */ 12702 } 12703 12704 close(fd); 12705 return 0; 12706} 12707 12708 12709static int 12710set_wps_env(char *uibuf) 12711{ 12712 int wps_fd = -1; 12713 struct sockaddr_in to; 12714 int sentBytes = 0; 12715 uint32 uilen = strlen(uibuf); 12716 12717 if (is_wps_enabled() == 0) 12718 return -1; 12719 12720 if ((wps_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 12721 goto exit; 12722 } 12723 12724 /* send to WPS */ 12725 to.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 12726 to.sin_family = AF_INET; 12727 to.sin_port = htons(WPS_UI_PORT); 12728 12729 sentBytes = sendto(wps_fd, uibuf, uilen, 0, (struct sockaddr *) &to, 12730 sizeof(struct sockaddr_in)); 12731 12732 if (sentBytes != uilen) { 12733 goto exit; 12734 } 12735 12736 /* Sleep 100 ms to make sure 12737 WPS have received socket */ 12738 USLEEP(100*1000); 12739 close(wps_fd); 12740 return 0; 12741 12742exit: 12743 if (wps_fd >= 0) 12744 close(wps_fd); 12745 12746 /* Show error message ? */ 12747 return -1; 12748} 12749 12750/* Check lan index according to wl_unit */ 12751static int 12752wps_get_lan_idx() 12753{ 12754 int i; 12755 char prefix[] = "wlXXXXXXXXXX_"; 12756 char *wl_ifname, *lan_ifnames; 12757 char tmp[NVRAM_BUFSIZE]; 12758 12759 if (!make_wl_prefix(prefix,sizeof(prefix), 1, NULL)) 12760 return -1; /* Error */ 12761 12762 wl_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 12763 12764 /* find wlx_ifname in lan_ifnames */ 12765 for (i = 0; i< MAX_NVPARSE; i++) { 12766 if (i == 0) 12767 snprintf(tmp, sizeof(tmp), "lan_ifnames"); 12768 else 12769 snprintf(tmp, sizeof(tmp), "lan%d_ifnames", i); 12770 12771 lan_ifnames = nvram_get(tmp); 12772 if (lan_ifnames && find_in_list(lan_ifnames, wl_ifname)) 12773 break; 12774 } 12775 12776 if (i == MAX_NVPARSE) 12777 return -1; 12778 12779 return i; 12780} 12781 12782static int 12783wps_get_oob_name(char *name, int len) 12784{ 12785 int i; 12786 char prefix[] = "wlXXXXXXXXXX_"; 12787 char wl_mode[]="wlXXXXXXXXXX_mode"; 12788 char *mode; 12789 char *wl_ifname, *lan_ifnames; 12790 char tmp[NVRAM_BUFSIZE]; 12791 12792 if (!make_wl_prefix(prefix,sizeof(prefix), 1, NULL)) { 12793 return -1; 12794 } 12795 12796 snprintf(wl_mode,sizeof(wl_mode),"%smode",prefix); 12797 mode = nvram_safe_get(wl_mode); 12798 if (strcmp(mode, "ap") == 0) { 12799 /* For AP */ 12800 wl_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 12801 12802 /* find wlx_ifname in lan_ifnames */ 12803 for (i = 0; i< MAX_NVPARSE; i++) { 12804 if (i == 0) 12805 snprintf(tmp, sizeof(tmp), "lan_ifnames"); 12806 else 12807 snprintf(tmp, sizeof(tmp), "lan%d_ifnames", i); 12808 12809 lan_ifnames = nvram_get(tmp); 12810 if (lan_ifnames && find_in_list(lan_ifnames, wl_ifname)) 12811 break; 12812 } 12813 12814 if (i == MAX_NVPARSE) 12815 return -1; 12816 12817 if (i == 0) 12818 snprintf(name, len, "lan_wps_oob"); 12819 else 12820 snprintf(name, len, "lan%d_wps_oob", i); 12821 } 12822 else { 12823 /* For STA */ 12824 snprintf(name, len, "%swps_oob", prefix); 12825 } 12826 return 0; 12827} 12828 12829static void 12830wps_disable_oob() 12831{ 12832 char name[NVRAM_BUFSIZE]; 12833 12834 if (wps_get_oob_name(name, NVRAM_BUFSIZE) == -1) 12835 return; 12836 nvram_set(name, "disabled"); 12837} 12838 12839static void 12840wps_enable_oob() 12841{ 12842 char name[NVRAM_BUFSIZE]; 12843#ifdef __CONFIG_NFC__ 12844#define WPS_CONFMET_EXT_NFC_TOK 0x0010 12845 char *value, tmp[16]; 12846 unsigned short config_method; 12847#endif 12848 12849 if (wps_get_oob_name(name, NVRAM_BUFSIZE) == -1) 12850 return; 12851 nvram_set(name, "enabled"); 12852 12853#ifdef __CONFIG_NFC__ 12854 /* Remove the external NFC Token bit. */ 12855 value = nvram_get("wps_config_method"); 12856 if (value) { 12857 config_method = strtoul(value, NULL, 16); 12858 if (config_method & WPS_CONFMET_EXT_NFC_TOK) { 12859 config_method &= ~WPS_CONFMET_EXT_NFC_TOK; 12860 sprintf(tmp, "0x%x", config_method); 12861 nvram_set("wps_config_method", tmp); 12862 } 12863 } 12864#endif /* __CONFIG_NFC__ */ 12865} 12866 12867/* Check current wl_unit interfave wps_reg statuc */ 12868static int 12869wps_is_reg() 12870{ 12871 int lan_idx; 12872 char tmp[NVRAM_BUFSIZE]; 12873 12874 lan_idx = wps_get_lan_idx(); 12875 if (lan_idx == -1) 12876 return 0; 12877 12878 /* found, get lanx_wps_reg */ 12879 if (lan_idx == 0) 12880 snprintf(tmp, sizeof(tmp), "lan_wps_reg"); 12881 else 12882 snprintf(tmp, sizeof(tmp), "lan%d_wps_reg", lan_idx); 12883 12884 if (nvram_match(tmp, "enabled")) 12885 return 1; 12886 12887 return 0; 12888} 12889 12890/* Check current wl_unit interfave wps_oob status */ 12891static int 12892wps_is_oob() 12893{ 12894 char tmp[NVRAM_BUFSIZE]; 12895 12896 /* WPS is disabled */ 12897 if (wps_get_oob_name(tmp, NVRAM_BUFSIZE) == -1) 12898 return 0; 12899 /* 12900 * OOB: enabled 12901 * Configured: disabled 12902 */ 12903 if (nvram_match(tmp, "disabled")) 12904 return 0; 12905 12906 return 1; 12907} 12908static int wps_check_pin(char *pin, char *value) 12909{ 12910 12911 /* add in PF#3, session 7.4.3 "1234-5670" */ 12912 if (strlen(value) == 9 && 12913 (value[4] < '0' || value[4] > '9')) { 12914 /* remove '-' */ 12915 memcpy(pin, value, 4); 12916 memcpy(pin+4, value+5, 4); 12917 } 12918 else { 12919 strncpy(pin, value, 8); 12920 } 12921 12922 /* pin validation */ 12923 if (wl_wpsPincheck(pin)) 12924 return -1; 12925 return 0; 12926} 12927 12928static int wps_get_credentials(webs_t wp, char *uibuf, int uilen) 12929{ 12930 char *value; 12931 int wps_akm = 0; 12932 12933 /* credential setting */ 12934 if ((value = websGetVar(wp, "wps_ssid", NULL))) 12935 { 12936 uilen += sprintf(uibuf + uilen, "wps_ssid=\"%s\" ", value); 12937 } 12938 else { 12939 websWrite(wp, "Unable to get SSID."); 12940 return -1; 12941 } 12942 12943 /* Authentication Type */ 12944 if ((value = websGetVar(wp, "wps_akm", NULL))) 12945 { 12946 if (!strlen(value)) 12947 uilen += sprintf(uibuf + uilen, "wps_akm=\"\" "); 12948 else { 12949 uilen += sprintf(uibuf + uilen, "wps_akm=\"%s\" ", value); 12950 wps_akm = 1; 12951 } 12952 } 12953 else { 12954 websWrite(wp, "Unable to get Authentication Type."); 12955 return -1; 12956 } 12957 12958 /* Encryption Type */ 12959 if ((value = websGetVar(wp, "wps_crypto", NULL))) 12960 { 12961 uilen += sprintf(uibuf + uilen, "wps_crypto=\"%s\" ", value); 12962 } 12963 else { 12964 if (wps_akm) { 12965 websWrite(wp, "Unable to get Encryption Type."); 12966 return -1; 12967 } 12968 } 12969 12970 /* WPA passphrase */ 12971 if ((value = websGetVar(wp, "wps_psk", NULL))) 12972 { 12973 uilen += sprintf(uibuf + uilen, "wps_psk=\"%s\" ", value); 12974 } 12975 else { 12976 if (wps_akm) { 12977 websWrite(wp, "Unable to get Passphrase Key."); 12978 return -1; 12979 } 12980 } 12981 12982 return uilen; 12983} 12984static int wps_cgi(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 12985 char_t *url, char_t *path, char_t *query) 12986{ 12987 char *value = NULL, *action_mode = NULL; 12988 char *wps_ssid = NULL, *wps_akm = NULL, *wps_crypto = NULL, *wps_psk = NULL; 12989 char tmp[256]; 12990 char nvifname[IFNAMSIZ], osifname[IFNAMSIZ]; 12991 char pin[9] = {0}; 12992 char uibuf[1024] = "SET "; 12993 int uilen = 4; 12994 bool b_wps_version2 = FALSE; 12995 char prefix[] = "wlXXXXXXXXXX_"; 12996 int len; 12997 int akm = 1; 12998 12999 action_mode = websGetVar(wp, "action", NULL); 13000 13001 if (action_mode == NULL) { 13002 websError(wp, 400, "action mode is not specified\n"); 13003 return -1; 13004 } 13005 13006 if (!make_wl_prefix(prefix, sizeof(prefix), 1, NULL)) { 13007 websError(wp, 400, "unit number variable doesn't exist\n"); 13008 return -1; 13009 } 13010 13011 if (!strcmp(action_mode, "Reset To OOB")) { 13012 websWrite(wp, "Reset to OOB ..."); 13013 wps_enable_oob(); 13014 13015 snprintf(tmp, sizeof(tmp), "%sssid", prefix); 13016 nvram_set(tmp, nvram_default_get("wl_ssid")); 13017 13018 snprintf(tmp, sizeof(tmp), "%sakm", prefix); 13019 nvram_set(tmp, nvram_default_get("wl_akm")); 13020 13021 snprintf(tmp, sizeof(tmp), "%scrypto", prefix); 13022 nvram_set(tmp, nvram_default_get("wl_crypto")); 13023 13024 snprintf(tmp, sizeof(tmp), "%swpa_psk", prefix); 13025 nvram_set(tmp, nvram_default_get("wl_wpa_psk")); 13026 nvram_commit(); 13027 action = RESTART; 13028 } 13029 else if (!strcmp(action_mode, "Save Credentials")) { 13030 websWrite(wp, "Validating values..."); 13031 13032 if (!(wps_ssid = websGetVar(wp, "wps_ssid", NULL))) { 13033 websWrite(wp, "Unable to get WPS SSID.\n"); 13034 return -1; 13035 } 13036 13037 if ((wps_akm = websGetVar(wp, "wps_akm", NULL))) { 13038 if (!strlen(wps_akm)) 13039 akm = 0; 13040 } 13041 else { 13042 websWrite(wp, "Unable to get Authentication Type.\n"); 13043 return -1; 13044 } 13045 13046 if (akm) { 13047 if (!(wps_crypto = websGetVar(wp, "wps_crypto", NULL))) { 13048 websWrite(wp, "Unable to get Encryption Type.\n"); 13049 return -1; 13050 } 13051 13052 if (!(wps_psk = websGetVar(wp, "wps_psk", NULL))) { 13053 websWrite(wp, "Unable to get WPA passphrase.\n"); 13054 return -1; 13055 } 13056 13057 len = strlen(wps_psk); 13058 if (len == 64) { 13059 char *c; 13060 for (c = wps_psk; *c; c++) { 13061 if (!isxdigit((int) *c)) { 13062 websWrite(wp, "Invalid <b>WPA passphase</b>: character %c is not a hexadecimal digit<br>", *c); 13063 return -1; 13064 } 13065 } 13066 } else if (len < 8 || len > 63) { 13067 websWrite(wp, "Invalid <b>WPA passphase</b>: must be between 8 and 63 ASCII characters or 64 hexadecimal digits<br>"); 13068 return -1; 13069 } 13070 } 13071 13072 action = RESTART; 13073 /* now we can apply new ssid/akm/crypto and psk */ 13074 snprintf(tmp, sizeof(tmp), "%sssid", prefix); 13075 nvram_set(tmp, wps_ssid); 13076 nvram_set("wl_ssid", wps_ssid); 13077 snprintf(tmp, sizeof(tmp), "%sakm", prefix); 13078 nvram_set(tmp, wps_akm); 13079 nvram_set("wl_akm", wps_akm); 13080 if (akm) { 13081 snprintf(tmp, sizeof(tmp), "%scrypto", prefix); 13082 nvram_set(tmp, wps_crypto); 13083 nvram_set("wl_crypto", wps_crypto); 13084 snprintf(tmp, sizeof(tmp), "%swpa_psk", prefix); 13085 nvram_set(tmp, wps_psk); 13086 nvram_set("wl_wpa_psk", wps_psk); 13087 } 13088 13089 wps_disable_oob(); 13090 websWrite(wp, "done<br>"); 13091 websWrite(wp, "Committing values..."); 13092 nvram_set("is_modified", "1"); 13093 nvram_set("is_default", "0"); 13094 nvram_commit(); 13095 websWrite(wp, "done<br>"); 13096 } 13097 /* WPS AP want to Add Enrollee */ 13098 else if (!strcmp(action_mode, "Add Enrollee")) { 13099 13100 websWrite(wp, "validate variable...\n"); 13101 wps_action = WPS_UI_ACT_ADDENROLLEE; 13102 websWrite(wp, "WPS is preparing to Add Enrollee...\n"); 13103 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", wps_action); 13104 13105 uilen = wps_get_credentials(wp, uibuf, uilen); 13106 if (uilen == -1) 13107 return -1; 13108 13109 /* get sta pin, if pin value is empty the user want to use PBC method. */ 13110 if ((value = websGetVar(wp, "wps_sta_pin", NULL))) { 13111 if (value[0] == 0) { 13112 wps_method = WPS_UI_METHOD_PBC; 13113 strncpy(pin, "00000000", 8); 13114 uilen += sprintf(uibuf + uilen, "wps_pbc_method=\"%d\" ", WPS_UI_PBC_SW); 13115 } 13116 else { 13117 wps_method = WPS_UI_METHOD_PIN; 13118 13119 /* check sta pin */ 13120 if (wps_check_pin(pin, value)){ 13121 websWrite(wp, "Warning: PIN checksum is invalid.\n"); 13122 return -1; 13123 } 13124 13125 /* WSC 2.0, get authorized mac */ 13126 value = websGetVar(wp, "wps_autho_sta_mac", NULL); 13127 if (value && *value) { 13128 unsigned char hwaddr[6]; 13129 13130 /* Check for bad, multicast, broadcast, or null address */ 13131 if (!ether_atoe(value, hwaddr) || 13132 (hwaddr[0] & 1) || 13133 (hwaddr[0] & hwaddr[1] & hwaddr[2] & 13134 hwaddr[3] & hwaddr[4] & hwaddr[5]) == 0xff || 13135 (hwaddr[0] | hwaddr[1] | hwaddr[2] | 13136 hwaddr[3] | hwaddr[4] | hwaddr[5]) == 0x00) { 13137 websWrite(wp, "Invalid <b>Authorized Station MAC</b> " 13138 "%s: not a MAC address\n", value); 13139 action = NOTHING; 13140 return -1; 13141 } 13142 else 13143 uilen += sprintf(uibuf + uilen, "wps_autho_sta_mac=\"%s\" ", value); 13144 } 13145 13146 } 13147 uilen += sprintf(uibuf + uilen, "wps_sta_pin=\"%s\" ", pin); 13148 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", wps_method); 13149 } 13150 websWrite(wp, "OK"); 13151 13152 nvram_set("wps_proc_status", "0"); 13153 strncpy(wps_unit, nvram_safe_get("wl_unit"), sizeof(wps_unit)); 13154 wps_unit[sizeof(wps_unit)-1] = '\0'; 13155 13156 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_START); 13157 13158 sprintf(nvifname, "wl%s", wps_unit); 13159 (void)nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13160 13161 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13162 set_wps_env(uibuf); 13163 } 13164 else if (!strcmp(action_mode, "Start")) 13165 { 13166 int wps_config_command = WPS_UI_CMD_START; 13167 13168 websWrite(wp, "validate variable...\n"); 13169 13170 if (!(value = websGetVar(wp, "wps_action", NULL))) { 13171 websWrite(wp, "Unable to get wps action.\n"); 13172 return -1; 13173 } 13174 else { 13175 if (!strcmp(value, "Enroll")) 13176 wps_action = WPS_UI_ACT_ENROLL; 13177 else if (!strcmp(value, "ConfigAP")) 13178 wps_action = WPS_UI_ACT_STA_CONFIGAP; 13179 else if (!strcmp(value, "GetAPConfig")) 13180 wps_action = WPS_UI_ACT_STA_GETAPCONFIG; 13181 13182 sprintf(tmp, "%d", wps_action); 13183 nvram_set("wps_action", tmp); 13184 websWrite(wp, "WPS is preparing to %s...\n", value); 13185 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", wps_action); 13186 } 13187 13188 if (wps_action == WPS_UI_ACT_ENROLL) 13189 { 13190 value = websGetVar(wp, "wps_method", NULL); 13191 13192 if (!strcmp(value, "PIN")) 13193 wps_method = WPS_UI_METHOD_PIN; 13194 else if (!strcmp(value, "PBC")) 13195 { 13196 wps_method = WPS_UI_METHOD_PBC; 13197 strncpy(pin, "00000000", 8); 13198 uilen += sprintf(uibuf + uilen, "wps_pbc_method=\"%d\" ", WPS_UI_PBC_SW); 13199 } 13200#ifdef __CONFIG_NFC__ 13201 else if (!strcmp(value, "NFC")) { 13202 wps_method = WPS_UI_METHOD_NFC_PW; 13203 wps_config_command = WPS_UI_CMD_NFC_WR_PW; 13204 websWrite(wp, "<br><br>Please place your NFC token now!<br>\n"); 13205 /* Station PIN comes from NFC Password */ 13206 uilen += sprintf(uibuf + uilen, "wps_sta_pin=\"NFC_PW\" "); 13207 } 13208#endif 13209 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", wps_method); 13210 13211 } /* WPS_UI_ACT_ENROLL */ 13212 13213 if (wps_action == WPS_UI_ACT_STA_CONFIGAP) { 13214 uilen = wps_get_credentials(wp, uibuf, uilen); 13215 if (uilen < 0) 13216 return -1; 13217 } 13218 13219 if (wps_action == WPS_UI_ACT_STA_CONFIGAP || 13220 wps_action == WPS_UI_ACT_STA_GETAPCONFIG) { 13221 wps_method = WPS_UI_METHOD_PIN; 13222#ifdef __CONFIG_NFC__ 13223 value = websGetVar(wp, "wps_method", NULL); 13224 13225 if (!strcmp(value, "PIN")) 13226 wps_method = WPS_UI_METHOD_PIN; 13227 else if (!strcmp(value, "NFC")) { 13228 wps_method = WPS_UI_METHOD_NFC_PW; 13229 wps_config_command = WPS_UI_CMD_NFC_RD_PW; 13230 websWrite(wp, "<br><br>Please place your NFC password token now!<br>\n"); 13231 /* AP PIN comes from NFC Password */ 13232 uilen += sprintf(uibuf + uilen, "wps_stareg_ap_pin=\"NFC_PW\" "); 13233 } 13234#endif 13235 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", wps_method); 13236 13237 /* get AP pin */ 13238 if (!strcmp(value, "PIN")) { 13239 if ((value = websGetVar(wp, "wps_ap_pin", NULL))) 13240 if (wps_check_pin(pin, value)) { 13241 websWrite(wp, "Input AP PIN is invalidated."); 13242 return -1; 13243 } 13244 uilen += sprintf(uibuf + uilen, "wps_stareg_ap_pin=\"%s\" ", pin); 13245 } 13246 } 13247 13248 if ((wps_action == WPS_UI_ACT_ENROLL && 13249 (wps_method == WPS_UI_METHOD_PIN || 13250#ifdef __CONFIG_NFC__ 13251 wps_method == WPS_UI_METHOD_NFC_PW || 13252#endif 13253 FALSE)) || 13254 wps_action == WPS_UI_ACT_STA_CONFIGAP || 13255 wps_action == WPS_UI_ACT_STA_GETAPCONFIG) { 13256 wps_ap_list_info_t *ap; 13257 int wps_ap_index; 13258 char eastr[ETHER_ADDR_STR_LEN]; 13259 13260 13261 if ((value = websGetVar(wp, "wps_ap_list", NULL)) == NULL || 13262 (wps_ap_index = atoi(value)) == -1 || 13263 (ap = wps_enr_get_selected_ap(wps_ap_index)) == NULL) 13264 { 13265 websWrite(wp, "Unable to get selected WPS AP."); 13266 return -1; 13267 } 13268 13269 selected_ap = ap; 13270 if (wps_action == WPS_UI_ACT_STA_CONFIGAP || 13271 wps_action == WPS_UI_ACT_STA_GETAPCONFIG) 13272 uilen += sprintf(uibuf + uilen, "wps_scstate=\"%s\" ", ap->scstate ? "configured" : "unconfigured"); 13273 13274 uilen += sprintf(uibuf + uilen, "wps_enr_ssid=\"%s\" ", ap->ssid); 13275 uilen += sprintf(uibuf + uilen, "wps_enr_bssid=\"%s\" ", ether_etoa(ap->BSSID, eastr)); 13276 uilen += sprintf(uibuf + uilen, "wps_enr_wsec=\"%d\" ", ap->wep); 13277 } 13278 websWrite(wp, "OK"); 13279 13280 nvram_set("wps_proc_status", "0"); 13281 strncpy(wps_unit, nvram_safe_get("wl_unit"), sizeof(wps_unit)); 13282 wps_unit[sizeof(wps_unit)-1] = '\0'; 13283 13284 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", wps_config_command); 13285 13286 sprintf(nvifname, "wl%s", wps_unit); 13287 (void)nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13288 13289 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13290 set_wps_env(uibuf); 13291 nvram_commit(); 13292 } /* start */ 13293 else if (!strcmp(action_mode, "Rescan")) { 13294 websWrite(wp, "Re-Scanning WPS supported AP(s)..."); 13295 wl_wpsEnrScan(); 13296 websWrite(wp, "OK"); 13297 } 13298 /* WPS PBC push again, Add in PF #3 */ 13299 else if (!strcmp(action_mode, "PBC Again")) { 13300 13301 websWrite(wp, "validate variable...\n"); 13302 13303 /* WSC 2.0, support WPS V2 or not */ 13304 if (strcmp(nvram_safe_get("wps_version2"), "enabled") == 0) 13305 b_wps_version2 = TRUE; 13306 if ((value = websGetVar(wp, "wps_action", NULL)) == NULL) { 13307 websError(wp, 400, "wps_action does not exist\n"); 13308 return -1; 13309 } 13310 if (strcmp(value, "AddEnrollee") == 0) { 13311 13312 /* Must in AddEnrollee in PBC method */ 13313 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", WPS_UI_METHOD_PBC); 13314 13315 /* WSC 2.0, get authorized mac, get by wps process itself */ 13316 if (b_wps_version2 && strlen(wps_autho_sta_mac)) 13317 uilen += sprintf(uibuf + uilen, "wps_autho_sta_mac=\"%s\" ", wps_autho_sta_mac); 13318 uilen += sprintf(uibuf + uilen, "wps_sta_pin=\"00000000\" "); /* PBC */ 13319 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_ADDENROLLEE); 13320 13321 websWrite(wp, "OK"); 13322 nvram_set("wps_proc_status", "0"); 13323 strncpy(wps_unit, nvram_safe_get("wl_unit"), sizeof(wps_unit)); 13324 wps_unit[sizeof(wps_unit)-1] = '\0'; 13325 13326 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_START); 13327 13328 sprintf(nvifname, "wl%s", wps_unit); 13329 (void)nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13330 13331 uilen += sprintf(uibuf + uilen, "wps_pbc_method=\"%d\" ", WPS_UI_PBC_SW); 13332 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13333 } 13334 else if (strcmp(value, "Enroll") == 0){ 13335 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", WPS_UI_METHOD_PBC); 13336 13337 websWrite(wp, "OK"); 13338 nvram_set("wps_proc_status", "0"); 13339 strncpy(wps_unit, nvram_safe_get("wl_unit"), sizeof(wps_unit)); 13340 wps_unit[sizeof(wps_unit)-1] = '\0'; 13341 13342 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_ENROLL); 13343 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_START); 13344 13345 sprintf(nvifname, "wl%s", wps_unit); 13346 (void)nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13347 13348 uilen += sprintf(uibuf + uilen, "wps_pbc_method=\"%d\" ", WPS_UI_PBC_SW); 13349 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13350 13351 13352 uilen += sprintf(uibuf + uilen, "wps_enr_ssid=\"%s\" ", nvram_safe_get("wps_enr_ssid")); 13353 uilen += sprintf(uibuf + uilen, "wps_enr_bssid=\"%s\" ", nvram_safe_get("wps_enr_bssid")); 13354 uilen += sprintf(uibuf + uilen, "wps_enr_wsec=\"%s\" ", nvram_safe_get("wps_enr_wsec")); 13355 printf("\n*****\n%s\n", uibuf); 13356 } 13357 set_wps_env(uibuf); 13358 } 13359 /* WPS key generate */ 13360 else if (!strcmp(action_mode, "Generate")) { 13361 char devPwd[12]; 13362 13363 websWrite(wp, "Generating WPS PIN number..."); 13364 wl_wpsPinGen(devPwd); 13365 nvram_set("wps_device_pin", devPwd); 13366 nvram_commit(); 13367 websWrite(wp, "OK"); 13368 /* Restart for WPS process take the new PIN */ 13369 action = RESTART; 13370 } 13371 /* WPS stop */ 13372 else if (!strcmp(action_mode, "STOPWPS")) { 13373 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_STOP); 13374 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_NONE); 13375 set_wps_env(uibuf); 13376 websWrite(wp, "WPS process stopped"); 13377 } 13378#ifdef __CONFIG_NFC__ 13379 /* NFC write configuration */ 13380 else if (!strcmp(action_mode, "NFC Write Configuration")) { 13381 websWrite(wp, "Please place your NFC token now!"); 13382 13383 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13384 sprintf(nvifname, "wl%s", wps_unit); 13385 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13386 13387 /* Use UI credential */ 13388 uilen = wps_get_credentials(wp, uibuf, uilen); 13389 if (uilen < 0) 13390 return -1; 13391 13392 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13393 13394 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_WR_CFG); 13395 13396 set_wps_env(uibuf); 13397 } 13398 /* NFC read configuration */ 13399 else if (!strcmp(action_mode, "NFC Read Configuration")) { 13400 websWrite(wp, "Please place your configured NFC token now!"); 13401 13402 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13403 sprintf(nvifname, "wl%s", wps_unit); 13404 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13405 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13406 13407 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_RD_CFG); 13408 13409 set_wps_env(uibuf); 13410 } 13411 else if (!strcmp(action_mode, "Stop NFC Write")){ 13412 websWrite(wp, "Stopping NFC writing...."); 13413 13414 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13415 sprintf(nvifname, "wl%s", wps_unit); 13416 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13417 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13418 13419 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_STOP); 13420 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_NONE); 13421 13422 set_wps_env(uibuf); 13423 } 13424 else if (!strcmp(action_mode, "Stop NFC Read")){ 13425 websWrite(wp, "Stopping NFC reading...."); 13426 13427 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13428 sprintf(nvifname, "wl%s", wps_unit); 13429 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13430 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13431 13432 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_STOP); 13433 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_NONE); 13434 13435 set_wps_env(uibuf); 13436 } 13437 else if (!strcmp(action_mode, "NFC Add Enrollee")) { 13438 websWrite(wp, "Please place your NFC password token now!"); 13439 13440 /* Station PIN comes from NFC Password */ 13441 uilen += sprintf(uibuf + uilen, "wps_sta_pin=\"NFC_PW\" "); 13442 13443 wps_action = WPS_UI_ACT_ADDENROLLEE; 13444 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", wps_action); 13445 13446 wps_method = WPS_UI_METHOD_NFC_PW; 13447 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", wps_method); 13448 13449 uilen = wps_get_credentials(wp, uibuf, uilen); 13450 if (uilen == -1) 13451 return -1; 13452 13453 nvram_set("wps_proc_status", "0"); 13454 13455 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13456 sprintf(nvifname, "wl%s", wps_unit); 13457 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13458 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13459 13460 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_RD_PW); 13461 13462 set_wps_env(uibuf); 13463 } 13464 else if (!strcmp(action_mode, "NFC Config AP")) { 13465 websWrite(wp, "Please place your NFC token now!"); 13466 13467 /* API PIN comes from NFC Password, leverage wps_stareg_ap_pin */ 13468 uilen += sprintf(uibuf + uilen, "wps_stareg_ap_pin=\"NFC_PW\" "); 13469 13470 wps_action = WPS_UI_ACT_CONFIGAP; 13471 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", wps_action); 13472 13473 wps_method = WPS_UI_METHOD_NFC_PW; 13474 uilen += sprintf(uibuf + uilen, "wps_method=\"%d\" ", wps_method); 13475 13476 uilen = wps_get_credentials(wp, uibuf, uilen); 13477 if (uilen == -1) 13478 return -1; 13479 13480 nvram_set("wps_proc_status", "0"); 13481 13482 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13483 sprintf(nvifname, "wl%s", wps_unit); 13484 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13485 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13486 13487 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_WR_PW); 13488 13489 set_wps_env(uibuf); 13490 } 13491 /* NFC hand over selector */ 13492 else if (!strcmp(action_mode, "NFC Hand Over As Selecotr")) { 13493 websWrite(wp, "Please place your NFC portable device now!"); 13494 13495 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13496 sprintf(nvifname, "wl%s", wps_unit); 13497 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13498 13499 /* Use UI credential */ 13500 uilen = wps_get_credentials(wp, uibuf, uilen); 13501 if (uilen < 0) 13502 return -1; 13503 13504 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13505 13506 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_HO_S); 13507 13508 set_wps_env(uibuf); 13509 } 13510 /* NFC hand over requester */ 13511 else if (!strcmp(action_mode, "NFC Hand Over As Requester")) { 13512 websWrite(wp, "Please place your NFC device to AP now!"); 13513 13514 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13515 sprintf(nvifname, "wl%s", wps_unit); 13516 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13517 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13518 13519 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_HO_R); 13520 13521 set_wps_env(uibuf); 13522 } 13523 else if (!strcmp(action_mode, "Stop NFC Hand Over")){ 13524 websWrite(wp, "Stopping NFC Hand Over...."); 13525 13526 strcpy(wps_unit, nvram_safe_get("wl_unit")); 13527 sprintf(nvifname, "wl%s", wps_unit); 13528 nvifname_to_osifname(nvifname, osifname, sizeof(osifname)); 13529 uilen += sprintf(uibuf + uilen, "wps_ifname=\"%s\" ", osifname); 13530 13531 uilen += sprintf(uibuf + uilen, "wps_config_command=\"%d\" ", WPS_UI_CMD_NFC_STOP); 13532 uilen += sprintf(uibuf + uilen, "wps_action=\"%d\" ", WPS_UI_ACT_NONE); 13533 13534 set_wps_env(uibuf); 13535 } 13536#endif /* __CONFIG_NFC__ */ 13537/* 13538*/ 13539#ifdef __CONFIG_WFI__ 13540 else if (!strcmp(action_mode, "Invite")) 13541 { 13542 char *invite_name=NULL, *invite_mac=NULL, *invite_unit=NULL; 13543 13544 action = NOTHING; 13545 websWrite(wp, "Validating values..."); 13546 13547 invite_name = websGetVar(wp, "invite_name", ""); 13548 invite_mac = websGetVar(wp, "invite_mac", ""); 13549 invite_unit = nvram_safe_get("wl_unit"); 13550 printf (" Inviting %s(%s) to %s ...\n", invite_mac, invite_name, invite_unit); 13551 13552 websWrite(wp, "done<br>"); 13553 13554 websWrite(wp, "Committing values..."); 13555 websWrite(wp, "done<br>"); 13556 13557 websWrite(wp, "Inviting the STA...<p>"); 13558 13559 /* Issue WFI Invite command */ 13560 { 13561 int i; 13562 char acComamnd[64]; 13563 13564 for (i = 0; i < 3; i++) { 13565 if (nvram_match(WPSM_WFI_CMD_NVNAME, "")) 13566 break; 13567 SLEEP (1); 13568 } 13569 sprintf(acComamnd, "invite %s %s%s", invite_unit, invite_mac, invite_name); 13570 nvram_set(WPSM_WFI_CMD_NVNAME, acComamnd); 13571 } 13572 13573 nvram_set("wfi_count", "120"); 13574 13575 if (nvram_match("wfi_pinmode", "1")){ /* wfi_pinmode manual */ 13576 nvram_unset("wps_sta_pin"); 13577 nvram_set("wfi_manual_pin", "0"); 13578 } 13579 13580 /* 13581 * redirect the page to "cancelinvite.aps", 13582 * to allow user cancel WFI or Enter PIN manually 13583 */ 13584 websWrite(wp, "<script type=\"text/javascript\">\n"); 13585 websWrite(wp, "<!--\n"); 13586 websWrite(wp, "window.location = \"%s\"\n", "cancelinvite.asp"); 13587 websWrite(wp, "//-->\n"); 13588 websWrite(wp, "</script>\n"); 13589 13590 websFooter(wp); 13591 websDone(wp, 200); 13592 return 1; 13593 } 13594 else if (!strcmp(action_mode, "Cancel")) 13595 { 13596 printf ("Cancel invitation!\n"); 13597 /* Issue WFI command */ 13598 { 13599 int i; 13600 13601 for (i = 0; i < 3; i++) { 13602 if (nvram_match(WPSM_WFI_CMD_NVNAME, "")) 13603 break; 13604 SLEEP (1); 13605 } 13606 nvram_set(WPSM_WFI_CMD_NVNAME, "cancel"); 13607 for (i = 0; i < 3; i++) { 13608 SLEEP(1); 13609 if (nvram_match(WPSM_WFI_CMD_NVNAME, "")) 13610 break; 13611 } 13612 } 13613 13614 action = NOTHING; 13615 13616 websWrite(wp, "<p>Action is canceled <p>\n"); 13617 websWrite(wp, "<script type=\"text/javascript\">\n"); 13618 websWrite(wp, "<!--\n"); 13619 websWrite(wp, "window.location = \"%s\"\n", "invite.asp"); 13620 websWrite(wp, "//-->\n"); 13621 websWrite(wp, "</script>\n"); 13622 13623 websFooter(wp); 13624 websDone(wp, 200); 13625 return 1; 13626 } 13627 else if (!strcmp(action_mode, "Check")) 13628 { 13629 char *wfi_count=NULL, *wfi_error=NULL; 13630 int count, error_code=0, flag= -1; 13631 13632 wfi_count = websGetVar(wp, "count", ""); 13633 if (wfi_count) { 13634 count = atoi(wfi_count); 13635 if (count >= 0) 13636 { 13637 /* Check wps_config_command value to see if the action is finished */ 13638 if (nvram_match("wfi_status", "0")){ /* Invite Done */ 13639 wfi_error = nvram_get("wfi_error"); 13640 if (wfi_error && *wfi_error){ 13641 error_code = atoi(wfi_error); 13642 printf(" get error_code = %d\n", error_code); 13643 switch (error_code){ 13644 case 0 : 13645 flag = 0; /* No error */ 13646 break; 13647 case 1 : 13648 flag = 1; /* Time out */ 13649 break; 13650 case 2 : 13651 flag = 2; /* STA rejected the invite */ 13652 break; 13653 case 3 : 13654 flag = 3; /* Cancelled */ 13655 break; 13656 default: 13657 flag = 4; /* WPS Error */ 13658 break; 13659 } 13660 } 13661 } 13662 else{ /* 1 : Inviting, 2: WPS in progress */ 13663 nvram_set("wfi_count", wfi_count); 13664 } 13665 } 13666 else 13667 flag=1; 13668 } 13669 else 13670 flag=1; 13671 13672 if (flag >= 0) { 13673 /* Invite Done, redirect the page to "invite.asp */ 13674 if (flag == 0) { 13675 /* Successful */ 13676 printf("Invite successful.\n"); 13677 websWrite(wp, " Invite successful.\n"); 13678 } 13679 else if (flag == 1){ 13680 /* Time out */ 13681 printf("Time out...\n"); 13682 websWrite(wp, " The station did not respond.\n"); 13683 } 13684 else if (flag == 2){ 13685 /* STA rejected the invite */ 13686 websWrite(wp, " The station rejected the invitation.\n"); 13687 } 13688 else if (flag == 3){ 13689 websWrite(wp, " Cancelled.\n"); 13690 } 13691 else 13692 websWrite(wp, " WPS Failed.\n"); 13693 websWrite(wp, (char_t *) apply_footer, "invite.asp"); 13694 websFooter(wp); 13695 websDone(wp, 200); 13696 13697 return 1; 13698 } 13699 else { 13700 /* Still in progress, redirect the page to "cancelinvite.aps", to allow user cancel WFI */ 13701 /* redirect the page to "cancelinvite.aps" or "invite.asp, to allow user cancel WFI */ 13702 websWrite(wp, "<script type=\"text/javascript\">\n"); 13703 websWrite(wp, "<!--\n"); 13704 websWrite(wp, "window.location = \"%s\"\n", "cancelinvite.asp"); 13705 websWrite(wp, "//-->\n"); 13706 websWrite(wp, "</script>\n"); 13707 13708 websFooter(wp); 13709 websDone(wp, 200); 13710 return 1; 13711 } 13712 } 13713 else if (!strcmp(action_mode, "Enter")) { 13714 char *wps_sta_pin=NULL; 13715 13716 wps_sta_pin = websGetVar(wp, "wps_sta_pin", ""); 13717 13718 nvram_set("wps_sta_pin", wps_sta_pin); 13719 nvram_set("wfi_manual_pin", "1"); 13720 13721 //todo : Set PIN for WFI 13722 // 13723 13724 action = NOTHING; 13725 } 13726#endif /* __CONFIG_WFI__ */ 13727/* 13728*/ 13729 return 1; 13730 13731} 13732#endif /* __CONFIG_WPS__ */ 13733 13734static int 13735apply_cgi(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 13736 char_t *url, char_t *path, char_t *query) 13737{ 13738 char *value=NULL; 13739 char *page=NULL; 13740 13741 action = NOTHING; 13742 13743 websHeader(wp); 13744 websWrite(wp, (char_t *) apply_header); 13745 13746 page = websGetVar(wp, "page", ""); 13747 13748 value = websGetVar(wp, "action", ""); 13749 13750 /* Apply values */ 13751 if (!strcmp(value, "Apply")) { 13752 action = RESTART; 13753 websWrite(wp, "Validating values..."); 13754 13755 if (strcmp("lan.asp",page)) 13756 validate_cgi(wp); 13757 else 13758 validate_lan_cgi(wp); 13759 if(ret_code) 13760 { 13761 websWrite(wp, "<br>"); 13762 action = NOTHING; 13763 }else{ 13764 websWrite(wp, "done<br>"); 13765 websWrite(wp, "Committing values..."); 13766 nvram_set("is_modified", "1"); 13767 nvram_set("is_default", "0"); 13768 nvram_commit(); 13769 websWrite(wp, "done<br>"); 13770 } 13771 } 13772 13773 /* Restore defaults */ 13774 else if (!strncmp(value, "Restore", 7)) { 13775 websWrite(wp, "Restoring defaults..."); 13776 nvram_set("restore_defaults", "1"); 13777 /* Unset FA overridden */ 13778 if (FA_ON(atoi(nvram_safe_get("ctf_fa_mode")))) 13779 nvram_unset("ctf_fa_mode"); 13780 13781 nvram_commit(); 13782 websWrite(wp, "done<br>"); 13783 action = REBOOT; 13784 } 13785 13786 /* Release lease */ 13787 else if (!strcmp(value, "Release")) { 13788 websWrite(wp, "Releasing lease..."); 13789 if (sys_release()) 13790 websWrite(wp, "error<br>"); 13791 else 13792 websWrite(wp, "done<br>"); 13793 action = NOTHING; 13794 } 13795 13796 /* Renew lease */ 13797 else if (!strcmp(value, "Renew")) { 13798 websWrite(wp, "Renewing lease..."); 13799 if (sys_renew()) 13800 websWrite(wp, "error<br>"); 13801 else 13802 websWrite(wp, "done<br>"); 13803 action = NOTHING; 13804 } 13805 13806 /* Reboot router */ 13807 else if (!strcmp(value, "Reboot")) { 13808 websWrite(wp, "Rebooting..."); 13809 action = REBOOT; 13810 } 13811 13812 /* Upgrade image */ 13813 else if (!strcmp(value, "Upgrade")) { 13814 char *os_name = nvram_safe_get("os_name"); 13815 char *os_server = websGetVar(wp, "os_server", nvram_safe_get("os_server")); 13816 char *os_version = websGetVar(wp, "os_version", "current"); 13817 char upgrade_url[PATH_MAX]; 13818 if (!*os_version) 13819 os_version = "current"; 13820 snprintf(upgrade_url, sizeof(upgrade_url), "%s/%s/%s/%s.trx", 13821 os_server, os_name, os_version, os_name); 13822 websWrite(wp, "Retrieving %s...", upgrade_url); 13823 if (sys_upgrade(upgrade_url, NULL, NULL)) { 13824 websWrite(wp, "error<br>"); 13825 goto footer; 13826 } else { 13827 websWrite(wp, "done<br>"); 13828 action = REBOOT; 13829 } 13830 } 13831 13832 /* Report stats */ 13833 else if (!strcmp(value, "Stats")) { 13834 char *server = websGetVar(wp, "stats_server", nvram_safe_get("stats_server")); 13835 websWrite(wp, "Contacting %s...", server); 13836 if (sys_stats(server)) { 13837 websWrite(wp, "error<br>"); 13838 goto footer; 13839 } else { 13840 websWrite(wp, "done<br>"); 13841 nvram_set("stats_server", server); 13842 } 13843 } 13844 /* Radio On Off */ 13845 else if (!strcmp(value, "RadioOff")) { 13846 websWrite(wp, "Turing Off Radio..."); 13847 wl_radio_onoff(wp, 1); 13848 action = NOTHING; 13849 } 13850 else if (!strcmp(value, "RadioOn")) { 13851 websWrite(wp, "Radio on..."); 13852 wl_radio_onoff(wp, 0); 13853 action = NOTHING; 13854 } 13855#ifdef __CONFIG_NAT__ 13856 /* Delete connection */ 13857 else if (!strcmp(value, "Delete")) { 13858 int unit; 13859 if (!(value = websGetVar(wp, "wan_unit", NULL)) || 13860 (unit = atoi(value)) < 0 || unit >= MAX_NVPARSE) { 13861 websWrite(wp, "Unable to delete connection, index error."); 13862 action = NOTHING; 13863 } 13864 else { 13865 struct nvram_tuple *t; 13866 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 13867 int unit2, units = 0; 13868 /* 13869 * We can't delete the last connection since we can't differentiate 13870 * the cases where user does not want any connection (user deletes 13871 * the last one) vs. the router is booted the first time when there 13872 * is no connection at all (where a default one is created anyway). 13873 */ 13874 for (unit2 = 0; unit2 < MAX_NVPARSE; unit2 ++) { 13875 WAN_PREFIX(unit2, prefix); 13876 if (nvram_get(strcat_r(prefix, "unit", tmp)) && units++ > 0) 13877 break; 13878 } 13879 if (units < 2) { 13880 websWrite(wp, "Can not delete the last connection."); 13881 action = NOTHING; 13882 } 13883 else { 13884 /* set prefix */ 13885 WAN_PREFIX(unit, prefix); 13886 /* remove selected wan%d_ set */ 13887 websWrite(wp, "Deleting connection..."); 13888 for (t = router_defaults; t->name; t ++) { 13889 if (!strncmp(t->name, "wan_", 4)) 13890 nvram_unset(strcat_r(prefix, &t->name[4], tmp)); 13891 } 13892 /* fix unit number */ 13893 unit2 = unit; 13894 for (; unit < MAX_NVPARSE; unit ++) { 13895 WAN_PREFIX(unit, prefix); 13896 if (nvram_get(strcat_r(prefix, "unit", tmp))) 13897 break; 13898 } 13899 if (unit >= MAX_NVPARSE) { 13900 unit = unit2 - 1; 13901 for (; unit >= 0; unit --) { 13902 WAN_PREFIX(unit, prefix); 13903 if (nvram_get(strcat_r(prefix, "unit", tmp))) 13904 break; 13905 } 13906 } 13907 snprintf(tmp, sizeof(tmp), "%d", unit); 13908 nvram_set("wan_unit", tmp); 13909 /* check if there is any primary connection - see comment in wan_unit() */ 13910 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 13911 WAN_PREFIX(unit, prefix); 13912 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 13913 continue; 13914 if (nvram_invmatch(strcat_r(prefix, "proto", tmp), "disabled") && 13915 nvram_match(strcat_r(prefix, "primary", tmp), "1")) 13916 break; 13917 } 13918 /* no one is primary, pick the first enabled one as primary */ 13919 if (unit >= MAX_NVPARSE) 13920 wan_primary(wp); 13921 /* save the change */ 13922 nvram_set("is_modified", "1"); 13923 nvram_set("is_default", "0"); 13924 nvram_commit(); 13925 websWrite(wp, "done<br>"); 13926 action = RESTART; 13927 } 13928 } 13929 } 13930#endif /* __CONFIG_NAT__ */ 13931#ifdef __CONFIG_WAPI_IAS__ 13932 else if (!strcmp(value, "Revoke")) { 13933 value = websGetVar(wp, "sn", NULL); 13934 if (value == NULL) { 13935 websWrite(wp, "Invalid Revoke action<br>"); 13936 } 13937 else { 13938 cert_revoke(wp, value); 13939 } 13940 action = NOTHING; 13941 } 13942#endif /* __CONFIG_WAPI_IAS__ */ 13943#ifdef __CONFIG_WPS__ 13944 else if (!strcmp("wps.asp", page)) { 13945 wps_cgi(wp, urlPrefix, webDir, arg, url, path, query); 13946 } 13947#endif /* __CONFIG_WPS__ */ 13948 13949 /* Invalid action */ 13950 else 13951 websWrite(wp, "Invalid action %s<br>", value); 13952 13953 footer: 13954 websWrite(wp, (char_t *) apply_footer, websGetVar(wp, "page", "")); 13955 websFooter(wp); 13956 websDone(wp, 200); 13957 if (action == RESTART) 13958 sys_restart(); 13959 else if (action == REBOOT) 13960 sys_reboot(); 13961 13962 return 1; 13963} 13964 13965/* Copy all wl%d_XXXXX to wl_XXXXX */ 13966int 13967copy_wl_index_to_unindex(webs_t wp, char_t *urlPrefix, char_t *webDir, 13968 int arg, char_t *url, char_t *path, char_t *query) 13969{ 13970 struct variable *v=NULL; 13971 char *value=NULL; 13972 char name[IFNAMSIZ], os_name[IFNAMSIZ], *next=NULL; 13973 int unit = 0; 13974 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 13975 char unit_str[]={'\0','\0','\0','\0','\0'}; 13976 int applying = 0; 13977 char *wl_bssid = NULL; 13978 char vif[64] ; 13979 13980 /* Can enter this function through GET or POST */ 13981 if ((value = websGetVar(wp, "action", NULL))) { 13982 if (strcmp(value, "Select")) 13983 { 13984 /* we need to make sure wl_unit on the web page matches the 13985 wl_unit in NVRAM. If they match, bail out now, otherwise 13986 proceed with the rest of the function */ 13987 13988 if ((value = websGetVar(wp, "wl_unit", NULL))) { 13989 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))){ 13990 snprintf(vif,sizeof(vif),"%s.%s",value,wl_bssid); 13991 value = vif; 13992 } 13993 if (!strcmp( nvram_safe_get("wl_unit" ), value)) 13994 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 13995 } 13996 applying = 1; 13997 } 13998 } 13999 14000 /* copy wl%d_XXXXXXXX to wl_XXXXXXXX */ 14001 if ((value = websGetVar(wp, "wl_unit", NULL))) { 14002 if ((wl_bssid = websGetVar(wp, "wl_bssid", NULL)) && (atoi(wl_bssid))){ 14003 snprintf(vif,sizeof(vif),"%s.%s",value,wl_bssid); 14004 value = vif; 14005 } 14006 strncpy(unit_str,value,sizeof(unit_str) - 1); 14007 } 14008#ifdef __CONFIG_WPS__ 14009 else if (!strcmp(path, "wps.asp")) { 14010 get_wps_env(); 14011 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 14012 } 14013#endif /* __CONFIG_WPS__ */ 14014 else { 14015 char ifnames[256]; 14016 snprintf(ifnames, sizeof(ifnames), "%s %s %s %s", 14017 nvram_safe_get("lan_ifnames"), 14018 nvram_safe_get("lan1_ifnames"), 14019 nvram_safe_get("wan_ifnames"), 14020 nvram_safe_get("unbridged_ifnames")); 14021 14022 if (!remove_dups(ifnames,sizeof(ifnames))){ 14023 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 14024 return -1; 14025 } 14026 14027 /* Probe for first wl interface */ 14028 foreach(name, ifnames, next) { 14029 if (nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0) 14030 continue; 14031 if (wl_probe(os_name) == 0 && 14032 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)) == 0){ 14033 snprintf(unit_str,sizeof(unit_str),"%d",unit); 14034 break; 14035 } 14036 } 14037 14038 } 14039 if (*unit_str) { 14040 snprintf(prefix, sizeof(prefix), "wl%s_", unit_str); 14041 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 14042 char *val = NULL; 14043 14044 if ((v->ezc_flags & WEB_IGNORE) || ((prefix[3] == '.') && (v->ezc_flags & VIF_IGNORE))) { 14045 continue; 14046 } 14047 if (!strncmp(v->name, "wl_", 3)) { 14048 (void)strcat_r(prefix, &v->name[3], tmp); 14049 /* 14050 * tmp holds fully qualified name (wl0.1_....) 14051 * First try nvram; if NULL, try default; ? : is gcc-specific 14052 */ 14053 val = nvram_get(tmp) ? : nvram_default_get(tmp); 14054 if (val == NULL) { 14055 val = ""; 14056 } 14057 nvram_set(v->name, val); 14058 } 14059 if (!strncmp(v->name, "wl_unit", 7)) { 14060 break; 14061 } 14062 } 14063 } 14064 14065 /* Set currently selected unit */ 14066 nvram_set("wl_unit", unit_str); 14067 14068 if( applying ) 14069 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 14070 14071 /* Display the page */ 14072 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 14073} 14074 14075#ifdef __CONFIG_NAT__ 14076static int 14077wan_asp(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 14078 char_t *url, char_t *path, char_t *query) 14079{ 14080 struct variable *v=NULL; 14081 char *value=NULL; 14082 int unit = 0; 14083 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 14084 char ustr[16]; 14085 struct nvram_tuple *t=NULL; 14086 14087 /* Can enter this function through GET or POST */ 14088 if ((value = websGetVar(wp, "action", NULL))) { 14089 if (!strcmp(value, "New")) { 14090 /* pick one that 'does not' exist */ 14091 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 14092 WAN_PREFIX(unit, prefix); 14093 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 14094 break; 14095 } 14096 if (unit >= MAX_NVPARSE) { 14097 websHeader(wp); 14098 websWrite(wp, (char_t *) apply_header); 14099 websWrite(wp, "Unable to create new connection. Maximum %d.", MAX_NVPARSE); 14100 websWrite(wp, (char_t *) apply_footer, websGetVar(wp, "page", "")); 14101 websFooter(wp); 14102 websDone(wp, 200); 14103 return 1; 14104 } 14105 /* copy default to newly created wan%d_ set */ 14106 for (t = router_defaults; t->name; t ++) { 14107 if (!strncmp(t->name, "wan_", 4)) 14108 nvram_set(strcat_r(prefix, &t->name[4], tmp), t->value); 14109 } 14110 /* the following variables must be overwritten */ 14111 snprintf(ustr, sizeof(ustr), "%d", unit); 14112 nvram_set(strcat_r(prefix, "unit", tmp), ustr); 14113 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 14114 nvram_set(strcat_r(prefix, "ifname", tmp), nvram_safe_get("wan_ifname")); 14115 nvram_set(strcat_r(prefix, "hwaddr", tmp), nvram_safe_get("wan_hwaddr")); 14116 nvram_set(strcat_r(prefix, "ifnames", tmp), nvram_safe_get("wan_ifnames")); 14117 /* commit change */ 14118 nvram_set("is_modified", "1"); 14119 nvram_set("is_default", "0"); 14120 nvram_commit(); 14121 } 14122 else if (!strcmp(value, "Select")) { 14123 if ((value = websGetVar(wp, "wan_unit", NULL))) 14124 unit = atoi(value); 14125 else 14126 unit = -1; 14127 } 14128 else 14129 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 14130 } 14131 else if ((value = websGetVar(wp, "wan_unit", NULL))) 14132 unit = atoi(value); 14133 else 14134 unit = atoi(nvram_safe_get("wan_unit")); 14135 if (unit < 0 || unit >= MAX_NVPARSE) 14136 unit = 0; 14137 14138 /* Set prefix */ 14139 WAN_PREFIX(unit, prefix); 14140 14141 /* copy wan%d_ set to wan_ set */ 14142 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 14143 if (v->ezc_flags & WEB_IGNORE) 14144 continue; 14145 if (strncmp(v->name, "wan_", 4)) 14146 continue; 14147 value = nvram_get(strcat_r(prefix, &v->name[4], tmp)); 14148 if (value) 14149 nvram_set(v->name, value); 14150 if (!strncmp(v->name, "wan_unit", 8)) 14151 break; 14152 } 14153 14154 /* Set currently selected unit */ 14155 snprintf(tmp, sizeof(tmp), "%d", unit); 14156 nvram_set("wan_unit", tmp); 14157 14158 /* Display the page */ 14159 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 14160} 14161#endif /* __CONFIG_NAT__ */ 14162 14163#ifdef WEBS 14164 14165void 14166initHandlers(void) 14167{ 14168 websAspDefine("nvram_get", ej_nvram_get); 14169 websAspDefine("nvram_match", ej_nvram_match); 14170 websAspDefine("nvram_match_bitflag", ej_nvram_match_bitflag); 14171 websAspDefine("nvram_get_bitflag", ej_nvram_get_bitflag); 14172 websAspDefine("nvram_invmatch", ej_nvram_invmatch); 14173 websAspDefine("nvram_list", ej_nvram_list); 14174 websAspDefine("nvram_indexmatch", ej_nvram_indexmatch); 14175 websAspDefine("filter_client", ej_filter_client); 14176 websAspDefine("filter_url", ej_filter_url); 14177 websAspDefine("forward_port", ej_forward_port); 14178#ifdef __CONFIG_HSPOT__ 14179 websAspDefine("print_wl_wanmetrics",ej_print_wl_wanmetrics); 14180 websAspDefine("print_wl_oplist", ej_print_wl_oplist); 14181 websAspDefine("print_wl_homeqlist", ej_print_wl_homeqlist); 14182 websAspDefine("print_wl_osuplist", ej_print_wl_osuplist); 14183 websAspDefine("print_wl_concaplist", ej_print_wl_concaplist); 14184 websAspDefine("print_iconlist", ej_print_iconlist); 14185 websAspDefine("print_wl_qosmapie", ej_print_wl_qosmapie); 14186 /* ---- 802.11u ----------------------------------- */ 14187 websAspDefine("print_wl_netauthlist", ej_print_wl_netauthlist); 14188 websAspDefine("print_wl_realmlist", ej_print_wl_realmlist); 14189 websAspDefine("print_wl_venuelist", ej_print_wl_venuelist); 14190 websAspDefine("print_wl_ouilist", ej_print_wl_ouilist); 14191 websAspDefine("print_wl_3gpplist", ej_print_wl_3gpplist); 14192#endif /* __CONFIG_HSPOT__ */ 14193 websAspDefine("static_route", ej_static_route); 14194 websAspDefine("localtime", ej_localtime); 14195 websAspDefine("dumplog", ej_dumplog); 14196 websAspDefine("syslog", ej_syslog); 14197 websAspDefine("dumpleases", ej_dumpleases); 14198 websAspDefine("link", ej_link); 14199 14200 websUrlHandlerDefine("/apply.cgi", NULL, 0, apply_cgi, 0); 14201 websUrlHandlerDefine("/wireless.asp", NULL, 0, copy_wl_index_to_unindex, 0); 14202 14203 websSetPassword(nvram_safe_get("http_passwd")); 14204 14205 websSetRealm("Broadcom Home Gateway Reference Design"); 14206 14207 /* Initialize hash table */ 14208 hash_vtab(&vtab,v,variables_arraysize()); 14209} 14210 14211#else /* !WEBS */ 14212 14213int internal_init(void) 14214{ 14215 /* Initialize hash table */ 14216 if (hash_vtab(&vtab,variables,variables_arraysize())) 14217 return -1; 14218 return 0; 14219} 14220static void 14221do_auth(char *userid, char *passwd, char *realm) 14222{ 14223 assert(userid); 14224 assert(passwd); 14225 assert(realm); 14226 14227 strncpy(userid, nvram_safe_get("http_username"), AUTH_MAX); 14228 strncpy(passwd, nvram_safe_get("http_passwd"), AUTH_MAX); 14229 strncpy(realm, "Broadcom Home Gateway Reference Design", AUTH_MAX); 14230} 14231 14232char post_buf[POST_BUF_SIZE]; 14233char ezc_version[128]; 14234char no_cache[] = 14235"Cache-Control: no-cache\r\n" 14236"Pragma: no-cache\r\n" 14237"Expires: 0" 14238; 14239 14240char download_hdr[] = 14241"Cache-Control: no-cache\r\n" 14242"Pragma: no-cache\r\n" 14243"Expires: 0\r\n" 14244"Content-Type: application/download\r\n" 14245"Content-Disposition: attachment ; filename=nvram.txt" 14246; 14247 14248#ifdef __CONFIG_WAPI_IAS__ 14249char as_cert_download_hdr[] = 14250"Cache-Control: no-cache\r\n" 14251"Pragma: no-cache\r\n" 14252"Expires: 0\r\n" 14253"Content-Type: application/download\r\n" 14254"Content-Disposition: attachment ; filename=as.cer" 14255; 14256 14257char user_cert_download_hdr[] = 14258"Cache-Control: no-cache\r\n" 14259"Pragma: no-cache\r\n" 14260"Expires: 0\r\n" 14261"Content-Type: application/download\r\n" 14262"Content-Disposition: attachment ; filename=user.cer" 14263; 14264 14265#endif /* __CONFIG_WAPI_IAS__ */ 14266 14267static void 14268do_apply_post(char *url, FILE *stream, int len, char *boundary) 14269{ 14270 assert(url); 14271 assert(stream); 14272 14273 /* Get query */ 14274 if (!fgets(post_buf, MIN(len + 1, sizeof(post_buf)), stream)) 14275 return; 14276 len -= strlen(post_buf); 14277 14278 /* Initialize CGI */ 14279 init_cgi(post_buf); 14280 14281 /* Slurp anything remaining in the request */ 14282 while (len--) 14283 (void) fgetc(stream); 14284} 14285 14286static void 14287do_apply_cgi(char *url, FILE *stream) 14288{ 14289 char *path=NULL, *query=NULL; 14290 14291 assert(url); 14292 assert(stream); 14293 14294 /* Parse path */ 14295 query = url; 14296 path = strsep(&query, "?") ? : url; 14297 14298 apply_cgi(stream, NULL, NULL, 0, url, path, query); 14299 14300 /* Reset CGI */ 14301 init_cgi(NULL); 14302} 14303 14304 14305static void 14306do_upgrade_post(char *url, FILE *stream, int len, char *boundary) 14307{ 14308 char buf[1024]; 14309 14310 assert(url); 14311 assert(stream); 14312 14313 ret_code = EINVAL; 14314 14315 /* Look for our part */ 14316 while (len > 0) { 14317 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 14318 return; 14319 len -= strlen(buf); 14320 if (!strncasecmp(buf, "Content-Disposition:", 20) && 14321 strstr(buf, "name=\"file\"")) 14322 break; 14323 } 14324 14325 /* Skip boundary and headers */ 14326 while (len > 0) { 14327 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 14328 return; 14329 len -= strlen(buf); 14330 if (!strcmp(buf, "\n") || !strcmp(buf, "\r\n")) 14331 break; 14332 } 14333 14334 ret_code = sys_upgrade(NULL, stream, &len); 14335 14336 /* Slurp anything remaining in the request */ 14337 while (len--) 14338 (void) fgetc(stream); 14339} 14340 14341static void 14342do_upgrade_cgi(char *url, FILE *stream) 14343{ 14344 assert(url); 14345 assert(stream); 14346 14347 websHeader(stream); 14348 websWrite(stream, (char_t *) apply_header); 14349 14350 /* We could probably be more informative here... */ 14351 if (ret_code) 14352 websWrite(stream, "Error during upgrade<br>"); 14353 else 14354 websWrite(stream, "Upgrade complete. Rebooting...<br>"); 14355 14356 websWrite(stream, (char_t *) apply_footer, "firmware.asp"); 14357 websFooter(stream); 14358 websDone(stream, 200); 14359 14360 /* Reboot if successful */ 14361 if (ret_code == 0) 14362 sys_reboot(); 14363} 14364 14365#ifdef PLC 14366static char hex2nible(char c) 14367{ 14368 switch (c) 14369 { 14370 case '0': case '1': case '2': case '3': case '4': 14371 case '5': case '6': case '7': case '8': case '9': 14372 return c - '0'; 14373 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 14374 return 10 + c - 'a'; 14375 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 14376 return 10 + c - 'A'; 14377 default: 14378 return 0; 14379 } 14380} 14381 14382/************************************************** 14383 * Function name : static void BcmPostParse(char *url, FILE *stream, int len, 14384 * char *boundary) 14385 * Created by : Toni Homedes i Saun 14386 * Date created : 06-10-2010 14387 * Notes : Public function 14388 * Restrictions (pre-conditions) 14389 * Odd modes (post-conditions) 14390 **************************************************/ 14391/** \brief Parses post arguments in application/x-www-form-urlencoded form 14392 * 14393 * The arguments are added to the file global BcmPostArgs variable. 14394 * 14395 * The CGI function is responsible for frring this dictionnary 14396 * 14397 * \param[in] url unused 14398 * \param[in] stream socket to read from 14399 * \param[in] len len of args 14400 * \param[in] boundary unused 14401 * 14402 **************************************************/ 14403static void BcmPostParse(char *url, FILE *stream, int len, char *boundary) 14404{ 14405 BcmPostArgs = DictNew(); 14406 char line[512]; 14407 int i = 1; 14408 int value_pos = 0; 14409 14410 bzero(line, sizeof line); 14411 14412 /* CheckBoxes say nothing when not checked */ 14413 DictSet(BcmPostArgs, "plc_cfg_root", ""); 14414 14415 while(len && !feof(stream)) 14416 { 14417 int c; 14418 14419 c = fgetc(stream), --len; 14420 14421 if ('%' == c && len >= 2) /* percent encoded char follows */ 14422 { 14423 char cc; 14424 c = fgetc(stream), --len; 14425 cc = hex2nible(c) << 4; 14426 c = fgetc(stream), --len; 14427 cc = hex2nible(c); 14428 c = cc; 14429 } 14430 else if ('&' == c || EOF == c || !len) 14431 { 14432 if ('&' != c && '=' != c && EOF != c) 14433 { 14434 if ('+' == c) 14435 c = ' '; 14436 line[i++] = c; 14437 } 14438 line[i++] = '\0'; 14439 14440 DictSet(BcmPostArgs, line + 1, value_pos ? line + value_pos : ""); 14441 memset(line, '\0', sizeof line); 14442 value_pos = i = 0; 14443 14444 if (!len || EOF == c) 14445 return; 14446 } 14447 else if ('=' == c) 14448 { 14449 c = '\0'; 14450 value_pos = i + 1; 14451 } 14452 else if ('+' == c) 14453 { 14454 c = ' '; 14455 } 14456 14457 if (i < sizeof line - 1) 14458 { 14459 line[i++] = c; 14460 } 14461 } 14462} 14463#endif 14464 14465/* This utility routine builds the wl prefixes from wl_unit. 14466 * Input is expected to be a null terminated string 14467 * 14468 * Inputs -prefix: Pointer to prefix buffer 14469 * -prefix_size: Size of buffer 14470 * -Mode flag: If set generates unit.subunit output 14471 * if not set generates unit only 14472 * -ifname: Optional interface name string 14473 * 14474 * 14475 * Returns - pointer to prefix, NULL if error. 14476 * 14477 * 14478*/ 14479char * 14480make_wl_prefix(char *prefix,int prefix_size, int mode, char *ifname) 14481{ 14482 int unit=-1,subunit=-1; 14483 char *wl_unit=NULL; 14484 14485 assert(prefix); 14486 assert(prefix_size); 14487 14488 if (ifname){ 14489 assert(*ifname); 14490 wl_unit=ifname; 14491 }else{ 14492 wl_unit=nvram_get("wl_unit"); 14493 14494 if (!wl_unit) 14495 return NULL; 14496 } 14497 14498 if (get_ifname_unit(wl_unit,&unit,&subunit) < 0 ) 14499 return NULL; 14500 14501 if (unit < 0) return NULL; 14502 14503 if ((mode) && (subunit > 0 )) 14504 snprintf(prefix, prefix_size, "wl%d.%d_", unit,subunit); 14505 else 14506 snprintf(prefix, prefix_size, "wl%d_", unit); 14507 14508 return prefix; 14509} 14510 14511/* Format of the NVRAM text file is as follows 14512 * the following major sections 14513 * Header Block 14514 * Constraint Block 14515 * NVRAM variables 14516 * 14517 * Header consists of : 14518 * LineCount 14519 * Checksum 14520 * 14521 * Constraint block consists of : 14522 * Defined by NVRAM_CONSTRAINT_VARS 14523 * 14524 * 14525*/ 14526 14527/* Get major os version. The nvram variable gives the whole thing. 14528 * this function avoids the messy parsing. 14529 * Used by NVRAM constraint validation routines. 14530 * The input argument is not used. This is used to maintain 14531 * argument list compatability with nvram_get(). 14532 * 14533*/ 14534static char* 14535osversion_get(const char *name) 14536{ 14537 14538 static char ret_string[32]; 14539 14540 assert(name); 14541 14542 snprintf(ret_string,sizeof(ret_string),"%d.%d", 14543 ROUTER_MAJOR_VERSION, ROUTER_MINOR_VERSION); 14544 14545 14546 return ret_string; 14547 14548} 14549 14550/* This routine strips the CRLF from the HTTP stream */ 14551/* Returns new length or -1 if there is an error*/ 14552static int 14553remove_crlf(char *buf, int len) 14554{ 14555 14556 int slen; 14557 if (!buf) return -1; 14558 if (!len) return 0; 14559 14560 slen = strlen(buf); 14561 len = len-slen; 14562 if ((buf[slen-1] == '\n' ) && (buf[slen-2] == '\r' )){ 14563 buf[slen-1]='\0'; 14564 buf[slen-2]='\0'; 14565 14566 } 14567 else if ( buf[slen-1] == '\n' ) buf[slen-1]='\0'; 14568 14569 return len; 14570} 14571/* Utility routine to add a string from a string buffer. 14572 * 14573 * Routine expects that the buffer is composed of text strings with 14574 * a null as the delimiter. 14575 * 14576 * Input is expected to be a null terminated string 14577 * 14578 * Inputs -Pointer to char buffer 14579 * -NULL input terminated string 14580 * -Offset to end of used area. Including the NULL terminator 14581 * -Size of the buffer (to avoid running of the end of the buffer) 14582 * 14583 * 14584 * Returns - Number of bytes occupied including NULL terminator. -1 if error 14585 * 14586 * 14587*/ 14588static int 14589add_string(char *buf, char *string, int start, int bufsize) 14590{ 14591 int len; 14592 14593 assert(buf); 14594 14595 if (!string) return -1; 14596 if (!*string) return -1; 14597 if (!bufsize) return -1; 14598 if (start >=bufsize) return -1; 14599 14600 len = strlen(string); 14601 14602 if ( (start + len + 1) >= bufsize ) return -1; 14603 14604 strncpy(buf,string,len); 14605 14606 return start + len + 1; 14607} 14608static void 14609do_nvramul_post(char *url, FILE *stream, int len, char *boundary) 14610{ 14611 char buf[1024]; 14612 int index,cur_entry; 14613 char *ptr=NULL; 14614 char *name=NULL; 14615 char tmp[NVRAM_MAX_STRINGSIZE]; 14616 char file_checksum[NVRAM_SHA1BUFSIZE],checksum[NVRAM_SHA1BUFSIZE]; 14617 unsigned char key[NVRAM_SHA1BUFSIZE]; 14618 int checksum_linenum = NVRAM_CHECKSUM_LINENUM; 14619 char salt[NVRAM_SALTSIZE]; 14620 int numlines=0; 14621 int entries,offset,slen; 14622 unsigned char passphrase[]=NVRAM_PASSPHRASE; 14623 char nvram_file_header[][NVRAM_MAX_STRINGSIZE/2] = NVRAM_FILEHEADER; 14624 upload_constraints constraint_vars [] = NVRAM_CONSTRAINT_VARS; 14625 struct pb { 14626 char header[NVRAM_HEADER_LINECOUNT(nvram_file_header)][NVRAM_MAX_STRINGSIZE]; 14627 char buf[MAX_NVRAM_SPACE]; 14628 }*tmpbuf=NULL; 14629#if !defined(WLTEST) 14630 struct variable *v = NULL; 14631#endif /* !WLTEST */ 14632 14633 assert(stream); 14634 14635 entries = NVRAM_HEADER_LINECOUNT(nvram_file_header); 14636 ret_code = EINVAL; 14637 14638 /* Look for our part */ 14639 while (len > 0) { 14640 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 14641 return; 14642 14643 /* Remove LF that fgets()drags in */ 14644 len=remove_crlf(buf,len); 14645 /* look for start of attached file header */ 14646 14647 if (*buf){ 14648 if (strstr(buf,NVRAM_BEGIN_WEBFILE)) break; 14649 } 14650 14651 } 14652 14653 if (!len) return; 14654 14655 /* loop thru the header lines until we get the blank line 14656 that signifies the start of file contents */ 14657 while (len > 0){ 14658 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 14659 return; 14660 /* Remove LF that fgets()drags in */ 14661 len=remove_crlf(buf,len); 14662 14663 /* look for the blank line */ 14664 if (*buf == NVRAM_END_WEBFILE) break; 14665 } 14666 14667 if (!len) return; 14668 14669 /* Found start of upload file. Proceed with the upload */ 14670 /* Look for start of upload data */ 14671 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 14672 return; 14673 14674 len = len - strlen(buf); 14675 14676 /* Get the number of NVRAM variables */ 14677 sprintf(tmp,"%s=%s",nvram_file_header[NVRAM_LINECOUNT_LINENUM],"%d"); 14678 14679 if ( (sscanf(buf,tmp,&numlines) != 1) || !len ){ 14680 strncpy(posterr_msg,"Invalid NVRAM header<br>",ERR_MSG_SIZE); 14681 return ; 14682 } 14683 14684 if (numlines == 0) { 14685 strncpy(posterr_msg, "Invalid NVRAM header<br>", ERR_MSG_SIZE); 14686 return; 14687 } 14688 14689 tmpbuf = (struct pb *) malloc( sizeof(struct pb)); 14690 if (!tmpbuf){ 14691 strncpy(posterr_msg,"Memory allocation error<br>",ERR_MSG_SIZE); 14692 return; 14693 } 14694 14695 memset(tmpbuf,0,sizeof(struct pb)); 14696 14697 /* Copy over the first line of the file. Needed for 14698 proper checksum calculations */ 14699 14700 strcpy(tmpbuf->header[0],buf); 14701 14702 /* read in checksum */ 14703 if (!fgets(tmpbuf->header[1], MIN(len + 1,NVRAM_MAX_STRINGSIZE), stream)) 14704 goto do_nvramul_post_cleanup0; 14705 14706 len = len - strlen(tmpbuf->header[1]); 14707 14708 /* start reading in the rest of the NVRAM contents into memory buffer*/ 14709 offset = 0; 14710 for (index = 2 ; (len > 0) && (index < numlines); index++){ 14711 char filebuf[NVRAM_MAX_STRINGSIZE]; 14712 14713 if (!fgets(filebuf, MIN(len + 1,NVRAM_MAX_STRINGSIZE), stream)) 14714 goto do_nvramul_post_cleanup0; 14715 14716 offset = add_string(&tmpbuf->buf[offset],filebuf,offset, 14717 sizeof(((struct pb *)0)->buf)); 14718 if (offset < 0){ 14719 snprintf(posterr_msg,ERR_MSG_SIZE, 14720 "Error processing NVRAM variable:%s<br>",filebuf); 14721 goto do_nvramul_post_cleanup0; 14722 } 14723 len = len - strlen(filebuf); 14724 14725 /* don't remove the LFs since the we are using multipart 14726 MIME encoding that does not touch the contents of the 14727 uploaded file. LFs are actually part of the NVRAM var lines. 14728 */ 14729 } 14730 14731 /* Bail if the number of actual lines is less than that 14732 in the header 14733 */ 14734 14735 if ( !len && (index < numlines) ){ 14736 strncpy(posterr_msg,"NVRAM file incomplete<br>",ERR_MSG_SIZE); 14737 goto do_nvramul_post_cleanup0; 14738 } 14739 14740 /* Save and decode checksum from file */ 14741 ptr = tmpbuf->header[checksum_linenum]; 14742 14743 sprintf(tmp,"%s=",nvram_file_header[checksum_linenum]); 14744 14745 if ( !strstr(ptr,tmp) ) { 14746 snprintf(posterr_msg,ERR_MSG_SIZE, 14747 "No checksum present at line %d<br>",checksum_linenum+1); 14748 goto do_nvramul_post_cleanup0 ; 14749 } 14750 ptr = &ptr[strlen(tmp)]; 14751 14752 if ( b64_decode(ptr,(unsigned char *)tmp,NVRAM_MAX_STRINGSIZE) != NVRAM_FILECHKSUM_SIZE){ 14753 strncpy(posterr_msg,"Invalid checksum.<br>",ERR_MSG_SIZE); 14754 goto do_nvramul_post_cleanup0 ; 14755 }; 14756 14757 memset(file_checksum,0,sizeof(file_checksum)); 14758 memc 14759 14760 /* Extract salt value from stored checksum*/ 14761 memcpy(salt,&tmp[NVRAM_HASHSIZE],NVRAM_SALTSIZE); 14762 14763 /* Regenerate encryption key */ 14764 memset(key,0,sizeof(key)); 14765 fPRF(passphrase,strlen((char *)passphrase),NULL,0, 14766 (unsigned char*)salt,sizeof(salt),key,NVRAM_FILEKEYSIZE); 14767 14768 /* Plug in filler for checksum into read buffer*/ 14769 memset(tmpbuf->header[checksum_linenum],0,NVRAM_MAX_STRINGSIZE); 14770 snprintf(tmpbuf->header[checksum_linenum], 14771 NVRAM_MAX_STRINGSIZE,"%s\n",NVRAM_CHECKSUM_FILLER); 14772 14773 /* Calculate checksum and compare with stored value*/ 14774 14775 memset(checksum,0,sizeof(checksum)); 14776 hmac_sha1((unsigned char*)tmpbuf,sizeof(struct pb) , 14777 key,NVRAM_FILEKEYSIZE,(unsigned char *)checksum); 14778 14779 if (memcmp(checksum,file_checksum,NVRAM_HASHSIZE)){ 14780 memcpy(posterr_msg,"File checksum error<br>",ERR_MSG_SIZE); 14781 goto do_nvramul_post_cleanup0; 14782 } 14783 14784 /* Check constraints on the data */ 14785 14786 cur_entry = NVRAM_HEADER_LINECOUNT(nvram_file_header); 14787 slen=0; 14788 name = tmpbuf->buf; 14789 for (index = 0 ; *constraint_vars[index].name && *name; index++,cur_entry++,name += slen + 1) { 14790 char *var=NULL,*ptr=NULL; 14791 int comparesize ; 14792 14793 slen = strlen(name); 14794 14795 if (cur_entry > numlines){ 14796 memcpy(posterr_msg, 14797 "Constraints mismatch between file and running image<br>", 14798 ERR_MSG_SIZE); 14799 goto do_nvramul_post_cleanup0; 14800 } 14801 14802 14803 var = constraint_vars[index].get(constraint_vars[index].name); 14804 14805 if (!var){ 14806 snprintf(posterr_msg,ERR_MSG_SIZE, 14807 "NVRAM variable:%s not found in running image<br>", 14808 constraint_vars[index].name); 14809 goto do_nvramul_post_cleanup0; 14810 } 14811 14812 if (!strstr(name,constraint_vars[index].name)){ 14813 snprintf(posterr_msg,ERR_MSG_SIZE, 14814 "NVRAM variable:%s not found in uploaded file<br>", 14815 constraint_vars[index].name); 14816 goto do_nvramul_post_cleanup0; 14817 } 14818 14819 /*Move past separator*/ 14820 ptr = &name[strlen(constraint_vars[index].name) + 1] ; 14821 14822 /* Ignore last character which is a \n */ 14823 comparesize = strlen(ptr) -1; 14824 14825 /* If the primary match fails try for the secomdary matches */ 14826 if (strncmp(ptr,var,comparesize)){ 14827 int sec_fail=0; 14828 14829 /* If partial march is defined match altval pattern against 14830 file and image values*/ 14831 if (constraint_vars[index].flags & NVRAM_CONS_PARTIAL_MATCH){ 14832 sec_fail=( !strstr(ptr,constraint_vars[index].altval) && 14833 !strstr(var,constraint_vars[index].altval)); 14834 } 14835 else if (constraint_vars[index].flags & NVRAM_CONS_ALT_MATCH){ 14836 sec_fail=(strncmp(ptr,constraint_vars[index].altval,comparesize)); 14837 } 14838 else sec_fail =1; 14839 14840 if (sec_fail){ 14841 snprintf(posterr_msg,ERR_MSG_SIZE, 14842 "NVRAM constraint mismatch FILE:<b>%s=%s</b> IMAGE:<b>%s=%s</b><br>", 14843 constraint_vars[index].name,ptr,constraint_vars[index].name,var); 14844 goto do_nvramul_post_cleanup0; 14845 } 14846 } 14847 14848 } 14849 14850 /* Process the NVRAM payload 14851 * 14852 * Remove the carriage returns at the end of the NVRAM variables 14853 * 14854 */ 14855 14856 cur_entry = NVRAM_HEADER_LINECOUNT(nvram_file_header) + NVRAM_HEADER_LINECOUNT(constraint_vars); 14857 14858 slen=0; 14859 for (index = cur_entry ;(index < numlines) && *name; index++,name += slen + 1){ 14860 int offset; 14861 char *ptr=NULL; 14862 char *varname=NULL; 14863 char *myptr=NULL; 14864 14865 offset = index * NVRAM_MAX_STRINGSIZE; 14866 14867 /* The length of the actual var must be saved here as the subsequent 14868 * manipulation using strsep() changes the string buffer. 14869 * This to ensure that the buffer (tmpbuf->buf) is correctly procesed 14870 * This buffer separates the individual AVPs using a null character 14871 */ 14872 14873 slen =strlen(name); 14874 ptr = name; 14875 14876 /* Remove the CR at the end of the string */ 14877 ptr[slen-1] = '\0'; 14878 14879 /* Look for tag that indicates that the value is encrypted */ 14880 if (*ptr==NVRAM_ENCTAG){ 14881 char buf[NVRAM_MAX_STRINGSIZE]; 14882 int bufsize = sizeof(buf); 14883 char *varname=NULL; 14884 14885 varname=strsep(&ptr, "="); 14886 14887 /* Increment pointer to move past tag */ 14888 varname++; 14889 14890 if (!decrypt_var(varname,ptr,strlen(ptr),buf,&bufsize,(char *)key,NVRAM_FILEKEYSIZE)){ 14891 snprintf(posterr_msg,ERR_MSG_SIZE, 14892 "Error decrypting value %s at line %d<br>",ptr,index); 14893 goto do_nvramul_post_cleanup0; 14894 } 14895 14896 snprintf(name,NVRAM_MAX_STRINGSIZE,"%s=%s",varname,buf); 14897 14898 } 14899 14900 /* 14901 Write out NVRAM variables. 14902 */ 14903 14904 myptr = name; 14905 varname=strsep(&myptr, "="); 14906 14907#if !defined(WLTEST) 14908 v=get_var_handle(varname); 14909 14910 /* Restore only those NVRAM vars in the validation table 14911 Ignore those with the obvious flag set 14912 */ 14913 if (!v) 14914 continue; 14915 14916 if (v->ezc_flags & NVRAM_IGNORE) 14917 continue; 14918#endif /* !WLTEST */ 14919 14920 if (nvram_set(varname,myptr)) 14921 goto do_nvramul_post_cleanup0; 14922 14923 } 14924 14925 nvram_commit(); 14926 14927 /* We are done */ 14928 ret_code = 0; 14929 14930do_nvramul_post_cleanup0: 14931 /* Clear up any outstanding stuff */ 14932 /* Slurp anything remaining in the request */ 14933 while (len--) 14934 (void) fgetc(stream); 14935 14936 if (tmpbuf) free(tmpbuf); 14937 14938 return; 14939} 14940 14941static void 14942do_nvramul_cgi(char *url, FILE *stream) 14943{ 14944 assert(stream); 14945 assert(url); 14946 14947 websHeader(stream); 14948 websWrite(stream, (char_t *) apply_header); 14949 14950 if (ret_code){ 14951 websWrite(stream, "Error during NVRAM upload<br>"); 14952 if (*posterr_msg){ 14953 websWrite(stream, posterr_msg); 14954 memset(posterr_msg,0,ERR_MSG_SIZE); 14955 } 14956 14957 } else websWrite(stream, "NVRAM upload complete.<br>Rebooting....<br>"); 14958 14959 websWrite(stream, (char_t *) apply_footer, "firmware.asp"); 14960 websFooter(stream); 14961 websDone(stream, 200); 14962 14963 /* Reboot if successful */ 14964 if (ret_code == 0) 14965 sys_reboot(); 14966 14967} 14968 14969/* 14970 This routine validates and formats the NVRAM variable into the file output format. 14971 If the variable is not in the monster V-block or its allowed multi instance variants 14972 it is dropped 14973 14974 Returns number of characters printed or -1 on error 14975*/ 14976static int 14977save_nvram_var(char *name, char *var_val,char *buf, int buflen,char *key, int keylen) 14978{ 14979 char tmp[NVRAM_MAX_STRINGSIZE]; 14980 int len=sizeof(tmp); 14981 int retval=0; 14982 struct variable *v = NULL; 14983 14984 assert(name); 14985 assert(buf); 14986 assert(key); 14987 assert(buflen); 14988 assert(keylen); 14989 14990 14991 /* If var_val is null, this forces the variable to be unset when the file is uploaded 14992 If the variable is supposed to be encrypted but is null, skip it and do not 14993 mark the string as encrypted. 14994 14995 If var_val is null the variable does not exist. Skip and do not save in that case. 14996 */ 14997 14998 v = get_var_handle(name); 14999 15000 if (!v) { 15001#if defined(WLTEST) 15002 retval= snprintf(buf,buflen,"%s=%s\n", (char_t *)name, (char_t *)var_val); 15003 return retval; 15004#else 15005 return 0; 15006#endif /* WLTEST */ 15007 } 15008 15009 if (v->ezc_flags & NVRAM_IGNORE) 15010 return 0; 15011 15012 if (var_val) { 15013 if (strlen(var_val) > NVRAM_MAX_STRINGSIZE){ 15014 cprintf("get_nvram_var():String too long Len=%d String=%s\n", strlen(var_val) ,var_val); 15015 return -1; 15016 } 15017 15018 if ( (v->ezc_flags & NVRAM_ENCRYPT) && (*var_val) ){ 15019 var_val = encrypt_var(name,var_val,strlen(var_val),tmp,&len,key,keylen); 15020 15021 if (!var_val){ 15022 cprintf("get_nvram_var():Error encrypting %s\n",name); 15023 return -1; 15024 } 15025 15026 retval=snprintf(buf,buflen,"%c%s=%s\n", 15027 NVRAM_ENCTAG, 15028 (char_t *)name, 15029 (char_t *)var_val); 15030 } else retval=snprintf(buf,buflen,"%s=%s\n", 15031 (char_t *)name, 15032 (char_t *)var_val); 15033 } 15034 return retval; 15035} 15036 15037/* This is the cgi handler for the NVRAM download function 15038 * Inputs: -url of the calling file (not used but HTTPD expects this form) 15039 * -Pointer to the post buffer 15040 * 15041 * 15042 * Returns: None 15043*/ 15044static void 15045do_nvramdl_cgi(char *url, FILE *stream) 15046{ 15047 char checksum[NVRAM_SHA1BUFSIZE]; 15048 unsigned char passphrase[]=NVRAM_PASSPHRASE; 15049 char salt[NVRAM_SALTSIZE]; 15050 unsigned char key[NVRAM_SHA1BUFSIZE]; 15051 int entries; 15052 char tmp[NVRAM_MAX_STRINGSIZE],tmp1[NVRAM_MAX_STRINGSIZE]; 15053 char tmp_buf[NVRAM_MAX_STRINGSIZE]; 15054 char *buf=NULL; 15055 char *var_val=NULL; 15056 char *var_name=NULL; 15057 char *name=NULL; 15058 char *ptr=NULL; 15059 int index; 15060 int retval; 15061 upload_constraints constraint_vars [] = NVRAM_CONSTRAINT_VARS; 15062 char nvram_file_header[][NVRAM_MAX_STRINGSIZE/2] = NVRAM_FILEHEADER; 15063 struct pb { 15064 char header[NVRAM_HEADER_LINECOUNT(nvram_file_header)][NVRAM_MAX_STRINGSIZE]; 15065 char buf[MAX_NVRAM_SPACE]; 15066 } *post_buf=NULL; 15067 15068 int offset = 0; 15069 15070 assert(stream); 15071 15072 post_buf = (struct pb *)malloc(sizeof (struct pb)); 15073 15074 if (!post_buf) { 15075 cprintf("do_nvramdl_cgi():Error allocating %d bytes for post_buf\n", 15076 sizeof (struct pb)); 15077 goto do_nvramdl_cgi_error; 15078 } 15079 15080 buf = (char *)malloc(MAX_NVRAM_SPACE); 15081 15082 if (!buf) { 15083 cprintf("do_nvramdl_cgi():Error allocating %d bytes for buf\n", 15084 MAX_NVRAM_SPACE); 15085 goto do_nvramdl_cgi_error; 15086 } 15087 15088 memset (post_buf,0,sizeof(struct pb)); 15089 memset (buf,0,MAX_NVRAM_SPACE); 15090 15091 assert(stream); 15092 15093 entries = NVRAM_HEADER_LINECOUNT(nvram_file_header); 15094 memset(tmp_buf,0,sizeof(tmp_buf)); 15095 15096 memset(salt,0,sizeof(salt)); 15097 15098 srand(time((time_t *)NULL)); 15099 for (index = 0 ; index < 30 ; index ++) rand(); 15100 index =rand(); 15101 memcpy(&salt[sizeof(index)],&index,sizeof(index)); 15102 for (index = 0 ; index < 30 ; index ++) rand(); 15103 index =rand(); 15104 memcpy(&salt,&index,sizeof(index)); 15105 15106 /* 15107 The first entry of the file is the number of variables 15108 The second entry is the offset to the start of the NVRAM variables 15109 The third entry is the SHA1 checksum 15110 */ 15111 15112 /* PopulateHeader info */ 15113 offset = 0; 15114 for (index =0 ;*constraint_vars[index].name;index++){ 15115 entries++; 15116 var_val=constraint_vars[index].get(constraint_vars[index].name); 15117 snprintf(tmp_buf,NVRAM_MAX_STRINGSIZE,"%s=%s\n", 15118 constraint_vars[index].name, 15119 (var_val) ? var_val : "unknown"); 15120 if (!offset) cprintf("Post_buf address = %p\n",&post_buf->buf[offset]); 15121 offset = add_string(&post_buf->buf[offset],tmp_buf,offset,sizeof(struct pb)); 15122 if (offset < 0){ 15123 cprintf("httpd: Error Adding NVRAM header info.\n"); 15124 goto do_nvramdl_cgi_error; 15125 } 15126 }; 15127 15128 memset(key,0,sizeof(key)); 15129 fPRF(passphrase,strlen((char *)passphrase),NULL,0, 15130 (unsigned char*)salt,sizeof(salt),key,NVRAM_FILEKEYSIZE); 15131 15132 /* Plug in filler for checksum */ 15133 snprintf(post_buf->header[NVRAM_CHECKSUM_LINENUM],NVRAM_MAX_STRINGSIZE,"%s\n",NVRAM_CHECKSUM_FILLER); 15134 /* Grab the NVRAM buffer */ 15135 15136 nvram_getall(buf, MAX_NVRAM_SPACE); 15137 15138 for(name = buf; *name; name += strlen(name) + 1){ 15139 var_val =tmp; 15140 strncpy(tmp,name,sizeof(tmp) - 1); 15141 tmp[sizeof(tmp) - 1] = '\0'; 15142 var_name=strsep(&var_val,"="); 15143 retval = save_nvram_var(var_name,var_val,tmp_buf, 15144 sizeof(tmp_buf),(char *)key,NVRAM_FILEKEYSIZE); 15145 15146 if (retval <0){ 15147 cprintf("httpd: Error Adding NVRAM variable info.\n"); 15148 goto do_nvramdl_cgi_error; 15149 }; 15150 15151 if (retval > 0 ) { 15152 entries++; 15153 offset = add_string(&post_buf->buf[offset],tmp_buf,offset,sizeof(struct pb)); 15154 if (offset < 0){ 15155 cprintf("httpd: Error Adding NVRAM variable info.\n"); 15156 goto do_nvramdl_cgi_error; 15157 } 15158 }; 15159 15160 if (offset > MAX_NVRAM_SPACE) { 15161 cprintf("httpd: MAX_NVRAM_SPACE of %d (%d) exceeded\n",MAX_NVRAM_SPACE,offset); 15162 goto do_nvramdl_cgi_error; 15163 }; 15164 } 15165 15166 15167 /* Add the header info */ 15168 snprintf(post_buf->header[NVRAM_LINECOUNT_LINENUM],NVRAM_MAX_STRINGSIZE,"%s=%d\n", 15169 nvram_file_header[NVRAM_LINECOUNT_LINENUM],entries); 15170 15171 /*Generate the hash */ 15172 15173 memset(checksum,0,sizeof(checksum)); 15174 hmac_sha1((unsigned char*)post_buf,sizeof(struct pb),key,NVRAM_FILEKEYSIZE, 15175 (unsigned char*)checksum); 15176 15177 memcpy(tmp,checksum,NVRAM_HASHSIZE); 15178 memcpy(&tmp[NVRAM_HASHSIZE],salt,NVRAM_SALTSIZE); 15179 15180 ptr = b64_encode((unsigned char *)tmp, NVRAM_FILECHKSUM_SIZE, 15181 (unsigned char *)buf, MAX_NVRAM_SPACE ); 15182 15183 if (!ptr){ 15184 cprintf("do_nvramdl_cgi():Error performing base-64 encode of NVRAM checksum.\n"); 15185 goto do_nvramdl_cgi_error; 15186 } 15187 15188 strncpy(tmp1, ptr, sizeof(tmp1) - 1); 15189 tmp1[sizeof(tmp1) - 1] = '\0'; 15190 15191 snprintf(post_buf->header[NVRAM_CHECKSUM_LINENUM],NVRAM_MAX_STRINGSIZE,"%s=%s\n", 15192 nvram_file_header[NVRAM_CHECKSUM_LINENUM],tmp1); 15193 /* Write out header */ 15194 for (index =0; index < NVRAM_HEADER_LINECOUNT(nvram_file_header) ; index ++) 15195 websWrite(stream, "%s", post_buf->header[index]); 15196 15197 /* Write out rest of file */ 15198 15199 for(name = post_buf->buf; *name; name += strlen(name) + 1){ 15200 /*cprintf("Val->%s\n",name);*/ 15201 websWrite(stream, "%s", name); 15202 }; 15203 15204do_nvramdl_cgi_error: 15205 15206 if (post_buf) 15207 free(post_buf); 15208 if (buf) 15209 free(buf); 15210 15211 websDone(stream, 200); 15212 15213 return; 15214} 15215 15216#ifdef __CONFIG_WAPI_IAS__ 15217#define LENGTH 255 15218#define RECVFROM_LEN 64*1024 15219 15220#define RECVTIMEOUT 5 15221 15222/* install certificate part */ 15223#define AS_CERFILE "as_cerfile" /* ASU Certificate File name in security.asp */ 15224#define USER_CERFILE "user_cerfile" /* User Certificate File name in security.asp */ 15225#define AS_CERFILE_PATH "/tmp/as_cerfile.cer" /* Temporary file to save ASU certificate */ 15226#define USER_CERFILE_PATH "/tmp/user_cerfile.cer" /* Temporary file to save User certificate */ 15227#define CERT_START_SIGN "-----BEGIN CERTIFICATE-----" 15228#define CERT_END_SIGN "-----END CERTIFICATE-----" 15229#define USER_CERT_END_SIGN "-----END EC PRIVATE KEY-----" 15230 15231#define START_SIGN_IS_DATA 0x1 15232#define END_SIGN_IS_DATA 0x2 15233 15234struct srv_info 15235{ 15236 int fd; 15237 int port; 15238 struct sockaddr_in addr; 15239}; 15240 15241struct _head_info 15242{ 15243 unsigned short ver; 15244 unsigned short cmd; 15245 unsigned short reserve; 15246 unsigned short data_len; 15247}; 15248 15249struct _packet_reset_srv 15250{ 15251 struct _head_info head; 15252 unsigned char data[4096]; 15253}; 15254 15255#define VERSIONNOW 0x0001 15256#define AP_RELOAD 0x0212 15257#define AP_RELOAD_RESPONSE 0x0213 15258#define CHECK_CERT 0x0214 15259#define CHECK_CERT_RESPNOSE 0x0215 15260 15261/* X509 */ 15262#define PEM_STRING_X509_ASU "ASU CERTIFICATE" 15263#define PEM_STRING_X509_USER "USER CERTIFICATE" 15264#define PEM_STRING_X509_BEGIN "-----BEGIN " 15265#define PEM_STRING_X509_END "-----END " 15266#define PEM_STRING_X509 "CERTIFICATE" /* define in include/bcmcrypto/pme.h */ 15267#define PEM_STRING_PKCS8INF "PRIVATE KEY" /* define in include/bcmcrypto/pme.h */ 15268#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" /* define in include/bcmcrypto/pme.h */ 15269 15270 15271 15272/* process form */ 15273#define MSEP_LF 0x0A 15274#define MSEP_CR 0x0D 15275 15276 15277/* This is the cgi handler for the WAPI AS certificate download function 15278 * Inputs: -url of the calling file (not used but HTTPD expects this form) 15279 * -Pointer to the post buffer 15280 * Returns: None 15281*/ 15282 15283static int 15284as_communicate(char *req, int req_len, char *rsp, int *rsp_len) 15285{ 15286 struct sockaddr_in as_addr; 15287 struct timeval tv = {RECVTIMEOUT, 0}; 15288 int fd = -1; 15289 fd_set fds; 15290 int ret = 0; 15291 15292 memset(&as_addr, 0, sizeof(struct sockaddr_in)); 15293 as_addr.sin_family = AF_INET; 15294 as_addr.sin_port = htons(AS_UI_PORT); 15295 if (inet_aton(AS_UI_ADDR, &as_addr.sin_addr) < 0) { 15296 cprintf("Address translation error"); 15297 return -1; 15298 } 15299 15300 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 15301 /* send request to AS */ 15302 sendto(fd, req, req_len, 0, (struct sockaddr *)&as_addr, sizeof(struct sockaddr_in)); 15303 15304 /* receive response data */ 15305 FD_ZERO(&fds); 15306 FD_SET(fd, &fds); 15307 15308 select(fd + 1, &fds, NULL, NULL, &tv); 15309 15310 if (FD_ISSET(fd, &fds)) { 15311 memset(rsp, 0, *rsp_len); 15312 15313 *rsp_len = recv(fd, rsp, *rsp_len, 0); 15314 if (*rsp_len == 0) { 15315 cprintf("receive no data\n"); 15316 ret = -1; 15317 } 15318 rsp[*rsp_len] = 0; 15319 } 15320 else { 15321 cprintf("No data selected\n"); 15322 ret = -1; 15323 } 15324 15325 if(fd > 0) 15326 close(fd); 15327 15328 return ret; 15329} 15330 15331/* revoke certificate*/ 15332static int 15333cert_revoke(webs_t wp, char *sn_str) 15334{ 15335 char cmd[40]; 15336 char *rbuf = NULL; 15337 int rbuf_len = 128; 15338 15339 sprintf(cmd, "action=Revoke sn=%s", sn_str); 15340 15341 rbuf = malloc(rbuf_len); 15342 if (as_communicate(cmd, strlen(cmd), rbuf, &rbuf_len)) { 15343 websWrite(wp, "Communicate to AS server failed<br>"); 15344 } 15345 else { 15346 if (rbuf_len == 0) 15347 websWrite(wp, "Revoke certificate(%s) failed<br>", sn_str); 15348 else 15349 websWrite(wp, "%s<br>", rbuf); 15350 } 15351 15352 if (rbuf) 15353 free(rbuf); 15354 15355 return 0; 15356} 15357 15358static int 15359ej_as_cer_display(int eid, webs_t wp, int argc, char_t **argv) 15360{ 15361#define MAX_CERT_LENGTH 0xFFA8 15362 char *rbuf = NULL; 15363 int rbuf_len = MAX_CERT_LENGTH; 15364 int i, count, item; 15365 char *p; 15366 int ret = -1; 15367 char na[32+1], sn[32], dur[8], remain[8], status[16], type[16]; 15368 15369 if (!nvram_match("as_mode", "enabled")) 15370 return 0; 15371 15372 rbuf = malloc(rbuf_len); 15373 if (as_communicate("action=Query", 13, rbuf, &rbuf_len)) { 15374 goto query_err; 15375 } 15376 15377 /* query string must start with 'count' string */ 15378 if (rbuf_len < 5) { 15379 cprintf("data length incorrect"); 15380 goto query_err; 15381 } 15382 15383 /* display certificate result */ 15384 sscanf(rbuf, "count=%d", &count); 15385 p = rbuf; 15386 for (i = 0; i < count; i++) { 15387 p = strstr(p + 1, "item"); 15388 15389 sscanf(p, "item%d=%s %s %s %s %s %s", &item, na, sn, dur, remain, type, status); 15390 websWrite(wp, "<tr>"); 15391 websWrite(wp, "<td>%s</td>", na); 15392 websWrite(wp, "<td>%s</td>", sn); 15393 websWrite(wp, "<td>%s</td>", dur); 15394 websWrite(wp, "<td>%s</td>", remain); 15395 websWrite(wp, "<td>%s</td>", type); 15396 websWrite(wp, "<td>%s</td>", status); 15397 15398 if (strncmp(status, "Actived", 7) == 0) { 15399 websWrite(wp, "<form method=\"post\" action=\"apply.cgi\">"); 15400 websWrite(wp, "<td>"); 15401 websWrite(wp, "<input type=\"hidden\" name=\"sn\" value=\"%s\">", sn); 15402 websWrite(wp, "<input type=\"hidden\" name=\"page\" value=\"as.asp\">"); 15403 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"Revoke\">"); 15404 websWrite(wp, "</td>"); 15405 websWrite(wp, "</form>"); 15406 } 15407 else { 15408 websWrite(wp, "<td></td>"); 15409 } 15410 15411 websWrite(wp, "</tr>"); 15412 } 15413 15414 ret = 0; 15415 15416query_err: 15417 if (rbuf) 15418 free(rbuf); 15419 return ret; 15420} 15421 15422/* request new user certificate */ 15423static int 15424cert_ask(char *name, uint32 period, char *ret_msg) 15425{ 15426 char cmd[100]; 15427 char *rbuf = NULL; 15428 int rbuf_len = 128; 15429 int ret = -1; 15430 15431 sprintf(cmd, "action=Apply name=%s period=%d", name, period); 15432 15433 rbuf = malloc(rbuf_len); 15434 if (as_communicate(cmd, strlen(cmd), rbuf, &rbuf_len)) { 15435 sprintf(ret_msg, "Communicate to AS server failed"); 15436 } 15437 else { 15438 if (rbuf_len == 0) 15439 sprintf(ret_msg, "Apply new certificate failed"); 15440 else { 15441 /* retrieve user certificate location */ 15442 sscanf(rbuf, "user_cer=%s", ret_msg); 15443 ret = 0; 15444 } 15445 } 15446 15447 if (rbuf) 15448 free(rbuf); 15449 15450 return ret; 15451} 15452 15453static char* 15454read_all_data(char *file, int size_min, int size_max) 15455{ 15456 int size, count; 15457 char *data = NULL, *ptr; 15458 FILE *fp = NULL; 15459 struct stat stat; 15460 15461 if (!file) { 15462 cprintf("read_all_data():Invaild argument file\n"); 15463 return NULL; 15464 } 15465 15466 /* open file for read */ 15467 if ((fp = fopen(file, "r")) <= 0) { 15468 cprintf("read_all_data():Error open %s for read\n", file); 15469 return NULL; 15470 } 15471 if (fstat(fileno(fp), &stat) != 0) { 15472 cprintf("read_all_data():fstat file %s fail!\n", file); 15473 goto read_all_data_error; 15474 } 15475 size = stat.st_size; 15476 if ((size_min != -1 && size < size_min) || (size_max != -1 && size > size_max)) { 15477 cprintf("read_all_data():size %d check fail!\n", size); 15478 goto read_all_data_error; 15479 } 15480 15481 data = (char *)malloc(size + 1); 15482 if (!data) { 15483 cprintf("read_all_data():Error allocating %d bytes for buf\n", size); 15484 goto read_all_data_error; 15485 } 15486 memset (data, 0, size + 1); 15487 15488 ptr = data; 15489 while (size) { 15490 count = safe_fread(ptr, 1, size, fp); 15491 if (!count && (ferror(fp) || feof(fp))) 15492 break; 15493 size -= count; 15494 ptr += count; 15495 } 15496 15497 if (size) { 15498 cprintf("read_all_data():Read %s file fail, total size %d read size %d\n", 15499 file, (int)stat.st_size, (int)stat.st_size - size); 15500 goto read_all_data_error; 15501 } 15502 15503 if (fp) 15504 fclose(fp); 15505 15506 return data; 15507 15508read_all_data_error: 15509 15510 if (fp) 15511 fclose(fp); 15512 if (data) 15513 free(data); 15514 15515 return NULL; 15516} 15517 15518static void 15519do_as_x509_cert_dl_cgi(char *url, FILE *stream) 15520{ 15521 char *data = NULL; 15522 15523 assert(stream); 15524 15525 /* get as certificate file */ 15526 data = read_all_data(WAPI_AS_CER_FILE, -1, -1); 15527 15528 if (data) { 15529 /* Write out as cert data */ 15530 websWrite(stream, "%s", data); 15531 free (data); 15532 } 15533 15534 websDone(stream, 200); 15535 15536 return; 15537} 15538 15539static void 15540do_user_x509_cert_dl_cgi(char *url, FILE *stream) 15541{ 15542 char *owner = NULL; 15543 char *period_str = NULL; 15544 char *unit_str = NULL; 15545 char *rcv_msg = NULL; 15546 char *data = NULL; 15547 uint32 period = 0; 15548 15549 assert(stream); 15550 15551 owner = websGetVar(stream, "cer_owner", NULL); 15552 period_str = websGetVar(stream, "cer_period", NULL); 15553 unit_str = websGetVar(stream, "cer_period_unit", NULL); 15554 15555 if (owner == NULL || period_str == NULL || unit_str == NULL) { 15556 cprintf("do_user_x509_cert_dl_cgi():Wrong variables argument\n"); 15557 goto do_user_x509_cert_dl_cgi_error; 15558 } 15559 15560 period = atoi(period_str) * atoi(unit_str) * 86400; 15561 15562 if ((rcv_msg = malloc(LENGTH)) == NULL) { 15563 cprintf("do_user_x509_cert_dl_cgi():buffer allocate error\n"); 15564 goto do_user_x509_cert_dl_cgi_error; 15565 } 15566 memset(rcv_msg, 0, LENGTH); 15567 15568 if (cert_ask(owner, period, rcv_msg)) { 15569 cprintf("do_user_x509_cert_dl_cgi():%s\n", rcv_msg); 15570 goto do_user_x509_cert_dl_cgi_error; 15571 } 15572 else { 15573 /* retrieve data from received file path */ 15574 if (rcv_msg[0] != 0) 15575 data = read_all_data(rcv_msg, -1, -1); 15576 } 15577 15578 if (data) { 15579 /* Write out as cert data */ 15580 websWrite(stream, "%s", data); 15581 free(data); 15582 } 15583 15584do_user_x509_cert_dl_cgi_error: 15585 15586 websDone(stream, 200); 15587 15588 /* Reset CGI */ 15589 init_cgi(NULL); 15590 15591 if (rcv_msg) 15592 free(rcv_msg); 15593 15594 return; 15595} 15596 15597/* return remain len or -1 is error */ 15598static int 15599get_multipart(FILE *stream, int len, char *name, char *outfile, char *outbuf, 15600 char *start_sign, char *end_sign, int flag) 15601{ 15602 int ret = 0; 15603 int last_line = 0; 15604 char buf[1024]; 15605 FILE *fp = NULL; 15606 15607 assert(stream); 15608 assert(name); 15609 assert(start_sign); 15610 15611 if (!outfile && !outbuf) 15612 return -1; 15613 15614 /* look for "name" part */ 15615 while (len > 0) { 15616 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 15617 return -1; 15618 15619 /* remove LF that fgets() drags in and update len value */ 15620 len = remove_crlf(buf, len); 15621 15622 /* look for start of attached file header */ 15623 if (*buf && strstr(buf, name)) 15624 break; 15625 } 15626 15627 if (len <= 0) 15628 return -1; 15629 15630 /* open the outfile to write */ 15631 if (outfile && (fp = fopen(outfile, "w")) == NULL) 15632 return errno; 15633 15634 /* 15635 * loop thru the header lines until we get the "start_sign" line 15636 * that signifies the start of "name" contents 15637 */ 15638 while (len > 0) { 15639 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) { 15640 ret = -1; 15641 goto get_multipart_done; 15642 } 15643 15644 if (strstr(buf, start_sign)) { 15645 /* write to "outfile" or "outbuf" */ 15646 if (flag & START_SIGN_IS_DATA) { 15647 if (fp) 15648 safe_fwrite(buf, 1, strlen(buf), fp); 15649 else 15650 memcpy(outbuf, buf, strlen(buf)); 15651 } 15652 len -= strlen(buf); 15653 break; 15654 } 15655 len -= strlen(buf); 15656 } 15657 15658 if (outbuf && !end_sign) { 15659 if (!(flag & START_SIGN_IS_DATA)) { 15660 if (len > 0 && fgets(buf, MIN(len + 1, sizeof(buf)), stream)) { 15661 memcpy(outbuf, buf, strlen(buf)); 15662 len -= strlen(buf); 15663 } else { 15664 ret = -1; 15665 goto get_multipart_done; 15666 } 15667 } 15668 15669 ret = len; 15670 goto get_multipart_done; 15671 } 15672 15673 if (len <= 0) { 15674 ret = -1; 15675 goto get_multipart_done; 15676 } 15677 15678 /* 15679 * loop thru the header lines until we get the "end_sing" line 15680 * that signifies the end of "name" contents 15681 */ 15682 while (len > 0) { 15683 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) { 15684 ret = -1; 15685 goto get_multipart_done; 15686 } 15687 15688 if (strstr(buf, end_sign)) { 15689 last_line = 1; 15690 len = remove_crlf(buf, len); 15691 15692 } else 15693 len -= strlen(buf); 15694 15695 if (fp && (!last_line || (last_line && (flag & END_SIGN_IS_DATA)))) { 15696 safe_fwrite(buf, 1, strlen(buf), fp); 15697 } 15698 15699 if (last_line) 15700 break; 15701 } 15702 15703 ret = len; 15704 15705get_multipart_done: 15706 15707 if (fp) 15708 fclose(fp); 15709 15710 return ret; 15711 15712} 15713 15714static int 15715check_cert_file(char *user_cert_data) 15716{ 15717 if (user_cert_data != NULL && strstr(user_cert_data, "KEY-----") != NULL) 15718 return 0; 15719 15720 return -1; 15721} 15722 15723static char* 15724search_pem_str(char *in, char *name) 15725{ 15726 char *p = NULL; 15727 15728 p = strstr(in, name); 15729 return p; 15730} 15731 15732static int 15733PEM_read_x509(char **data, int *datal, char *name, char *fcontent, int flen) 15734{ 15735 char *p = fcontent; 15736 char *end = fcontent + flen; 15737 char *bdata = NULL; 15738 char *edata = NULL; 15739 int ret = 0; 15740 15741 do { 15742 bdata = search_pem_str(p, name); 15743 if ((bdata == NULL) || (bdata >end)) { 15744 ret = -1; 15745 break; 15746 } 15747 bdata +=strlen(name); 15748 if (strncmp(bdata, "-----", 5) != 0) 15749 { 15750 ret = -1; 15751 break; 15752 }; 15753 bdata += 5; 15754 15755 edata = search_pem_str(bdata, PEM_STRING_X509_END); 15756 if ((edata == NULL) || (edata >end)) { 15757 ret = -2; 15758 break; 15759 } 15760 *data = bdata; 15761 *datal = edata-bdata; 15762 }while(0); 15763 15764 return ret ; 15765} 15766 15767static void 15768cp_cert_flag(char **buffer, char *str_x509, const char *str_cert) 15769{ 15770 char *p = *buffer; 15771 15772 /*cp -----BEGIN ASU(USER) CERTIFICATE-----*/ 15773 memcpy(p, str_x509, strlen(str_x509)); 15774 p += strlen(str_x509); 15775 memcpy(p, str_cert, strlen(str_cert)); 15776 p += strlen(str_cert); 15777 memcpy(p, "-----", 5); 15778 p += 5; 15779 *buffer = p; 15780} 15781static void 15782PEM_write(char **in, char *data, int datal, const char *name) 15783{ 15784 char *p = *in; 15785 15786 /*cp LF+CR */ 15787 p[0] = MSEP_CR; p[1] = MSEP_LF; p +=2; 15788 15789 /*cp -----BEGIN ASU(USER) CERTIFICATE-----*/ 15790 cp_cert_flag(&p, PEM_STRING_X509_BEGIN, name); 15791 15792 /*cp -----cert content-----*/ 15793 memcpy(p, data, datal); 15794 p += datal; 15795 15796 /*cp -----END ASU(USER) CERTIFICATE-----*/ 15797 cp_cert_flag(&p, PEM_STRING_X509_END, name); 15798 15799 /*cp LF+CR */ 15800 p[0] = MSEP_CR; p[1] = MSEP_LF; p +=2; 15801 15802 *in = p; 15803} 15804 15805static int 15806x509_cert_converge(char *buffer, char *as_data, char *user_data) 15807{ 15808 char *cert = NULL; 15809 char *p = buffer; 15810 int certl = 0; 15811 int ret = 0; 15812 15813 /* AS certificate */ 15814 ret = PEM_read_x509(&cert, &certl, PEM_STRING_X509, as_data, strlen(as_data)); 15815 if (ret != 0) { 15816 printf("ret = %d\n", ret); 15817 return 0; 15818 } 15819 PEM_write(&p, cert, certl, PEM_STRING_X509_ASU); 15820 15821 /* user cerfiticate */ 15822 cert = NULL; 15823 certl = 0; 15824 ret = PEM_read_x509(&cert, &certl, PEM_STRING_X509, user_data, strlen(user_data)); 15825 if (ret != 0) { 15826 printf("ret = %d\n", ret); 15827 return 0; 15828 } 15829 PEM_write(&p, cert, certl, PEM_STRING_X509_USER); 15830 15831 cert = NULL; 15832 certl = 0; 15833 if((PEM_read_x509(&cert, &certl, PEM_STRING_PKCS8INF, user_data, strlen(user_data))) == 0) 15834 PEM_write(&p, cert, certl, PEM_STRING_ECPRIVATEKEY); 15835 15836 return (p - buffer); 15837} 15838 15839static int 15840init_srv_info(struct srv_info *WAI_srv, const char *ip_addr) 15841{ 15842 int ret = 0; 15843 15844 memset(&(WAI_srv->addr), 0, sizeof(struct sockaddr_in)); 15845 WAI_srv ->fd = socket(AF_INET, SOCK_DGRAM, 0); 15846 WAI_srv->addr.sin_family = AF_INET; 15847 WAI_srv->addr.sin_port = htons(WAI_srv->port); 15848 ret = inet_aton(ip_addr, &(WAI_srv->addr.sin_addr)); 15849 if (ret == 0) { 15850 printf("\nas IP_addr error!!!\n\n"); 15851 } 15852 15853 return ret; 15854} 15855 15856static int 15857send_wapi_info(struct srv_info *WAI_srv, struct _packet_reset_srv *packet_reset_srv) 15858{ 15859 int sendlen = 0; 15860 int data_len = 0; 15861 int ret = 0; 15862 15863 data_len = packet_reset_srv->head.data_len + sizeof(struct _head_info); 15864 packet_reset_srv->head.data_len = htons(packet_reset_srv->head.data_len); 15865 sendlen = sendto(WAI_srv->fd, (char *)packet_reset_srv, data_len, 0, 15866 (struct sockaddr *)&(WAI_srv->addr), sizeof(struct sockaddr_in)); 15867 if (sendlen != data_len) 15868 ret = -1; 15869 15870 return ret; 15871} 15872static int 15873recv_wapi_info(struct srv_info *WAI_srv, struct _packet_reset_srv *recv_from_srv, int timeout) 15874{ 15875 fd_set readfds; 15876 struct timeval tv; 15877 int bytes_read; 15878 15879 15880 /* First, setup a select() statement to poll for the data comming in */ 15881 FD_ZERO(&readfds); 15882 FD_SET(WAI_srv->fd, &readfds); 15883 15884 tv.tv_sec = timeout; 15885 tv.tv_usec = 0; 15886 15887 select(WAI_srv->fd + 1, &readfds, NULL, NULL, &tv); 15888 if (FD_ISSET(WAI_srv->fd, &readfds)) { 15889 bytes_read = recv(WAI_srv->fd, (char *)recv_from_srv, RECVFROM_LEN, 0); 15890 return(bytes_read); 15891 } 15892 15893 return -1; 15894} 15895 15896static void 15897wapi_ntoh_data(struct _packet_reset_srv *recv_from_srv) 15898{ 15899 recv_from_srv->head.ver = ntohs(recv_from_srv->head.ver); 15900 recv_from_srv->head.cmd = ntohs(recv_from_srv->head.cmd); 15901 recv_from_srv->head.data_len = ntohs(recv_from_srv->head.data_len); 15902} 15903 15904static int 15905process_wapi_info(struct _packet_reset_srv *recv_from_WAI) 15906{ 15907 int ret = 0; 15908 unsigned short CMD = 0; 15909 unsigned char check_result = 0; 15910 15911 wapi_ntoh_data(recv_from_WAI); 15912 if (recv_from_WAI->head.ver != VERSIONNOW) { 15913 cprintf("Version error in data from , The Ver is %d\n", recv_from_WAI->head.ver ); 15914 ret = -1; 15915 goto process_wapi_info_error; 15916 } 15917 15918 if (recv_from_WAI->head.data_len != 2) { 15919 cprintf("data_len error in data from , The Ver is %d\n", recv_from_WAI->head.data_len ); 15920 ret = -1; 15921 goto process_wapi_info_error; 15922 } 15923 15924 CMD = recv_from_WAI->head.cmd; 15925 check_result = *((unsigned short *)recv_from_WAI->data); 15926 switch(CMD) 15927 { 15928 case CHECK_CERT_RESPNOSE: 15929 case AP_RELOAD_RESPONSE: 15930 if (check_result != 0) { 15931 ret = -1; 15932 } 15933 break; 15934 default: 15935 ret = -1; 15936 break; 15937 } 15938 15939process_wapi_info_error: 15940 15941 return ret; 15942} 15943 15944static int 15945save_certificate(const char *fname, char *fcontent, int flen) 15946{ 15947 FILE *f; 15948 int ret = 0; 15949 15950 /* save certificate file */ 15951 f = fopen(fname, "wb"); 15952 15953 if (f == NULL) 15954 ret = 1; 15955 15956 if (fwrite(fcontent, flen, 1, f) != 1) 15957 ret = 2; 15958 15959 fclose(f); 15960 15961 confmtd_backup(); 15962 15963 return ret; 15964} 15965 15966 15967static void 15968do_cert_ul_post(char *url, FILE *stream, int len, char *boundary) 15969{ 15970 int bufl, ret = 0; 15971 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 15972 char cert_file[LENGTH] = ""; 15973 char *as_data = NULL, *user_data = NULL; 15974 char *buffer; 15975 FILE *outfile = NULL; 15976 15977 struct _packet_reset_srv send_to_WAI; 15978 struct _packet_reset_srv recv_from_WAI; 15979 struct srv_info WAI_srv; 15980 15981 assert(url); 15982 assert(stream); 15983 15984 ret_code = EINVAL; 15985 15986 /* get wl prefix */ 15987 sprintf(prefix, "wl%s_", nvram_get("wl_unit")); 15988 15989 /* get as_cerfile */ 15990 len = get_multipart(stream, len, AS_CERFILE, AS_CERFILE_PATH, NULL, 15991 CERT_START_SIGN, CERT_END_SIGN, (START_SIGN_IS_DATA | END_SIGN_IS_DATA)); 15992 if (len == 0 || len == -1) { 15993 strncpy(posterr_msg, "Invalid AS certificate file<br>", ERR_MSG_SIZE); 15994 return; 15995 } 15996 15997 /* get user_cerfile */ 15998 len = get_multipart(stream, len, USER_CERFILE, USER_CERFILE_PATH, NULL, 15999 CERT_START_SIGN, USER_CERT_END_SIGN, (START_SIGN_IS_DATA | END_SIGN_IS_DATA)); 16000 if (len == 0 || len == -1) { 16001 strncpy(posterr_msg, "Invalid user certificate file<br>", ERR_MSG_SIZE); 16002 return; 16003 } 16004 16005 /* read as and user certificate */ 16006 if ((as_data = read_all_data(AS_CERFILE_PATH, -1, -1)) == NULL) { 16007 strncpy(posterr_msg, "Read AS certificate file fail<br>", ERR_MSG_SIZE); 16008 goto do_cert_ul_post_error; 16009 } 16010 16011 if ((user_data = read_all_data(USER_CERFILE_PATH, -1, -1)) == NULL) { 16012 strncpy(posterr_msg, "Read USER certificate file fail<br>", ERR_MSG_SIZE); 16013 goto do_cert_ul_post_error; 16014 } 16015 16016 /* check certificate files */ 16017 if((check_cert_file(user_data)) != 0) { 16018 strncpy(posterr_msg, "Certificate file format error.<br>", ERR_MSG_SIZE); 16019 goto do_cert_ul_post_error; 16020 } 16021 16022 /* initial WAI service communicate structure */ 16023 memset(&WAI_srv, 0, sizeof(struct srv_info)); 16024 memset(&send_to_WAI, 0, sizeof(struct _packet_reset_srv)); 16025 memset(&recv_from_WAI, 0, sizeof(struct _packet_reset_srv)); 16026 16027 WAI_srv.fd = -1; 16028 /* integrate certificate */ 16029 buffer = (char *)send_to_WAI.data; 16030 16031 bufl = x509_cert_converge(buffer, as_data, user_data); 16032 if (bufl == 0) { 16033 strncpy(posterr_msg, "X509 certificate converge fail.<br>", ERR_MSG_SIZE); 16034 goto do_cert_ul_post_error; 16035 } 16036 16037 /* send certificate to WAI service and check cert is Ap's certificate or not */ 16038 WAI_srv.port = WAP_UI_PORT; 16039 ret = init_srv_info(&WAI_srv, WAI_UI_ADDR); 16040 if (ret == 0) { 16041 printf("\nAS IP_addr error!!!\n\n"); 16042 strncpy(posterr_msg, "System error. installing certificate failed.<br>", 16043 ERR_MSG_SIZE); 16044 goto do_cert_ul_post_error; 16045 } 16046 send_to_WAI.head.ver = htons(VERSIONNOW); 16047 send_to_WAI.head.cmd = htons(CHECK_CERT); 16048 send_to_WAI.head.reserve = htons(1); 16049 send_to_WAI.head.data_len = bufl; 16050 16051 ret = send_wapi_info(&WAI_srv, &send_to_WAI); 16052 if (ret != 0) { 16053 cprintf("Call send_wapi_info for CHECK_CERT, WAI is disabled"); 16054 strncpy(posterr_msg, "WAI is disabled.<br>", ERR_MSG_SIZE); 16055 goto do_cert_ul_post_error; 16056 } 16057 16058 /* read WAI srv response */ 16059 ret = recv_wapi_info(&WAI_srv, &recv_from_WAI, RECVTIMEOUT); 16060 if (ret <= 0) { 16061 cprintf("Call recv_wapi_info for CHECK_CERT, WAI is disabled\n"); 16062 strncpy(posterr_msg, "WAI is disabled.<br>", ERR_MSG_SIZE); 16063 goto do_cert_ul_post_error; 16064 } 16065 16066 /* process WAI srv response */ 16067 ret = process_wapi_info(&recv_from_WAI); 16068 if (ret != 0) { 16069 strncpy(posterr_msg, "Certificate file format error.<br>", ERR_MSG_SIZE); 16070 goto do_cert_ul_post_error; 16071 } 16072 16073 /* get ap certificate file name */ 16074 snprintf(cert_file, sizeof(cert_file), "%s/%s%s", WAPI_WAI_DIR, prefix, "apcert.cer"); 16075 16076 /* save AP certificate */ 16077 ret = save_certificate(cert_file, buffer, bufl); 16078 if (ret) { 16079 strncpy(posterr_msg, "Save certificate error.<br>", ERR_MSG_SIZE); 16080 goto do_cert_ul_post_error; 16081 } 16082 16083 /* save cert type and status */ 16084 nvram_set(strcat_r(prefix, "wai_cert_index", tmp), "1"); 16085 nvram_set("wl_wai_cert_index", "1"); 16086 nvram_set(strcat_r(prefix, "wai_cert_status", tmp), "1"); 16087 nvram_set("wl_wai_cert_status", "1"); 16088 nvram_set(strcat_r(prefix, "wai_cert_name", tmp), cert_file); 16089 nvram_set("wl_wai_cert_name", cert_file); 16090 nvram_commit(); 16091 16092 /* We are done */ 16093 ret_code = 0; 16094 16095do_cert_ul_post_error: 16096 16097 /* remove temporary files */ 16098 unlink(AS_CERFILE_PATH); 16099 unlink(USER_CERFILE_PATH); 16100 16101 if (as_data) 16102 free(as_data); 16103 if (user_data) 16104 free(user_data); 16105 if (WAI_srv.fd >= 0) 16106 close(WAI_srv.fd); 16107 if (outfile) 16108 fclose(outfile); 16109 16110 /* Clear up any outstanding stuff */ 16111 /* Slurp anything remaining in the request */ 16112 while (len--) 16113 (void) fgetc(stream); 16114 16115 return; 16116} 16117 16118static void 16119do_cert_ul_cgi(char *url, FILE *stream) 16120{ 16121 assert(stream); 16122 assert(url); 16123 16124 websHeader(stream); 16125 websWrite(stream, (char_t *) apply_header); 16126 16127 if (ret_code){ 16128 websWrite(stream, "Error during certificate upload<br>"); 16129 if (*posterr_msg){ 16130 websWrite(stream, posterr_msg); 16131 memset(posterr_msg,0,ERR_MSG_SIZE); 16132 } 16133 } else websWrite(stream, "Certificate upload complete."); 16134 16135 websWrite(stream, (char_t *) apply_footer, "security.asp"); 16136 websFooter(stream); 16137 websDone(stream, 200); 16138 16139 /* Do system restart */ 16140 if (ret_code == 0) 16141 sys_restart(); 16142} 16143#endif /* __CONFIG_WAPI_IAS__ */ 16144 16145/* 16146 * This routine takes the cipher text ctext and produces the plaintext ptext 16147 * using the provided key. 16148 * 16149 * This routine accepts the cipher text in the MIME Base64 format. 16150 * 16151 * The plain text is 8 bytes less than the ciphertext 16152 */ 16153static char* 16154decrypt_var(char *varname,char *ctext, int ctext_len, char *ptext, int *ptext_len,char *key, int keylen) 16155{ 16156 unsigned char tmp[NVRAM_MAX_STRINGSIZE]; 16157 int len; 16158 char *end=NULL; 16159 16160 assert(ptext); 16161 assert(ctext); 16162 assert(ptext_len); 16163 assert(key); 16164 if (keylen < 1 ) return NULL; 16165 16166 if (ctext_len > NVRAM_MAX_STRINGSIZE){ 16167 cprintf("decrypt_var():Encrypted string is too long MAXSTRINGSIZE=%d Strlen=%d\n", 16168 NVRAM_MAX_STRINGSIZE,ctext_len); 16169 } 16170 16171 /* Cipher text must be more than 8 chars for this aes_unwrap() routine to work*/ 16172 if (ctext_len < 8) return NULL; 16173 16174 len=b64_decode(ctext,tmp,NVRAM_MAX_STRINGSIZE); 16175 16176 if (!len) return NULL; 16177 16178 if (aes_unwrap(keylen,(unsigned char *)key,len,tmp,(unsigned char *)ptext)) 16179 return NULL; 16180 16181 *ptext_len = len - 8; 16182 16183 end = strstr(ptext,varname); 16184 16185 if (end) 16186 (*end)= '\0'; 16187 else 16188 return NULL; 16189 16190 return ptext; 16191} 16192/* 16193 * This routine takes the plaintext text ptext and produces the ciphertext ctext 16194 * using the provided key. 16195 * 16196 * It accepts the plaintext in binary form and produces ciphertext in MIME Base64 format. 16197 * 16198 * 16199 */ 16200static char* 16201encrypt_var(char *varname,char *ptext, int ptext_len, char *ctext, int *ctext_len,char *key, int keylen) 16202{ 16203 unsigned char tmp[NVRAM_MAX_STRINGSIZE]; 16204 char *buf=NULL; 16205 int newlen; 16206 int varname_len; 16207 16208 assert(ptext); 16209 assert(ctext); 16210 assert(ctext_len); 16211 assert(key); 16212 if (keylen < 1 ) return NULL; 16213 if (ptext_len < 1) return NULL; 16214 16215 varname_len = strlen (varname); 16216 16217 /* Include the NULL at the end */ 16218 newlen = ptext_len + varname_len + 1; 16219 /* Align the incoming buffer to AES block length boundaries */ 16220 if (newlen % AES_BLOCK_LEN) 16221 newlen = (1 + newlen /AES_BLOCK_LEN ) * AES_BLOCK_LEN; 16222 16223 /* Do a string length check. When the binary string is base-64 encoded 16224 it becomes 30% larger as every 3 bytes are represented by 4 ascii 16225 characters */ 16226 16227 if ( (4*(1+(newlen+8)/3)) > NVRAM_MAX_STRINGSIZE ) 16228 { 16229 cprintf("encrypt_var():The encrypted string is too long. MAXSTRINGSIZE=%d Strlen=%d\n", 16230 NVRAM_MAX_STRINGSIZE,(4*(1+(newlen+8)/3))); 16231 return NULL; 16232 } 16233 16234 buf = malloc (newlen); 16235 if (!buf) return NULL; 16236 memset(buf,0,newlen); 16237 memcpy(buf,ptext,ptext_len); 16238 memcpy(buf + ptext_len,varname,varname_len); 16239 16240 if (aes_wrap(keylen,(unsigned char *)key,newlen,(unsigned char *)buf, 16241 (unsigned char *)ctext)){ 16242 if (buf) free(buf); 16243 return NULL; 16244 }; 16245 16246 if (buf) free(buf); 16247 16248 buf = b64_encode((unsigned char *)ctext,newlen+8,tmp,NVRAM_MAX_STRINGSIZE-(ptext_len + 1)); 16249 16250 if (buf){ 16251 strncpy(ctext,buf,NVRAM_MAX_STRINGSIZE); 16252 *ctext_len = strlen(ctext) ; 16253 return ctext; 16254 } else { 16255 cprintf("encrypt_var():base-64 encode error\n"); 16256 *ctext_len = 0; 16257 return NULL; 16258 } 16259} 16260 16261static void 16262do_wireless_asp(char *url, FILE *stream) 16263{ 16264 char *path=NULL, *query=NULL; 16265 16266 assert(stream); 16267 assert(url); 16268 16269 /* Parse path */ 16270 query = url; 16271 path = strsep(&query, "?") ? : url; 16272 16273 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 16274 16275 /* Reset CGI */ 16276 init_cgi(NULL); 16277} 16278 16279static void 16280do_security_asp(char *url, FILE *stream) 16281{ 16282 char *path=NULL, *query=NULL; 16283 16284 assert(stream); 16285 assert(url); 16286 16287 /* Parse path */ 16288 query = url; 16289 path = strsep(&query, "?") ? : url; 16290 16291 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 16292 16293 /* Reset CGI */ 16294 init_cgi(NULL); 16295} 16296 16297#ifdef __CONFIG_WPS__ 16298static void 16299do_wps_asp(char *url, FILE *stream) 16300{ 16301 char *path=NULL, *query=NULL; 16302 16303 assert(stream); 16304 assert(url); 16305 16306 /* Parse path */ 16307 query = url; 16308 path = strsep(&query, "?") ? : url; 16309 printf("do_wps_asp\n"); 16310 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 16311 16312 /* Reset CGI */ 16313 init_cgi(NULL); 16314} 16315#endif /* #ifdef __CONFIG_WPS__ */ 16316 16317#if defined(__CONFIG_SAMBA__) || defined(__CONFIG_DLNA_DMS__) 16318static int 16319do_storage(webs_t wp, char_t *urlPrefix, char_t *webDir, 16320 int arg, char_t *url, char_t *path, char_t *query) 16321{ 16322 16323 if ((websGetVar(wp, "action", NULL))) { 16324 16325 ret_code = 0; 16326 16327 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 16328 } 16329 16330 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 16331} 16332 16333static void 16334do_storage_asp(char *url, FILE *stream) 16335{ 16336 char *path=NULL, *query=NULL; 16337 16338 assert(url); 16339 assert(stream); 16340 16341 /* Parse path */ 16342 query = url; 16343 path = strsep(&query, "?") ? : url; 16344 16345 do_storage(stream, NULL, NULL, 0, url, path, query); 16346 16347 /* Reset CGI */ 16348 init_cgi(NULL); 16349} 16350#endif 16351 16352static void 16353do_media_asp(char *url, FILE *stream) 16354{ 16355 char *path=NULL, *query=NULL; 16356 16357 assert(stream); 16358 assert(url); 16359 16360 /* Parse path */ 16361 query = url; 16362 path = strsep(&query, "?") ? : url; 16363 16364 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 16365 16366 /* Reset CGI */ 16367 init_cgi(NULL); 16368} 16369 16370static void 16371do_internal_asp(char *url, FILE *stream) 16372{ 16373 char *path=NULL, *query=NULL; 16374 16375 assert(stream); 16376 assert(url); 16377 16378 /* Parse path */ 16379 query = url; 16380 path = strsep(&query, "?") ? : url; 16381 16382 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 16383 16384 /* Reset CGI */ 16385 init_cgi(NULL); 16386} 16387 16388#ifdef __CONFIG_NAT__ 16389static void 16390do_wan_asp(char *url, FILE *stream) 16391{ 16392 char *path=NULL, *query=NULL; 16393 16394 assert(stream); 16395 assert(url); 16396 16397 /* Parse path */ 16398 query = url; 16399 path = strsep(&query, "?") ? : url; 16400 16401 wan_asp(stream, NULL, NULL, 0, url, path, query); 16402 16403 /* Reset CGI */ 16404 init_cgi(NULL); 16405} 16406#endif /* __CONFIG_NAT__ */ 16407 16408struct mime_handler mime_handlers[] = { 16409#if defined(__CONFIG_TREND_IQOS__) && defined(CONFIG_TREND_IQOS_ENABLED) 16410 { "iQoS.cgi*", "application/json", no_cache, do_iqos_post, do_iqos_get, do_auth }, 16411#endif /* __CONFIG_TREND_IQOS__ && CONFIG_TREND_IQOS_ENABLED */ 16412#ifdef __CONFIG_NAT__ 16413 { "wan.asp", "text/html", no_cache, do_apply_post, do_wan_asp, do_auth }, 16414#endif /* __CONFIG_NAT__ */ 16415 { "radio.asp", "text/html", no_cache, do_apply_post, do_wireless_asp, do_auth }, 16416 { "ssid.asp", "text/html", no_cache, do_apply_post, do_wireless_asp, do_auth }, 16417#ifdef __CONFIG_HSPOT__ 16418 {"passpoint.asp", "text/html", no_cache, do_apply_post, do_passpoint_asp, do_auth}, 16419 {"iconupload.cgi*", "text/html", no_cache, do_uploadIcons_post, do_uploadIcons_cgi, do_auth }, 16420#endif /* __CONFIG_HSPOT__ */ 16421 { "security.asp", "text/html", no_cache, do_apply_post, do_security_asp, do_auth }, 16422#if defined(__CONFIG_VISUALIZATION__) && defined(CONFIG_VISUALIZATION_ENABLED) 16423 { "json.cgi*", "application/json", no_cache, vis_do_json_set, vis_do_json_get, do_auth }, 16424 { "visdata.db*", NULL, g_vis_download_db_hdr, NULL, vis_do_visdbdwnld_cgi, do_auth }, 16425#endif /* (__CONFIG_VISUALIZATION__) && (CONFIG_VISUALIZATION_ENABLED) */ 16426#ifdef __CONFIG_WPS__ 16427 { "wps.asp", "text/html", no_cache, do_apply_post, do_wps_asp, do_auth }, 16428#endif /* __CONFIG_WPS__ */ 16429 { "internal.asp", "text/html", no_cache, do_apply_post, do_internal_asp, do_auth }, 16430#ifdef __CONFIG_EZC__ 16431 { "ezconfig.asp", "text/html", ezc_version, do_apply_ezconfig_post, do_ezconfig_asp, do_auth }, 16432#endif /* __CONFIG_EZC__ */ 16433#if defined(__CONFIG_SAMBA__) || defined(__CONFIG_DLNA_DMS__) 16434 { "storage.asp", "text/html", no_cache, do_apply_post, do_storage_asp, do_auth }, 16435#endif /* __CONFIG_DLNA_DMS__ */ 16436 { "media.asp", "text/html", no_cache, do_apply_post, do_media_asp, do_auth }, 16437 { "**.asp", "text/html", no_cache, NULL, do_ej, do_auth }, 16438 { "**.css", "text/css", NULL, NULL, do_file, do_auth }, 16439 { "**.gif", "image/gif", NULL, NULL, do_file, do_auth }, 16440 { "**.png", "image/png", NULL, NULL, do_file, do_auth }, 16441 { "**.jpg", "image/jpeg", NULL, NULL, do_file, do_auth }, 16442 { "**.ico", "image/ico", NULL, NULL, do_file, do_auth }, 16443 { "**.js", "text/javascript", NULL, NULL, do_file, do_auth }, 16444 { "**apply.cgi*", "text/html", no_cache, do_apply_post, do_apply_cgi, do_auth }, 16445 { "upgrade.cgi*", "text/html", no_cache, do_upgrade_post, do_upgrade_cgi, do_auth }, 16446 /* set MIME type to NULL to override the one built into the webserver. download_hdr 16447 defines its content type 16448 */ 16449 { "nvramdl.cgi*", NULL, download_hdr, NULL, do_nvramdl_cgi, do_auth }, 16450 { "nvramul.cgi*", NULL, "text/html", do_nvramul_post,do_nvramul_cgi , do_auth }, 16451#ifdef __CONFIG_WAPI_IAS__ 16452 { "cert_ul.cgi*", NULL, "text/html", do_cert_ul_post, do_cert_ul_cgi , do_auth }, 16453 { "as_x509_cert_dl.cgi*", NULL, as_cert_download_hdr, NULL, do_as_x509_cert_dl_cgi, do_auth }, 16454 { "user_x509_cert_dl.cgi*", NULL, user_cert_download_hdr, do_apply_post, do_user_x509_cert_dl_cgi, do_auth }, 16455#endif /* __CONFIG_WAPI_IAS__ */ 16456#ifdef PLC 16457 { "plc.cgi*", "text/html", no_cache, BcmPostParse, do_plc_cgi, do_auth }, 16458 { "plc-restart.cgi*", "text/html", no_cache, BcmPostParse, do_plc_cgi_restart, do_auth }, 16459#endif 16460 { NULL, NULL, NULL, NULL, NULL, NULL } 16461}; 16462 16463struct ej_handler ej_handlers[] = { 16464 { "nvram_get", ej_nvram_get }, 16465 { "nvram_match", ej_nvram_match }, 16466 { "nvram_match_bitflag", ej_nvram_match_bitflag }, 16467 { "nvram_get_bitflag", ej_nvram_get_bitflag }, 16468 { "nvram_invmatch", ej_nvram_invmatch }, 16469 { "nvram_list", ej_nvram_list }, 16470 { "nvram_inlist", ej_nvram_inlist }, 16471 { "nvram_invinlist", ej_nvram_invinlist }, 16472 { "nvram_indexmatch", ej_nvram_indexmatch }, 16473#ifdef __CONFIG_HSPOT__ 16474 { "print_wl_wanmetrics", ej_print_wl_wanmetrics }, 16475 { "print_wl_oplist", ej_print_wl_oplist }, 16476 { "print_wl_homeqlist", ej_print_wl_homeqlist }, 16477 { "print_wl_concaplist", ej_print_wl_concaplist }, 16478 { "print_wl_osuplist", ej_print_wl_osuplist}, 16479 { "print_popup_osup", ej_print_popup_osup}, 16480 { "icon_change", ej_icon_change}, 16481 { "print_iconlist", ej_print_iconlist}, 16482 { "print_wl_qosmapie", ej_print_wl_qosmapie}, 16483 /* ---- 802.11u ----------------------------------- */ 16484 { "print_wl_netauthlist", ej_print_wl_netauthlist }, 16485 { "print_wl_realmlist", ej_print_wl_realmlist}, 16486 { "print_popup_realm", ej_print_popup_realm}, 16487 { "authid_change", ej_authid_change}, 16488 { "print_wl_venuegrp_type", ej_print_wl_venuegrp_type}, 16489 { "vanuegrp_change", ej_vanuegrp_change}, 16490 { "print_wl_venuelist", ej_print_wl_venuelist }, 16491 { "print_wl_ouilist", ej_print_wl_ouilist }, 16492 { "print_wl_3gpplist", ej_print_wl_3gpplist }, 16493#endif /* __CONFIG_HSPOT__ */ 16494#ifdef __CONFIG_NAT__ 16495 { "wan_list", ej_wan_list }, 16496 { "wan_iflist", ej_wan_iflist }, 16497 { "wan_route", ej_wan_route }, 16498 { "wan_link", ej_wan_link }, 16499 { "wan_lease", ej_wan_lease }, 16500 { "filter_client", ej_filter_client }, 16501 { "filter_url", ej_filter_url }, 16502 { "forward_port", ej_forward_port }, 16503 { "autofw_port_display", ej_autofw_port_display }, 16504#endif /* __CONFIG_NAT__ */ 16505 { "dfs_reentry_display", ej_dfs_reentry_display }, 16506 { "trf_mgmt_display", ej_trf_mgmt_display }, 16507 { "wps_psk_window_display", ej_wps_psk_window_display }, 16508 { "wps_current_psk_window_display", ej_wps_current_psk_window_display }, 16509 { "wps_config_change_display", ej_wps_config_change_display }, 16510 { "wps_display", ej_wps_display }, 16511 { "wps_closed_check_display", ej_wps_closed_check_display }, 16512 { "wps_wep_change_display", ej_wps_wep_change_display }, 16513 { "wps_security_pre_submit_display", ej_wps_security_pre_submit_display }, 16514 { "wps_get_ap_config_submit_display", ej_wps_get_ap_config_submit_display }, 16515 { "wps_akm_change_display", ej_wps_akm_change_display }, 16516 { "wps_refresh", ej_wps_refresh }, 16517 { "localtime", ej_localtime }, 16518 { "sysuptime", ej_sysuptime }, 16519 { "dumplog", ej_dumplog }, 16520 { "syslog", ej_syslog }, 16521#if defined(__CONFIG_DLNA_DMS__) 16522 { "get_mnt_path", ej_get_mnt_path }, 16523#endif 16524 { "wl_list", ej_wl_list }, 16525 { "wl_bssid_list", ej_wl_bssid_list}, 16526 { "wl_get_bridge", ej_wl_get_bridge}, 16527 { "wl_phytypes", ej_wl_phytypes }, 16528 { "wl_radioid", ej_wl_radioid }, 16529 { "wl_corerev", ej_wl_corerev }, 16530 { "wl_cur_chanspec", ej_wl_cur_chanspec }, 16531 { "wl_cur_channel", ej_wl_cur_channel }, 16532 { "wl_cur_bw", ej_wl_cur_bw }, 16533 { "wl_cur_nctrlsb", ej_wl_cur_nctrlsb }, 16534 { "wl_cur_phytype", ej_wl_cur_phytype }, 16535 { "wl_cur_regrev", ej_wl_cur_regrev }, /* add country_rev in config page */ 16536 { "wl_cur_country", ej_wl_cur_country }, 16537 { "wl_country_list", ej_wl_country_list }, 16538 { "wl_country_rev_list", ej_wl_country_rev_list }, /* add country_rev in config page */ 16539 { "wl_chanspec_list", ej_wl_chanspec_list }, 16540 { "wl_auth_list", ej_wl_auth_list }, 16541 { "wl_mode_list", ej_wl_mode_list }, 16542 { "wl_bw_cap_list", ej_wl_bw_cap_list}, 16543 { "wl_inlist", ej_wl_inlist }, 16544 { "wl_wds_status", ej_wl_wds_status }, 16545 { "wl_radio_roam_option", ej_wl_radio_roam_option}, 16546 { "wl_ure_list", ej_ure_list }, 16547 { "wl_ure_enabled", ej_ure_enabled }, 16548 { "wl_ure_any_enabled", ej_ure_any_enabled }, 16549 { "wl_ibss_mode", ej_wl_ibss_mode }, 16550 { "ses_button_display", ej_ses_button_display}, 16551 { "ses_cl_button_display", ej_ses_cl_button_display}, 16552 { "ses_wds_mode_list", ej_ses_wds_mode_list}, 16553 { "wl_nphyrates", ej_wl_nphyrates }, 16554 { "wl_txchains_list", ej_wl_txchains_list }, 16555 { "wl_rxchains_list", ej_wl_rxchains_list }, 16556 { "wl_cur_band", ej_wl_cur_band }, 16557 { "wl_nmode_enabled", ej_wl_nmode_enabled }, 16558 { "wl_nphy_set", ej_wl_nphy_set }, 16559 { "wl_nphy_comment_beg", ej_wl_nphy_comment_beg }, 16560 { "wl_nphy_comment_end", ej_wl_nphy_comment_end }, 16561 { "wl_phytype_name", ej_wl_phytype_name }, 16562 { "wl_protection", ej_wl_protection }, 16563 { "wl_mimo_preamble", ej_wl_mimo_preamble }, 16564 { "wl_legacy_string", ej_wl_legacy_string }, 16565 { "wl_crypto", ej_wl_crypto }, 16566 { "wl_wep", ej_wl_wep }, 16567 { "lan_route", ej_lan_route }, 16568 { "emf_enable_display", ej_emf_enable_display }, 16569 { "emf_entries_display", ej_emf_entries_display }, 16570 { "emf_uffp_entries_display", ej_emf_uffp_entries_display }, 16571 { "emf_rtport_entries_display", ej_emf_rtport_entries_display }, 16572 { "lan_guest_iflist", ej_lan_guest_iflist }, 16573 { "lan_leases", ej_lan_leases }, 16574 { "asp_list", ej_asp_list }, 16575 { "kernel_version", ej_kernel_version }, 16576#ifdef __CONFIG_WAPI_IAS__ 16577 { "as_cer_display", ej_as_cer_display }, 16578#endif 16579/* 16580*/ 16581#ifdef __CONFIG_WFI__ 16582 { "wl_invite_list", ej_wl_invite_list }, 16583 { "wl_wfi_mode", ej_wl_wfi_mode }, 16584#endif /* __CONFIG_WFI__ */ 16585/* 16586*/ 16587#ifdef PLC 16588 { "ggl_avln_list", ej_ggl_get_avln_list }, 16589 { "ggl_get_version", ej_ggl_cgi_version }, 16590 { "ggl_plc_get_autoconf_root", ej_ggl_plc_get_autoconf_root }, 16591 { "ggl_plc_get_info", ej_ggl_plc_get_info }, 16592 { "ggl_plc_get_mac", ej_ggl_plc_get_mac }, 16593 { "ggl_plc_get_nets", ej_ggl_plc_get_nets }, 16594 { "ggl_plc_get_nick", ej_ggl_plc_get_nick }, 16595 { "ggl_plc_get_role", ej_ggl_plc_get_role }, 16596 { "ggl_plc_get_stas", ej_ggl_plc_get_stas }, 16597 { "ggl_plc_get_uptime", ej_ggl_plc_get_uptime }, 16598#endif 16599 { "wl_auth_display", ej_wl_auth_display }, 16600 { "wet_tunnel_display", ej_wet_tunnel_display }, 16601#ifdef TRAFFIC_MGMT_RSSI_POLICY 16602 { "trf_mgmt_rssi_policy_display", ej_trf_mgmt_rssi_policy_display }, 16603#endif /* TRAFFIC_MGMT_RSSI_POLICY */ 16604 { "wl_txbf_capable", ej_wl_txbf_capable }, 16605 { "trf_mgmt_dwm_display", ej_trf_mgmt_dwm_display }, 16606 { NULL, NULL } 16607}; 16608 16609#endif /* !WEBS */ 16610 16611/* 16612 * Country names and abbreviations from ISO 3166 16613 */ 16614country_name_t country_names[] = { 16615 16616{"COUNTRY Z1", "Z1"}, 16617{"COUNTRY Z2", "Z2"}, 16618{"AFGHANISTAN", "AF"}, 16619{"ALBANIA", "AL"}, 16620{"ALGERIA", "DZ"}, 16621{"AMERICAN SAMOA", "AS"}, 16622{"ANDORRA", "AD"}, 16623{"ANGOLA", "AO"}, 16624{"ANGUILLA", "AI"}, 16625{"ANTARCTICA", "AQ"}, 16626{"ANTIGUA AND BARBUDA", "AG"}, 16627{"ARGENTINA", "AR"}, 16628{"ARMENIA", "AM"}, 16629{"ARUBA", "AW"}, 16630{"ASCENSION ISLAND", "AC"}, 16631{"ASHMORE AND BARBUDA", "AG"}, 16632{"AUSTRALIA", "AU"}, 16633{"AUSTRIA", "AT"}, 16634{"AZERBAIJAN", "AZ"}, 16635{"BAHAMAS", "BS"}, 16636{"BAHRAIN", "BH"}, 16637{"BAKER ISLAND", "Z2"}, 16638{"BANGLADESH", "BD"}, 16639{"BARBADOS", "BB"}, 16640{"BELARUS", "BY"}, 16641{"BELGIUM", "BE"}, 16642{"BELIZE", "BZ"}, 16643{"BENIN", "BJ"}, 16644{"BERMUDA", "BM"}, 16645{"BHUTAN", "BT"}, 16646{"BOLIVIA", "BO"}, 16647{"BOSNIA AND HERZEGOVINA","BA"}, 16648{"BOTSWANA", "BW"}, 16649{"BOUVET ISLAND", "BV"}, 16650{"BRAZIL", "BR"}, 16651{"BRITISH INDIAN OCEAN TERRITORY", "IO"}, 16652{"BRUNEI DARUSSALAM", "BN"}, 16653{"BULGARIA", "BG"}, 16654{"BURKINA FASO", "BF"}, 16655{"BURUNDI", "BI"}, 16656{"CAMBODIA", "KH"}, 16657{"CAMEROON", "CM"}, 16658{"CANADA", "CA"}, 16659{"CAPE VERDE", "CV"}, 16660{"CAYMAN ISLANDS", "KY"}, 16661{"CENTRAL AFRICAN REPUBLIC","CF"}, 16662{"CHAD", "TD"}, 16663{"CHANNEL ISLANDS", "Z1"}, 16664{"CHILE", "CL"}, 16665{"CHINA", "CN"}, 16666{"CHRISTMAS ISLAND", "CX"}, 16667{"CLIPPERTON ISLAND", "CP"}, 16668{"COCOS (KEELING) ISLANDS","CC"}, 16669{"COLOMBIA", "CO"}, 16670{"COMOROS", "KM"}, 16671{"CONGO", "CG"}, 16672{"CONGO, THE DEMOCRATIC REPUBLIC OF THE", "CD"}, 16673{"COOK ISLANDS", "CK"}, 16674{"COSTA RICA", "CR"}, 16675{"COTE D'IVOIRE", "CI"}, 16676{"CROATIA", "HR"}, 16677{"CUBA", "CU"}, 16678{"CYPRUS", "CY"}, 16679{"CZECH REPUBLIC", "CZ"}, 16680{"DENMARK", "DK"}, 16681{"DIEGO GARCIA", "Z1"}, 16682{"DJIBOUTI", "DJ"}, 16683{"DOMINICA", "DM"}, 16684{"DOMINICAN REPUBLIC", "DO"}, 16685{"ECUADOR", "EC"}, 16686{"EGYPT", "EG"}, 16687{"EL SALVADOR", "SV"}, 16688{"EQUATORIAL GUINEA", "GQ"}, 16689{"ERITREA", "ER"}, 16690{"ESTONIA", "EE"}, 16691{"ETHIOPIA", "ET"}, 16692{"FALKLAND ISLANDS (MALVINAS)", "FK"}, 16693{"FAROE ISLANDS", "FO"}, 16694{"FIJI", "FJ"}, 16695{"FINLAND", "FI"}, 16696{"FRANCE", "FR"}, 16697{"FRENCH GUIANA", "GF"}, 16698{"FRENCH POLYNESIA", "PF"}, 16699{"FRENCH SOUTHERN TERRITORIES", "TF"}, 16700{"GABON", "GA"}, 16701{"GAMBIA", "GM"}, 16702{"GEORGIA", "GE"}, 16703{"GERMANY", "DE"}, 16704{"GHANA", "GH"}, 16705{"GIBRALTAR", "GI"}, 16706{"GREECE", "GR"}, 16707{"GREENLAND", "GL"}, 16708{"GRENADA", "GD"}, 16709{"GUADELOUPE", "GP"}, 16710{"GUAM", "GU"}, 16711{"GUANTANAMO BAY", "Z1"}, 16712{"GUATEMALA", "GT"}, 16713{"GUERNSEY", "GG"}, 16714{"GUINEA", "GN"}, 16715{"GUINEA-BISSAU", "GW"}, 16716{"GUYANA", "GY"}, 16717{"HAITI", "HT"}, 16718{"HEARD ISLAND AND MCDONALD ISLANDS", "HM"}, 16719{"HOLY SEE (VATICAN CITY STATE)", "VA"}, 16720{"HONDURAS", "HN"}, 16721{"HONG KONG", "HK"}, 16722{"HOWLAND ISLAND", "Z2"}, 16723{"HUNGARY", "HU"}, 16724{"ICELAND", "IS"}, 16725{"INDIA", "IN"}, 16726{"INDONESIA", "ID"}, 16727{"IRAN, ISLAMIC REPUBLIC OF", "IR"}, 16728{"IRAQ", "IQ"}, 16729{"IRELAND", "IE"}, 16730{"ISRAEL", "IL"}, 16731{"ITALY", "IT"}, 16732{"JAMAICA", "JM"}, 16733{"JAN MAYEN AMAICA", "Z1"}, 16734{"JAPAN", "JP"}, 16735{"JAPAN_1", "J1"}, 16736{"JAPAN_2", "J2"}, 16737{"JAPAN_3", "J3"}, 16738{"JAPAN_4", "J4"}, 16739{"JAPAN_5", "J5"}, 16740{"JAPAN_6", "J6"}, 16741{"JAPAN_7", "J7"}, 16742{"JAPAN_8", "J8"}, 16743{"JARVIS ISLAND", "Z2"}, 16744{"JERSEY", "JE"}, 16745{"JOHNSTON ATOLL", "Z2"}, 16746{"JORDON", "JO"}, 16747{"KAZAKHSTAN", "KZ"}, 16748{"KENYA", "KE"}, 16749{"KINGMAN REEF", "Z2"}, 16750{"KIRIBATI", "KI"}, 16751{"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF", "KP"}, 16752{"KOREA, REPUBLIC OF", "KR"}, 16753{"KUWAIT", "KW"}, 16754{"KYRGYZSTAN", "KG"}, 16755{"LAO PEOPLE'S DEMOCRATIC REPUBLIC", "LA"}, 16756{"LATVIA", "LV"}, 16757{"LEBANON", "LB"}, 16758{"LESOTHO", "LS"}, 16759{"LIBERIA", "LR"}, 16760{"LIBYAN ARAB JAMAHIRIYA","LY"}, 16761{"LIECHTENSTEIN", "LI"}, 16762{"LITHUANIA", "LT"}, 16763{"LUXEMBOURG", "LU"}, 16764{"MACAO", "MO"}, 16765{"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF", "MK"}, 16766{"MADAGASCAR", "MG"}, 16767{"MALAWI", "MW"}, 16768{"MALAYSIA", "MY"}, 16769{"MALDIVES", "MV"}, 16770{"MALI", "ML"}, 16771{"MALTA", "MT"}, 16772{"MAN, ISLE OF", "IM"}, 16773{"MARSHALL ISLANDS", "MH"}, 16774{"MARTINIQUE", "MQ"}, 16775{"MAURITANIA", "MR"}, 16776{"MAURITIUS", "MU"}, 16777{"MAYOTTE", "YT"}, 16778{"MEXICO", "MX"}, 16779{"MICRONESIA, FEDERATED STATES OF", "FM"}, 16780{"MIDWAY ISLANDS", "Z2"}, 16781{"MOLDOVA, REPUBLIC OF", "MD"}, 16782{"MONACO", "MC"}, 16783{"MONGOLIA", "MN"}, 16784{"MONTSERRAT", "MS"}, 16785{"MOROCCO", "MA"}, 16786{"MOZAMBIQUE", "MZ"}, 16787{"MYANMAR", "MM"}, 16788{"NAMIBIA", "NA"}, 16789{"NAURU", "NR"}, 16790{"NEPAL", "NP"}, 16791{"NETHERLANDS", "NL"}, 16792{"NETHERLANDS ANTILLES", "AN"}, 16793{"NEW CALEDONIA", "NC"}, 16794{"NEW ZEALAND", "NZ"}, 16795{"NICARAGUA", "NI"}, 16796{"NIGER", "NE"}, 16797{"NIGERIA", "NG"}, 16798{"NIUE", "NU"}, 16799{"NORFOLK ISLAND", "NF"}, 16800{"NORTHERN MARIANA ISLANDS","MP"}, 16801{"NORWAY", "NO"}, 16802{"OMAN", "OM"}, 16803{"PAKISTAN", "PK"}, 16804{"PALAU", "PW"}, 16805{"PALESTINIAN TERRITORY, OCCUPIED", "PS"}, 16806{"PALMYRA ATOLL", "Z2"}, 16807{"PANAMA", "PA"}, 16808{"PAPUA NEW GUINEA", "PG"}, 16809{"PARAGUAY", "PY"}, 16810{"PERU", "PE"}, 16811{"PHILIPPINES", "PH"}, 16812{"PITCAIRN", "PN"}, 16813{"POLAND", "PL"}, 16814{"PORTUGAL", "PT"}, 16815{"PUERTO RICO", "PR"}, 16816{"QATAR", "QA"}, 16817{"Q1", "Q1"}, 16818{"REUNION", "RE"}, 16819{"ROMANIA", "RO"}, 16820{"ROTA ISLAND", "Z1"}, 16821{"RUSSIAN FEDERATION", "RU"}, 16822{"RWANDA", "RW"}, 16823{"SAINT HELENA", "SH"}, 16824{"SAINT KITTS AND NEVIS","KN"}, 16825{"SAINT LUCIA", "LC"}, 16826{"SAINT PIERRE AND MIQUELON", "PM"}, 16827{"SAINT VINCENT AND THE GRENADINES", "VC"}, 16828{"SAIPAN", "Z1"}, 16829{"SAMOA", "WS"}, 16830{"SAN MARINO", "SM"}, 16831{"SAO TOME AND PRINCIPE","ST"}, 16832{"SAUDI ARABIA", "SA"}, 16833{"SENEGAL", "SN"}, 16834{"SEYCHELLES", "SC"}, 16835{"SIERRA LEONE", "SL"}, 16836{"SINGAPORE", "SG"}, 16837{"SLOVAKIA", "SK"}, 16838{"SLOVENIA", "SI"}, 16839{"SOLOMON ISLANDS", "SB"}, 16840{"SOMALIA", "SO"}, 16841{"SOUTH AFRICA", "ZA"}, 16842{"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS", "GS"}, 16843{"SPAIN", "ES"}, 16844{"SRI LANKA", "LK"}, 16845{"SUDAN", "SD"}, 16846{"SURINAME", "SR"}, 16847{"SVALBARD AND JAN MAYEN","SJ"}, 16848{"SWAZILAND", "SZ"}, 16849{"SWEDEN", "SE"}, 16850{"SWITZERLAND", "CH"}, 16851{"SYRIAN ARAB REPUBLIC", "SY"}, 16852{"TAIWAN, PROVINCE OF CHINA", "TW"}, 16853{"TAJIKISTAN", "TJ"}, 16854{"TANZANIA, UNITED REPUBLIC OF", "TZ"}, 16855{"THAILAND", "TH"}, 16856{"TIMOR-LESTE", "TL"}, 16857{"TINIAN ISLAND", "Z1"}, 16858{"TOGO", "TG"}, 16859{"TOKELAU", "TK"}, 16860{"TONGA", "TO"}, 16861{"TRINIDAD AND TOBAGO", "TT"}, 16862{"TRISTAN DA CUNHA", "TA"}, 16863{"TUNISIA", "TN"}, 16864{"TURKEY", "TR"}, 16865{"TURKMENISTAN", "TM"}, 16866{"TURKS AND CAICOS ISLANDS", "TC"}, 16867{"TUVALU", "TV"}, 16868{"UGANDA", "UG"}, 16869{"UKRAINE", "UA"}, 16870{"UNITED ARAB EMIRATES", "AE"}, 16871{"UNITED KINGDOM", "GB"}, 16872{"UNITED STATES", "US"}, 16873{"UNITED STATES MINOR OUTLYING ISLANDS","UM"}, 16874{"URUGUAY", "UY"}, 16875{"UZBEKISTAN", "UZ"}, 16876{"VANUATU", "VU"}, 16877{"VENEZUELA", "VE"}, 16878{"VIET NAM", "VN"}, 16879{"VIRGIN ISLANDS, BRITISH", "VG"}, 16880{"VIRGIN ISLANDS, U.S.", "VI"}, 16881{"WAKE ISLAND", "Z1"}, 16882{"WALLIS AND FUTUNA", "WF"}, 16883{"WESTERN SAHARA", "EH"}, 16884{"YEMEN", "YE"}, 16885{"YUGOSLAVIA", "YU"}, 16886{"ZAMBIA", "ZM"}, 16887{"ZIMBABWE", "ZW"}, 16888{"ALL", "ALL"}, 16889{"RADAR CHANNELS", "RDR"}, 16890{"XA (EUROPE / APAC 2005)", "XA"}, 16891{"XB (NORTH AND SOUTH AMERICA AND TAIWAN)", "XB"}, 16892{"X0 (FCC WORLDWIDE)", "X0"}, 16893{"X1 (WORLDWIDE APAC)", "X1"}, 16894{"X2 (WORLDWIDE ROW 2)", "X2"}, 16895{"X3 (ETSI)", "X3"}, 16896{"EU (EUROPEAN UNION)", "EU"}, 16897{"XW (WORLDWIDE LOCALE FOR LINUX DRIVER)", "XW"}, 16898{"XX (WORLDWIDE LOCALE (PASSIVE Ch12-14))", "XX"}, 16899{"XY (FAKE COUNTRY CODE)", "XY"}, 16900{"XZ (WORLDWIDE LOCALE (PASSIVE Ch12-14))", "XZ"}, 16901{"XU (EUROPEAN LOCALE 0dBi ANTENNA IN 2.4GHz)", "XU"}, 16902{"XV (WORLDWIDE SAFE MODE LOCALE (PASSIVE Ch12-14))", "XV"}, 16903{"XT (SINGLE SKU fOR PC-OEMs)", "XT"}, 16904{NULL, NULL} 16905}; 16906